1 /***********************************************************************
2  * Copyright (c) 2013-2025 General Atomics Integrated Intelligence, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Apache License, Version 2.0
5  * which accompanies this distribution and is available at
6  * https://www.apache.org/licenses/LICENSE-2.0
7  ***********************************************************************/
8 
9 package org.locationtech.geomesa.features.kryo.json
10 
11 import com.esotericsoftware.kryo.io.{Input, Output}
12 import com.fasterxml.jackson.databind.JsonNode
13 import com.fasterxml.jackson.databind.node.{ArrayNode, ObjectNode}
14 import com.typesafe.scalalogging.LazyLogging
15 import org.locationtech.geomesa.features.kryo.json.JsonPathParser._
16 
17 import java.nio.charset.StandardCharsets
18 import scala.util.control.NonFatal
19 
20 /**
21  * Serializes into bson (https://bsonspec.org/). Note this is a limited form of bson that only matches
22  * the existing json types - does not cover the bson extensions like binary data, etc. Also note endianness,
23  * etc might not match the spec 100%.
24  *
25  * The bson serialized value is preceded by a single byte, `\x00` to indicate null, or `\x01` to indicate non-null.
26  * Additionally, non-document top-level values are supported, indicated with the prefix byte `\x02`. Top-level,
27  * non-document values are encoded as a jsonb `element` with an empty name.
28  *
29  * Reduced BSON spec - only native JSON elements supported:
30  *
31  * byte    1 byte (8-bits)
32  * int32   4 bytes (32-bit signed integer, two's complement)
33  * int64   8 bytes (64-bit signed integer, two's complement)
34  * double  8 bytes (64-bit IEEE 754-2008 binary floating point)
35  *
36  * document  ::= int32 e_list "\x00" BSON Document. int32 is the total number of bytes comprising the document.
37  * e_list    ::= element e_list
38  *           |	""
39  * element   ::= "\x01" e_name double	64-bit binary floating point
40  *           | "\x02" e_name string	UTF-8 string
41  *           | "\x03" e_name document	Embedded document
42  *           |	"\x04" e_name document	Array
43  *           |	"\x08" e_name "\x00"	Boolean "false"
44  *           |	"\x08" e_name "\x01"	Boolean "true"
45  *           |	"\x09" e_name int64	UTC datetime
46  *           |	"\x0A" e_name	Null value
47  *           |	"\x10" e_name int32	32-bit integer
48  *           |	"\x11" e_name int64	Timestamp
49  *           |	"\x12" e_name int64	64-bit integer
50  * e_name    ::= cstring	Key name
51  * string    ::= int32 (byte*) "\x00"	String - The int32 is the number bytes in the (byte*) + 1 (for the trailing '\x00').
52  *                                              The (byte*) is zero or more UTF-8 encoded characters.
53  * cstring   ::= (byte*) "\x00"	Zero or more modified UTF-8 encoded characters followed by '\x00'. The (byte*)
54  *                               MUST NOT contain '\x00', hence it is not full UTF-8.
55  *
56  * Note:
57  *   Array - The document for an array is a normal BSON document with integer values for the keys,
58  *   starting with 0 and continuing sequentially. For example, the array ['red', 'blue'] would be
59  *   encoded as the document {'0': 'red', '1': 'blue'}. The keys must be in ascending numerical order.
60  */
61 object KryoJsonSerialization extends LazyLogging {
62 
63   private[json] val TerminalByte :Byte = 0x00
64   private[json] val DoubleByte   :Byte = 0x01
65   private[json] val StringByte   :Byte = 0x02
66   private[json] val DocByte      :Byte = 0x03
67   private[json] val ArrayByte    :Byte = 0x04
68   private[json] val BooleanByte  :Byte = 0x08
69   private[json] val NullByte     :Byte = 0x0A
70   private[json] val IntByte      :Byte = 0x10
71   private[json] val LongByte     :Byte = 0x12
72 
73   private[json] val BooleanFalse :Byte = 0x00
74   private[json] val BooleanTrue  :Byte = 0x01
75   private[json] val NonDoc       :Byte = 0x02
76 
77   private val nameBuffers = new ThreadLocal[Array[Byte]] {
78     override def initialValue(): Array[Byte] = Array.ofDim[Byte](32)
79   }
80 
81   /**
82     * Serialize a json object
83     *
84     * @param out output to write to
85     * @param json json string to serialize - must be a json object
86     */
87   def serialize(out: Output, json: String): Unit = {
88     val obj = if (json == null) { null } else {
89       try {
90         mapper.readTree(json)
91       } catch {
92         case NonFatal(e) =>
93           logger.warn(s"Error parsing json:\n$json", e)
94           null
95       }
96     }
97     serialize(out, obj)
98   }
99 
100   /**
101     * Serialize a json object
102     *
103     * @param out output to write to
104     * @param json object to serialize
105     */
106   def serialize(out: Output, json: JsonNode): Unit = {
107     if (json == null || json.isNull) {
108       out.write(BooleanFalse)
109     } else if (json.isObject) {
110       out.write(BooleanTrue); writeDocument(out, json)
111     } else {
112       out.write(NonDoc); writeValue(out, "", json)
113     }
114   }
115 
116   /**
117     * Deserialize the given input. The input should be pointing to the start of
118     * the bytes written by `serialize`. Upon completion, the input will be pointing
119     * to the first byte after the bytes written by `serialize`.
120     *
121     * @param in input, pointing to the start of the json object
122     * @return json as a string
123     */
124   def deserializeAndRender(in: Input): String = {
125     val json = deserialize(in)
126     if (json == null) {
127       null
128     } else {
129       mapper.writeValueAsString(json)
130     }
131   }
132 
133   /**
134     * Deserialize the given input. The input should be pointing to the start of
135     * the bytes written by `serialize`. Upon completion, the input will be pointing
136     * to the first byte after the bytes written by `serialize`.
137     *
138     * @param in input, pointing to the start of the json object
139     * @return parsed json object
140     */
141   def deserialize(in: Input): JsonNode = {
142     try {
143       in.readByte match {
144         case BooleanFalse => null
145         case BooleanTrue  => readDocument(in: Input)
146         case NonDoc       => readValue(in)._2
147       }
148     } catch {
149       case NonFatal(e) => logger.error("Error reading serialized kryo json", e); null
150     }
151   }
152 
153   /**
154     * Deserialize the result of a json-path. The input should be pointing to the start of
155     * the bytes written by `serialize`. There is no guarantee where the input will be
156     * pointing after completion.
157     *
158     * If the path selects leaf elements, they will be returned as primitives. If the path
159     * selects objects, they will be returned as json strings. If more than one item is
160     * selected, they will be returned in a java.util.List. If nothing is selected, it will return null.
161     *
162     * @param in input, pointing to the start of the json object
163     * @param path pre-parsed json path to evaluate
164     * @return result of the path, if any
165     */
166   def deserialize(in: Input, path: JsonPath): Any = {
167     if (path.isEmpty) {
168       deserializeAndRender(in)
169     } else {
170       try { new KryoJsonPath(in).deserialize(path) } catch {
171         case NonFatal(e) => logger.error("Error reading serialized kryo json", e); null
172       }
173     }
174   }
175 
176   // primitive writing functions - in general will write a byte identifying the type, the key and then the value
177 
178   private def writeDocument(out: Output, name: String, value: JsonNode): Unit = {
179     out.writeByte(DocByte)
180     out.writeName(name)
181     writeDocument(out, value)
182   }
183 
184   // write a document without a name - used for the outermost object which doesn't have a key
185   private def writeDocument(out: Output, value: JsonNode): Unit = {
186     val start = out.position()
187     // write a placeholder that we will overwrite when we go back to write total length
188     // note: don't just modify position, as that doesn't expand the buffer correctly
189     out.writeInt(0)
190     value.forEachEntry { case (name, elem) => writeValue(out, name, elem) }
191     out.writeByte(TerminalByte) // marks the end of our object
192     // go back and write the total length
193     val end = out.position()
194     out.setPosition(start)
195     out.writeInt(end - start)
196     out.setPosition(end)
197   }
198 
199   private def writeValue(out: Output, name: String, value: JsonNode): Unit = {
200     if (value.isTextual || value.isBinary) {
201       writeString(out, name, value.asText())
202     } else if (value.isObject) {
203       writeDocument(out, name, value)
204     } else if (value.isArray) {
205       writeArray(out, name, value)
206     } else if (value.isDouble || value.isFloat) {
207       writeDouble(out, name, value.asDouble())
208     } else if (value.isInt || value.isShort) {
209       writeInt(out, name, value.intValue())
210     } else if (value.isLong) {
211       writeLong(out, name, value.longValue())
212     } else if (value.isNull) {
213       writeNull(out, name)
214     } else if (value.isBoolean) {
215       writeBoolean(out, name, value.booleanValue())
216     } else if (value.isBigDecimal) {
217       writeDouble(out, name, value.asDouble())
218     } else if (value.isBigInteger) {
219       if (value.canConvertToInt) {
220         writeInt(out, name, value.intValue())
221       } else if (value.canConvertToLong) {
222         writeLong(out, name, value.longValue())
223       } else {
224         logger.warn(s"Skipping int value that does not fit in a long: $value")
225       }
226     } else {
227       logger.warn(s"Unhandled JsonNode: $value")
228     }
229   }
230 
231   private def writeArray(out: Output, name: String, value: JsonNode): Unit = {
232     out.writeByte(ArrayByte)
233     out.writeName(name)
234     // we store as an object where array index is the key
235     var i = 0
236     val obj = mapper.createObjectNode()
237     while (i < value.size()) {
238       obj.set(i.toString, value.get(i))
239       i += 1
240     }
241     writeDocument(out, obj)
242   }
243 
244   private def writeString(out: Output, name: String, value: String): Unit = {
245     out.writeByte(StringByte)
246     out.writeName(name)
247     val bytes = value.getBytes(StandardCharsets.UTF_8)
248     out.writeInt(bytes.length)
249     out.write(bytes)
250     out.writeByte(TerminalByte)
251   }
252 
253   private def writeDouble(out: Output, name: String, value: Double): Unit = {
254     out.writeByte(DoubleByte)
255     out.writeName(name)
256     out.writeDouble(value)
257   }
258 
259   private def writeInt(out: Output, name: String, value: Int): Unit = {
260     out.writeByte(IntByte)
261     out.writeName(name)
262     out.writeInt(value)
263   }
264 
265   private def writeLong(out: Output, name: String, value: Long): Unit = {
266     out.writeByte(LongByte)
267     out.writeName(name)
268     out.writeLong(value)
269   }
270 
271   private def writeBoolean(out: Output, name: String, value: Boolean): Unit = {
272     out.writeByte(BooleanByte)
273     out.writeName(name)
274     out.writeByte(if (value) BooleanTrue else BooleanFalse)
275   }
276 
277   private def writeNull(out: Output, name: String): Unit = {
278     out.writeByte(NullByte)
279     out.writeName(name)
280   }
281 
282   // primitive reading/skipping methods corresponding to the write methods above
283   // assumes that the indicator byte and name have already been read
284 
285   private[json] def readDocument(in: Input): ObjectNode = {
286     val end = in.position() + in.readInt() - 1 // last byte is the terminal byte
287     val obj = mapper.createObjectNode()
288     while (in.position() < end) {
289       val (k, v) = readValue(in)
290       obj.set(k, v)
291     }
292     in.skip(1) // skip over terminal byte
293     obj
294   }
295 
296   private[json] def readValue(in: Input): (String, JsonNode) = {
297     val switch = in.readByte()
298     val name = in.readName()
299     val value = switch match {
300       case StringByte   => mapper.getNodeFactory.textNode(readString(in))
301       case DocByte      => readDocument(in)
302       case ArrayByte    => readArray(in)
303       case DoubleByte   => mapper.getNodeFactory.numberNode(in.readDouble())
304       case IntByte      => mapper.getNodeFactory.numberNode(in.readInt())
305       case LongByte     => mapper.getNodeFactory.numberNode(in.readLong())
306       case NullByte     => mapper.getNodeFactory.nullNode()
307       case BooleanByte  => mapper.getNodeFactory.booleanNode(readBoolean(in))
308     }
309     (name, value)
310   }
311 
312   private[json] def readArray(in: Input): ArrayNode = {
313     val obj = readDocument(in)
314     val array = mapper.getNodeFactory.arrayNode(obj.size())
315     obj.forEachEntry { case (_, v) => array.add(v) }
316     array
317   }
318 
319   private[json] def skipDocument(in: Input): Unit = in.skip(in.readInt - 4) // length includes bytes storing length
320 
321   private[json] def readString(in: Input): String = {
322     val bytes = Array.ofDim[Byte](in.readInt())
323     in.read(bytes)
324     in.skip(1) // skip TerminalByte
325     new String(bytes, StandardCharsets.UTF_8)
326   }
327 
328   private[json] def skipString(in: Input): Unit = in.skip(in.readInt() + 1) // skip TerminalByte
329 
330   private[json] def readBoolean(in: Input): Boolean = in.readByte == BooleanTrue
331 
332   private[json] def skipBoolean(in: Input): Unit = in.skip(1)
333 
334   private[json] implicit class RichOutput(val out: Output) extends AnyRef {
335     def writeName(name: String): Unit = {
336       // note: names are not allowed to contain the terminal byte (0x00) but we don't check for it
337       out.write(name.getBytes(StandardCharsets.UTF_8))
338       out.writeByte(TerminalByte)
339     }
340   }
341 
342   private[json] implicit class RichInput(val in: Input) extends AnyRef {
343     def readName(): String = {
344       var buffer = nameBuffers.get()
345       var i = 0
346       var byte: Byte = in.readByte()
347       while (byte != TerminalByte) {
348         if (i == buffer.length) {
349           // expand our cached buffer to accommodate the name
350           val copy = Array.ofDim[Byte](buffer.length * 2)
351           System.arraycopy(buffer, 0, copy, 0, i)
352           buffer = copy
353           nameBuffers.set(buffer)
354         }
355         buffer(i) = byte
356         i += 1
357         byte = in.readByte()
358       }
359       new String(buffer, 0, i, StandardCharsets.UTF_8)
360     }
361 
362     def skipName(): Unit = while (in.readByte() != TerminalByte) {}
363   }
364 }
Line Stmt Id Pos Tree Symbol Tests Code
63 3532 3300 - 3304 Literal <nosymbol> 0
64 3533 3346 - 3350 Literal <nosymbol> 1
65 3534 3392 - 3396 Literal <nosymbol> 2
66 3535 3438 - 3442 Literal <nosymbol> 3
67 3536 3484 - 3488 Literal <nosymbol> 4
68 3537 3530 - 3534 Literal <nosymbol> 8
69 3538 3576 - 3580 Literal <nosymbol> 10
70 3539 3622 - 3626 Literal <nosymbol> 16
71 3540 3668 - 3672 Literal <nosymbol> 18
73 3541 3715 - 3719 Literal <nosymbol> 0
74 3542 3761 - 3765 Literal <nosymbol> 1
75 3543 3807 - 3811 Literal <nosymbol> 2
77 3546 3841 - 3844 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.$anon.<init> new $anon()
78 3544 3937 - 3939 Literal <nosymbol> 32
78 3545 3919 - 3940 ApplyToImplicitArgs scala.Array.ofDim scala.Array.ofDim[Byte](32)((ClassTag.Byte: scala.reflect.ClassTag[Byte]))
88 3547 4169 - 4181 Apply java.lang.Object.== json.==(null)
88 3548 4185 - 4189 Literal <nosymbol> null
88 3549 4185 - 4189 Block <nosymbol> null
89 3554 4205 - 4363 Try <nosymbol> try { json.this.`package`.mapper.readTree(json) } catch { case scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _)) => { (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn(scala.StringContext.apply("Error parsing json:\\n", "").s(json), e) else (): Unit); null } }
90 3550 4219 - 4240 Apply com.fasterxml.jackson.databind.ObjectMapper.readTree json.this.`package`.mapper.readTree(json)
90 3551 4219 - 4240 Block com.fasterxml.jackson.databind.ObjectMapper.readTree json.this.`package`.mapper.readTree(json)
92 3553 4282 - 4355 Block <nosymbol> { (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn(scala.StringContext.apply("Error parsing json:\\n", "").s(json), e) else (): Unit); null }
94 3552 4351 - 4355 Literal <nosymbol> null
97 3555 4374 - 4393 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.serialize KryoJsonSerialization.this.serialize(out, obj)
107 3556 4593 - 4597 Literal <nosymbol> null
107 3557 4601 - 4612 Apply com.fasterxml.jackson.databind.JsonNode.isNull json.isNull()
107 3558 4585 - 4612 Apply scala.Boolean.|| json.==(null).||(json.isNull())
108 3559 4632 - 4644 Select scala.Byte.toInt KryoJsonSerialization.this.BooleanFalse.toInt
108 3560 4622 - 4645 Apply com.esotericsoftware.kryo.io.Output.write out.write(KryoJsonSerialization.this.BooleanFalse.toInt)
108 3561 4622 - 4645 Block com.esotericsoftware.kryo.io.Output.write out.write(KryoJsonSerialization.this.BooleanFalse.toInt)
109 3562 4661 - 4674 Apply com.fasterxml.jackson.databind.JsonNode.isObject json.isObject()
109 3566 4676 - 4738 Block <nosymbol> { out.write(KryoJsonSerialization.this.BooleanTrue.toInt); KryoJsonSerialization.this.writeDocument(out, json) }
109 3571 4657 - 4802 If <nosymbol> if (json.isObject()) { out.write(KryoJsonSerialization.this.BooleanTrue.toInt); KryoJsonSerialization.this.writeDocument(out, json) } else { out.write(KryoJsonSerialization.this.NonDoc.toInt); KryoJsonSerialization.this.writeValue(out, "", json) }
110 3563 4694 - 4705 Select scala.Byte.toInt KryoJsonSerialization.this.BooleanTrue.toInt
110 3564 4684 - 4706 Apply com.esotericsoftware.kryo.io.Output.write out.write(KryoJsonSerialization.this.BooleanTrue.toInt)
110 3565 4708 - 4732 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeDocument KryoJsonSerialization.this.writeDocument(out, json)
111 3570 4744 - 4802 Block <nosymbol> { out.write(KryoJsonSerialization.this.NonDoc.toInt); KryoJsonSerialization.this.writeValue(out, "", json) }
112 3567 4762 - 4768 Select scala.Byte.toInt KryoJsonSerialization.this.NonDoc.toInt
112 3568 4752 - 4769 Apply com.esotericsoftware.kryo.io.Output.write out.write(KryoJsonSerialization.this.NonDoc.toInt)
112 3569 4771 - 4796 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeValue KryoJsonSerialization.this.writeValue(out, "", json)
125 3572 5215 - 5230 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.deserialize KryoJsonSerialization.this.deserialize(in)
126 3573 5239 - 5251 Apply java.lang.Object.== json.==(null)
127 3574 5261 - 5265 Literal <nosymbol> null
127 3575 5261 - 5265 Block <nosymbol> null
129 3576 5285 - 5316 Apply com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString json.this.`package`.mapper.writeValueAsString(json)
129 3577 5285 - 5316 Block com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString json.this.`package`.mapper.writeValueAsString(json)
143 3578 5731 - 5742 Apply com.esotericsoftware.kryo.io.Input.readByte in.readByte()
143 3585 5731 - 5891 Match <nosymbol> in.readByte() match { case KryoJsonSerialization.this.BooleanFalse => null case KryoJsonSerialization.this.BooleanTrue => KryoJsonSerialization.this.readDocument((in: com.esotericsoftware.kryo.io.Input)) case KryoJsonSerialization.this.NonDoc => KryoJsonSerialization.this.readValue(in)._2 }
144 3579 5780 - 5784 Literal <nosymbol> null
144 3580 5780 - 5784 Block <nosymbol> null
145 3581 5814 - 5837 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.readDocument KryoJsonSerialization.this.readDocument((in: com.esotericsoftware.kryo.io.Input))
145 3582 5814 - 5837 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.readDocument KryoJsonSerialization.this.readDocument((in: com.esotericsoftware.kryo.io.Input))
146 3583 5867 - 5883 Select scala.Tuple2._2 KryoJsonSerialization.this.readValue(in)._2
146 3584 5867 - 5883 Block scala.Tuple2._2 KryoJsonSerialization.this.readValue(in)._2
149 3586 5987 - 5991 Literal <nosymbol> null
149 3587 5929 - 5991 Block <nosymbol> { (if (KryoJsonSerialization.this.logger.underlying.isErrorEnabled()) KryoJsonSerialization.this.logger.underlying.error("Error reading serialized kryo json", e) else (): Unit); null }
167 3588 6736 - 6748 Select org.locationtech.geomesa.features.kryo.json.JsonPathParser.JsonPath.isEmpty path.isEmpty
168 3589 6758 - 6782 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.deserializeAndRender KryoJsonSerialization.this.deserializeAndRender(in)
168 3590 6758 - 6782 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.deserializeAndRender KryoJsonSerialization.this.deserializeAndRender(in)
170 3591 6808 - 6846 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonPath.deserialize new KryoJsonPath(in).deserialize(path)
170 3592 6808 - 6846 Block org.locationtech.geomesa.features.kryo.json.KryoJsonPath.deserialize new KryoJsonPath(in).deserialize(path)
170 3595 6802 - 6952 Try <nosymbol> try { new KryoJsonPath(in).deserialize(path) } catch { case scala.util.control.NonFatal.unapply(<unapply-selector>) <unapply> ((e @ _)) => { (if (KryoJsonSerialization.this.logger.underlying.isErrorEnabled()) KryoJsonSerialization.this.logger.underlying.error("Error reading serialized kryo json", e) else (): Unit); null } }
171 3593 6940 - 6944 Literal <nosymbol> null
171 3594 6882 - 6944 Block <nosymbol> { (if (KryoJsonSerialization.this.logger.underlying.isErrorEnabled()) KryoJsonSerialization.this.logger.underlying.error("Error reading serialized kryo json", e) else (): Unit); null }
179 3596 7178 - 7185 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.DocByte KryoJsonSerialization.this.DocByte
179 3597 7164 - 7186 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(KryoJsonSerialization.this.DocByte)
180 3598 7191 - 7210 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichOutput.writeName KryoJsonSerialization.this.RichOutput(out).writeName(name)
181 3599 7215 - 7240 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeDocument KryoJsonSerialization.this.writeDocument(out, value)
186 3600 7424 - 7438 Apply com.esotericsoftware.kryo.io.Output.position out.position()
189 3601 7616 - 7631 Apply com.esotericsoftware.kryo.io.Output.writeInt out.writeInt(0)
190 3602 7678 - 7705 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeValue KryoJsonSerialization.this.writeValue(out, name, elem)
190 3603 7678 - 7705 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeValue KryoJsonSerialization.this.writeValue(out, name, elem)
190 3604 7636 - 7707 Apply com.fasterxml.jackson.databind.JsonNode.forEachEntry value.forEachEntry(((x0$1: String, x1$1: com.fasterxml.jackson.databind.JsonNode) => scala.Tuple2.apply[String, com.fasterxml.jackson.databind.JsonNode](x0$1, x1$1) match { case (_1: String, _2: com.fasterxml.jackson.databind.JsonNode)(String, com.fasterxml.jackson.databind.JsonNode)((name @ _), (elem @ _)) => KryoJsonSerialization.this.writeValue(out, name, elem) }))
191 3605 7726 - 7738 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.TerminalByte KryoJsonSerialization.this.TerminalByte
191 3606 7712 - 7739 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(KryoJsonSerialization.this.TerminalByte)
193 3607 7827 - 7841 Apply com.esotericsoftware.kryo.io.Output.position out.position()
194 3608 7846 - 7868 Apply com.esotericsoftware.kryo.io.Output.setPosition out.setPosition(start)
195 3609 7886 - 7897 Apply scala.Int.- end.-(start)
195 3610 7873 - 7898 Apply com.esotericsoftware.kryo.io.Output.writeInt out.writeInt(end.-(start))
196 3611 7903 - 7923 Apply com.esotericsoftware.kryo.io.Output.setPosition out.setPosition(end)
200 3612 8035 - 8049 Apply com.fasterxml.jackson.databind.JsonNode.isBinary value.isBinary()
200 3613 8016 - 8049 Apply scala.Boolean.|| value.isTextual().||(value.isBinary())
201 3614 8082 - 8096 Apply com.fasterxml.jackson.databind.JsonNode.asText value.asText()
201 3615 8059 - 8097 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeString KryoJsonSerialization.this.writeString(out, name, value.asText())
201 3616 8059 - 8097 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeString KryoJsonSerialization.this.writeString(out, name, value.asText())
202 3617 8113 - 8127 Apply com.fasterxml.jackson.databind.JsonNode.isObject value.isObject()
202 3669 8109 - 9107 If <nosymbol> if (value.isObject()) KryoJsonSerialization.this.writeDocument(out, name, value) else if (value.isArray()) KryoJsonSerialization.this.writeArray(out, name, value) else if (value.isDouble().||(value.isFloat())) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isInt().||(value.isShort())) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.isLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else if (value.isNull()) KryoJsonSerialization.this.writeNull(out, name) else if (value.isBoolean()) KryoJsonSerialization.this.writeBoolean(out, name, value.booleanValue()) else if (value.isBigDecimal()) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isBigInteger()) if (value.canConvertToInt()) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Unhandled JsonNode: {}", (value: AnyRef)) else (): Unit)
203 3618 8137 - 8168 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeDocument KryoJsonSerialization.this.writeDocument(out, name, value)
203 3619 8137 - 8168 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeDocument KryoJsonSerialization.this.writeDocument(out, name, value)
204 3620 8184 - 8197 Apply com.fasterxml.jackson.databind.JsonNode.isArray value.isArray()
204 3668 8180 - 9107 If <nosymbol> if (value.isArray()) KryoJsonSerialization.this.writeArray(out, name, value) else if (value.isDouble().||(value.isFloat())) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isInt().||(value.isShort())) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.isLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else if (value.isNull()) KryoJsonSerialization.this.writeNull(out, name) else if (value.isBoolean()) KryoJsonSerialization.this.writeBoolean(out, name, value.booleanValue()) else if (value.isBigDecimal()) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isBigInteger()) if (value.canConvertToInt()) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Unhandled JsonNode: {}", (value: AnyRef)) else (): Unit)
205 3621 8207 - 8235 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeArray KryoJsonSerialization.this.writeArray(out, name, value)
205 3622 8207 - 8235 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeArray KryoJsonSerialization.this.writeArray(out, name, value)
206 3623 8269 - 8282 Apply com.fasterxml.jackson.databind.JsonNode.isFloat value.isFloat()
206 3624 8251 - 8282 Apply scala.Boolean.|| value.isDouble().||(value.isFloat())
206 3667 8247 - 9107 If <nosymbol> if (value.isDouble().||(value.isFloat())) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isInt().||(value.isShort())) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.isLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else if (value.isNull()) KryoJsonSerialization.this.writeNull(out, name) else if (value.isBoolean()) KryoJsonSerialization.this.writeBoolean(out, name, value.booleanValue()) else if (value.isBigDecimal()) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isBigInteger()) if (value.canConvertToInt()) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Unhandled JsonNode: {}", (value: AnyRef)) else (): Unit)
207 3625 8315 - 8331 Apply com.fasterxml.jackson.databind.JsonNode.asDouble value.asDouble()
207 3626 8292 - 8332 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeDouble KryoJsonSerialization.this.writeDouble(out, name, value.asDouble())
207 3627 8292 - 8332 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeDouble KryoJsonSerialization.this.writeDouble(out, name, value.asDouble())
208 3628 8363 - 8376 Apply com.fasterxml.jackson.databind.JsonNode.isShort value.isShort()
208 3629 8348 - 8376 Apply scala.Boolean.|| value.isInt().||(value.isShort())
208 3666 8344 - 9107 If <nosymbol> if (value.isInt().||(value.isShort())) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.isLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else if (value.isNull()) KryoJsonSerialization.this.writeNull(out, name) else if (value.isBoolean()) KryoJsonSerialization.this.writeBoolean(out, name, value.booleanValue()) else if (value.isBigDecimal()) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isBigInteger()) if (value.canConvertToInt()) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Unhandled JsonNode: {}", (value: AnyRef)) else (): Unit)
209 3630 8406 - 8422 Apply com.fasterxml.jackson.databind.JsonNode.intValue value.intValue()
209 3631 8386 - 8423 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeInt KryoJsonSerialization.this.writeInt(out, name, value.intValue())
209 3632 8386 - 8423 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeInt KryoJsonSerialization.this.writeInt(out, name, value.intValue())
210 3633 8439 - 8451 Apply com.fasterxml.jackson.databind.JsonNode.isLong value.isLong()
210 3665 8435 - 9107 If <nosymbol> if (value.isLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else if (value.isNull()) KryoJsonSerialization.this.writeNull(out, name) else if (value.isBoolean()) KryoJsonSerialization.this.writeBoolean(out, name, value.booleanValue()) else if (value.isBigDecimal()) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isBigInteger()) if (value.canConvertToInt()) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Unhandled JsonNode: {}", (value: AnyRef)) else (): Unit)
211 3634 8482 - 8499 Apply com.fasterxml.jackson.databind.JsonNode.longValue value.longValue()
211 3635 8461 - 8500 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeLong KryoJsonSerialization.this.writeLong(out, name, value.longValue())
211 3636 8461 - 8500 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeLong KryoJsonSerialization.this.writeLong(out, name, value.longValue())
212 3637 8516 - 8528 Apply com.fasterxml.jackson.databind.JsonNode.isNull value.isNull()
212 3664 8512 - 9107 If <nosymbol> if (value.isNull()) KryoJsonSerialization.this.writeNull(out, name) else if (value.isBoolean()) KryoJsonSerialization.this.writeBoolean(out, name, value.booleanValue()) else if (value.isBigDecimal()) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isBigInteger()) if (value.canConvertToInt()) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Unhandled JsonNode: {}", (value: AnyRef)) else (): Unit)
213 3638 8538 - 8558 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeNull KryoJsonSerialization.this.writeNull(out, name)
213 3639 8538 - 8558 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeNull KryoJsonSerialization.this.writeNull(out, name)
214 3640 8574 - 8589 Apply com.fasterxml.jackson.databind.JsonNode.isBoolean value.isBoolean()
214 3663 8570 - 9107 If <nosymbol> if (value.isBoolean()) KryoJsonSerialization.this.writeBoolean(out, name, value.booleanValue()) else if (value.isBigDecimal()) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isBigInteger()) if (value.canConvertToInt()) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Unhandled JsonNode: {}", (value: AnyRef)) else (): Unit)
215 3641 8623 - 8643 Apply com.fasterxml.jackson.databind.JsonNode.booleanValue value.booleanValue()
215 3642 8599 - 8644 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeBoolean KryoJsonSerialization.this.writeBoolean(out, name, value.booleanValue())
215 3643 8599 - 8644 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeBoolean KryoJsonSerialization.this.writeBoolean(out, name, value.booleanValue())
216 3644 8660 - 8678 Apply com.fasterxml.jackson.databind.JsonNode.isBigDecimal value.isBigDecimal()
216 3662 8656 - 9107 If <nosymbol> if (value.isBigDecimal()) KryoJsonSerialization.this.writeDouble(out, name, value.asDouble()) else if (value.isBigInteger()) if (value.canConvertToInt()) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Unhandled JsonNode: {}", (value: AnyRef)) else (): Unit)
217 3645 8711 - 8727 Apply com.fasterxml.jackson.databind.JsonNode.asDouble value.asDouble()
217 3646 8688 - 8728 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeDouble KryoJsonSerialization.this.writeDouble(out, name, value.asDouble())
217 3647 8688 - 8728 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeDouble KryoJsonSerialization.this.writeDouble(out, name, value.asDouble())
218 3648 8744 - 8762 Apply com.fasterxml.jackson.databind.JsonNode.isBigInteger value.isBigInteger()
218 3661 8740 - 9107 If <nosymbol> if (value.isBigInteger()) if (value.canConvertToInt()) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Unhandled JsonNode: {}", (value: AnyRef)) else (): Unit)
219 3649 8776 - 8797 Apply com.fasterxml.jackson.databind.JsonNode.canConvertToInt value.canConvertToInt()
219 3659 8772 - 9039 If <nosymbol> if (value.canConvertToInt()) KryoJsonSerialization.this.writeInt(out, name, value.intValue()) else if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit)
220 3650 8829 - 8845 Apply com.fasterxml.jackson.databind.JsonNode.intValue value.intValue()
220 3651 8809 - 8846 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeInt KryoJsonSerialization.this.writeInt(out, name, value.intValue())
220 3652 8809 - 8846 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeInt KryoJsonSerialization.this.writeInt(out, name, value.intValue())
221 3653 8864 - 8886 Apply com.fasterxml.jackson.databind.JsonNode.canConvertToLong value.canConvertToLong()
221 3658 8860 - 9039 If <nosymbol> if (value.canConvertToLong()) KryoJsonSerialization.this.writeLong(out, name, value.longValue()) else (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit)
222 3654 8919 - 8936 Apply com.fasterxml.jackson.databind.JsonNode.longValue value.longValue()
222 3655 8898 - 8937 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeLong KryoJsonSerialization.this.writeLong(out, name, value.longValue())
222 3656 8898 - 8937 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeLong KryoJsonSerialization.this.writeLong(out, name, value.longValue())
224 3657 8961 - 9031 Typed <nosymbol> (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Skipping int value that does not fit in a long: {}", (value: AnyRef)) else (): Unit)
227 3660 9059 - 9101 Typed <nosymbol> (if (KryoJsonSerialization.this.logger.underlying.isWarnEnabled()) KryoJsonSerialization.this.logger.underlying.warn("Unhandled JsonNode: {}", (value: AnyRef)) else (): Unit)
232 3670 9210 - 9219 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.ArrayByte KryoJsonSerialization.this.ArrayByte
232 3671 9196 - 9220 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(KryoJsonSerialization.this.ArrayByte)
233 3672 9225 - 9244 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichOutput.writeName KryoJsonSerialization.this.RichOutput(out).writeName(name)
235 3673 9315 - 9316 Literal <nosymbol> 0
236 3674 9331 - 9356 Apply com.fasterxml.jackson.databind.ObjectMapper.createObjectNode json.this.`package`.mapper.createObjectNode()
237 3675 9372 - 9384 Apply com.fasterxml.jackson.databind.JsonNode.size value.size()
237 3676 9368 - 9384 Apply scala.Int.< i.<(value.size())
237 3681 9386 - 9386 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.while$1 while$1()
237 3682 9386 - 9446 Block <nosymbol> { { obj.set[Nothing](i.toString(), value.get(i)); i = i.+(1) }; while$1() }
237 3683 9361 - 9361 Literal <nosymbol> ()
237 3684 9361 - 9361 Block <nosymbol> ()
238 3677 9402 - 9412 Apply scala.Any.toString i.toString()
238 3678 9414 - 9426 Apply com.fasterxml.jackson.databind.JsonNode.get value.get(i)
238 3679 9394 - 9427 Apply com.fasterxml.jackson.databind.node.ObjectNode.set obj.set[Nothing](i.toString(), value.get(i))
239 3680 9434 - 9440 Apply scala.Int.+ i.+(1)
241 3685 9451 - 9474 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.writeDocument KryoJsonSerialization.this.writeDocument(out, obj)
245 3686 9576 - 9586 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.StringByte KryoJsonSerialization.this.StringByte
245 3687 9562 - 9587 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(KryoJsonSerialization.this.StringByte)
246 3688 9592 - 9611 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichOutput.writeName KryoJsonSerialization.this.RichOutput(out).writeName(name)
247 3689 9643 - 9665 Select java.nio.charset.StandardCharsets.UTF_8 java.nio.charset.StandardCharsets.UTF_8
247 3690 9628 - 9666 Apply java.lang.String.getBytes value.getBytes(java.nio.charset.StandardCharsets.UTF_8)
248 3691 9684 - 9696 Select scala.Array.length bytes.length
248 3692 9671 - 9697 Apply com.esotericsoftware.kryo.io.Output.writeInt out.writeInt(bytes.length)
249 3693 9702 - 9718 Apply com.esotericsoftware.kryo.io.Output.write out.write(bytes)
250 3694 9737 - 9749 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.TerminalByte KryoJsonSerialization.this.TerminalByte
250 3695 9723 - 9750 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(KryoJsonSerialization.this.TerminalByte)
254 3696 9852 - 9862 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.DoubleByte KryoJsonSerialization.this.DoubleByte
254 3697 9838 - 9863 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(KryoJsonSerialization.this.DoubleByte)
255 3698 9868 - 9887 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichOutput.writeName KryoJsonSerialization.this.RichOutput(out).writeName(name)
256 3699 9892 - 9914 Apply com.esotericsoftware.kryo.io.Output.writeDouble out.writeDouble(value)
260 3700 10010 - 10017 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.IntByte KryoJsonSerialization.this.IntByte
260 3701 9996 - 10018 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(KryoJsonSerialization.this.IntByte)
261 3702 10023 - 10042 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichOutput.writeName KryoJsonSerialization.this.RichOutput(out).writeName(name)
262 3703 10047 - 10066 Apply com.esotericsoftware.kryo.io.Output.writeInt out.writeInt(value)
266 3704 10164 - 10172 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.LongByte KryoJsonSerialization.this.LongByte
266 3705 10150 - 10173 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(KryoJsonSerialization.this.LongByte)
267 3706 10178 - 10197 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichOutput.writeName KryoJsonSerialization.this.RichOutput(out).writeName(name)
268 3707 10202 - 10222 Apply com.esotericsoftware.kryo.io.Output.writeLong out.writeLong(value)
272 3708 10326 - 10337 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.BooleanByte KryoJsonSerialization.this.BooleanByte
272 3709 10312 - 10338 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(KryoJsonSerialization.this.BooleanByte)
273 3710 10343 - 10362 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichOutput.writeName KryoJsonSerialization.this.RichOutput(out).writeName(name)
274 3711 10392 - 10403 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.BooleanTrue KryoJsonSerialization.this.BooleanTrue
274 3712 10392 - 10403 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.BooleanTrue KryoJsonSerialization.this.BooleanTrue
274 3713 10409 - 10421 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.BooleanFalse KryoJsonSerialization.this.BooleanFalse
274 3714 10409 - 10421 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.BooleanFalse KryoJsonSerialization.this.BooleanFalse
274 3715 10367 - 10422 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(if (value) KryoJsonSerialization.this.BooleanTrue else KryoJsonSerialization.this.BooleanFalse)
278 3716 10507 - 10515 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.NullByte KryoJsonSerialization.this.NullByte
278 3717 10493 - 10516 Apply com.esotericsoftware.kryo.io.Output.writeByte out.writeByte(KryoJsonSerialization.this.NullByte)
279 3718 10521 - 10540 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichOutput.writeName KryoJsonSerialization.this.RichOutput(out).writeName(name)
286 3719 10771 - 10803 Apply scala.Int.- in.position().+(in.readInt()).-(1)
287 3720 10852 - 10877 Apply com.fasterxml.jackson.databind.ObjectMapper.createObjectNode json.this.`package`.mapper.createObjectNode()
288 3721 10889 - 10908 Apply scala.Int.< in.position().<(end)
288 3725 10910 - 10910 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.while$2 while$2()
288 3726 10910 - 10970 Block <nosymbol> { { <synthetic> <artifact> private[this] val x$1: (String, com.fasterxml.jackson.databind.JsonNode) = (KryoJsonSerialization.this.readValue(in): (String, com.fasterxml.jackson.databind.JsonNode) @unchecked) match { case (_1: String, _2: com.fasterxml.jackson.databind.JsonNode)(String, com.fasterxml.jackson.databind.JsonNode)((k @ _), (v @ _)) => scala.Tuple2.apply[String, com.fasterxml.jackson.databind.JsonNode](k, v) }; val k: String = x$1._1; val v: com.fasterxml.jackson.databind.JsonNode = x$1._2; obj.set[Nothing](k, v) }; while$2() }
288 3727 10882 - 10882 Literal <nosymbol> ()
288 3728 10882 - 10882 Block <nosymbol> ()
289 3722 10923 - 10923 Select scala.Tuple2._1 x$1._1
289 3723 10926 - 10926 Select scala.Tuple2._2 x$1._2
290 3724 10951 - 10964 Apply com.fasterxml.jackson.databind.node.ObjectNode.set obj.set[Nothing](k, v)
292 3729 10975 - 10985 Apply com.esotericsoftware.kryo.io.Input.skip in.skip(1)
297 3730 11108 - 11121 Apply com.esotericsoftware.kryo.io.Input.readByte in.readByte()
298 3731 11137 - 11150 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichInput.readName KryoJsonSerialization.this.RichInput(in).readName()
300 3732 11240 - 11254 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.readString KryoJsonSerialization.this.readString(in)
300 3733 11209 - 11255 Apply com.fasterxml.jackson.databind.node.JsonNodeFactory.textNode json.this.`package`.mapper.getNodeFactory().textNode(KryoJsonSerialization.this.readString(in))
300 3734 11209 - 11255 Block com.fasterxml.jackson.databind.node.JsonNodeFactory.textNode json.this.`package`.mapper.getNodeFactory().textNode(KryoJsonSerialization.this.readString(in))
301 3735 11283 - 11299 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.readDocument KryoJsonSerialization.this.readDocument(in)
301 3736 11283 - 11299 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.readDocument KryoJsonSerialization.this.readDocument(in)
302 3737 11327 - 11340 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.readArray KryoJsonSerialization.this.readArray(in)
302 3738 11327 - 11340 Block org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.readArray KryoJsonSerialization.this.readArray(in)
303 3739 11401 - 11416 Apply com.esotericsoftware.kryo.io.Input.readDouble in.readDouble()
303 3740 11368 - 11417 Apply com.fasterxml.jackson.databind.node.JsonNodeFactory.numberNode json.this.`package`.mapper.getNodeFactory().numberNode(in.readDouble())
303 3741 11368 - 11417 Block com.fasterxml.jackson.databind.node.JsonNodeFactory.numberNode json.this.`package`.mapper.getNodeFactory().numberNode(in.readDouble())
304 3742 11478 - 11490 Apply com.esotericsoftware.kryo.io.Input.readInt in.readInt()
304 3743 11445 - 11491 Apply com.fasterxml.jackson.databind.node.JsonNodeFactory.numberNode json.this.`package`.mapper.getNodeFactory().numberNode(in.readInt())
304 3744 11445 - 11491 Block com.fasterxml.jackson.databind.node.JsonNodeFactory.numberNode json.this.`package`.mapper.getNodeFactory().numberNode(in.readInt())
305 3745 11552 - 11565 Apply com.esotericsoftware.kryo.io.Input.readLong in.readLong()
305 3746 11519 - 11566 Apply com.fasterxml.jackson.databind.node.JsonNodeFactory.numberNode json.this.`package`.mapper.getNodeFactory().numberNode(in.readLong())
305 3747 11519 - 11566 Block com.fasterxml.jackson.databind.node.JsonNodeFactory.numberNode json.this.`package`.mapper.getNodeFactory().numberNode(in.readLong())
306 3748 11594 - 11626 Apply com.fasterxml.jackson.databind.node.JsonNodeFactory.nullNode json.this.`package`.mapper.getNodeFactory().nullNode()
306 3749 11594 - 11626 Block com.fasterxml.jackson.databind.node.JsonNodeFactory.nullNode json.this.`package`.mapper.getNodeFactory().nullNode()
307 3750 11688 - 11703 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.readBoolean KryoJsonSerialization.this.readBoolean(in)
307 3751 11654 - 11704 Apply com.fasterxml.jackson.databind.node.JsonNodeFactory.booleanNode json.this.`package`.mapper.getNodeFactory().booleanNode(KryoJsonSerialization.this.readBoolean(in))
307 3752 11654 - 11704 Block com.fasterxml.jackson.databind.node.JsonNodeFactory.booleanNode json.this.`package`.mapper.getNodeFactory().booleanNode(KryoJsonSerialization.this.readBoolean(in))
309 3753 11715 - 11728 Apply scala.Tuple2.apply scala.Tuple2.apply[String, com.fasterxml.jackson.databind.node.BaseJsonNode{def findParent(x$1: String): com.fasterxml.jackson.databind.node.ObjectNode}](name, value)
313 3754 11804 - 11820 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.readDocument KryoJsonSerialization.this.readDocument(in)
314 3755 11869 - 11879 Apply com.fasterxml.jackson.databind.node.ObjectNode.size obj.size()
314 3756 11837 - 11880 Apply com.fasterxml.jackson.databind.node.JsonNodeFactory.arrayNode json.this.`package`.mapper.getNodeFactory().arrayNode(obj.size())
315 3757 11919 - 11931 Apply com.fasterxml.jackson.databind.node.ArrayNode.add array.add(v)
315 3758 11928 - 11928 Literal <nosymbol> ()
315 3759 11919 - 11931 Block <nosymbol> { array.add(v); () }
315 3760 11885 - 11933 Apply com.fasterxml.jackson.databind.node.ObjectNode.forEachEntry obj.forEachEntry(((x0$1: String, x1$1: com.fasterxml.jackson.databind.JsonNode) => scala.Tuple2.apply[String, com.fasterxml.jackson.databind.JsonNode](x0$1, x1$1) match { case (_1: String, _2: com.fasterxml.jackson.databind.JsonNode)(String, com.fasterxml.jackson.databind.JsonNode)(_, (v @ _)) => { array.add(v); () } }))
319 3761 12009 - 12023 Apply scala.Int.- in.readInt().-(4)
319 3762 12001 - 12024 Apply com.esotericsoftware.kryo.io.Input.skip in.skip(in.readInt().-(4))
322 3763 12154 - 12166 Apply com.esotericsoftware.kryo.io.Input.readInt in.readInt()
322 3764 12136 - 12167 ApplyToImplicitArgs scala.Array.ofDim scala.Array.ofDim[Byte](in.readInt())((ClassTag.Byte: scala.reflect.ClassTag[Byte]))
323 3765 12172 - 12186 Apply com.esotericsoftware.kryo.io.Input.read in.read(bytes)
324 3766 12191 - 12201 Apply com.esotericsoftware.kryo.io.Input.skip in.skip(1)
325 3767 12245 - 12267 Select java.nio.charset.StandardCharsets.UTF_8 java.nio.charset.StandardCharsets.UTF_8
325 3768 12227 - 12268 Apply java.lang.String.<init> new scala.Predef.String(bytes, java.nio.charset.StandardCharsets.UTF_8)
328 3769 12332 - 12348 Apply scala.Int.+ in.readInt().+(1)
328 3770 12324 - 12349 Apply com.esotericsoftware.kryo.io.Input.skip in.skip(in.readInt().+(1))
330 3771 12441 - 12452 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.BooleanTrue KryoJsonSerialization.this.BooleanTrue
330 3772 12426 - 12452 Apply scala.Byte.== in.readByte().==(KryoJsonSerialization.this.BooleanTrue)
332 3773 12505 - 12515 Apply com.esotericsoftware.kryo.io.Input.skip in.skip(1)
337 3774 12764 - 12786 Select java.nio.charset.StandardCharsets.UTF_8 java.nio.charset.StandardCharsets.UTF_8
337 3775 12750 - 12787 Apply java.lang.String.getBytes name.getBytes(java.nio.charset.StandardCharsets.UTF_8)
337 3776 12740 - 12788 Apply com.esotericsoftware.kryo.io.Output.write RichOutput.this.out.write(name.getBytes(java.nio.charset.StandardCharsets.UTF_8))
338 3777 12809 - 12821 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.TerminalByte KryoJsonSerialization.this.TerminalByte
338 3778 12795 - 12822 Apply com.esotericsoftware.kryo.io.Output.writeByte RichOutput.this.out.writeByte(KryoJsonSerialization.this.TerminalByte)
344 3779 12957 - 12974 Apply java.lang.ThreadLocal.get KryoJsonSerialization.this.nameBuffers.get()
345 3780 12989 - 12990 Literal <nosymbol> 0
346 3781 13014 - 13027 Apply com.esotericsoftware.kryo.io.Input.readByte RichInput.this.in.readByte()
347 3782 13049 - 13061 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.TerminalByte KryoJsonSerialization.this.TerminalByte
347 3783 13041 - 13061 Apply scala.Byte.!= byte.!=(KryoJsonSerialization.this.TerminalByte)
347 3796 13063 - 13063 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichInput.while$3 while$3()
347 3797 13063 - 13413 Block <nosymbol> { { if (i.==(buffer.length)) { val copy: Array[Byte] = scala.Array.ofDim[Byte](buffer.length.*(2))((ClassTag.Byte: scala.reflect.ClassTag[Byte])); java.lang.System.arraycopy(buffer, 0, copy, 0, i); buffer = copy; KryoJsonSerialization.this.nameBuffers.set(buffer) } else (); buffer.update(i, byte); i = i.+(1); byte = RichInput.this.in.readByte() }; while$3() }
347 3798 13034 - 13034 Literal <nosymbol> ()
347 3799 13034 - 13034 Block <nosymbol> ()
348 3784 13082 - 13095 Select scala.Array.length buffer.length
348 3785 13077 - 13095 Apply scala.Int.== i.==(buffer.length)
348 3790 13097 - 13336 Block <nosymbol> { val copy: Array[Byte] = scala.Array.ofDim[Byte](buffer.length.*(2))((ClassTag.Byte: scala.reflect.ClassTag[Byte])); java.lang.System.arraycopy(buffer, 0, copy, 0, i); buffer = copy; KryoJsonSerialization.this.nameBuffers.set(buffer) }
348 3791 13073 - 13073 Literal <nosymbol> ()
348 3792 13073 - 13073 Block <nosymbol> ()
350 3786 13200 - 13217 Apply scala.Int.* buffer.length.*(2)
350 3787 13182 - 13218 ApplyToImplicitArgs scala.Array.ofDim scala.Array.ofDim[Byte](buffer.length.*(2))((ClassTag.Byte: scala.reflect.ClassTag[Byte]))
351 3788 13229 - 13268 Apply java.lang.System.arraycopy java.lang.System.arraycopy(buffer, 0, copy, 0, i)
353 3789 13303 - 13326 Apply java.lang.ThreadLocal.set KryoJsonSerialization.this.nameBuffers.set(buffer)
355 3793 13345 - 13361 Apply scala.Array.update buffer.update(i, byte)
356 3794 13370 - 13376 Apply scala.Int.+ i.+(1)
357 3795 13392 - 13405 Apply com.esotericsoftware.kryo.io.Input.readByte RichInput.this.in.readByte()
359 3800 13439 - 13440 Literal <nosymbol> 0
359 3801 13445 - 13467 Select java.nio.charset.StandardCharsets.UTF_8 java.nio.charset.StandardCharsets.UTF_8
359 3802 13420 - 13468 Apply java.lang.String.<init> new scala.Predef.String(buffer, 0, i, java.nio.charset.StandardCharsets.UTF_8)
362 3803 13527 - 13539 Select org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.TerminalByte KryoJsonSerialization.this.TerminalByte
362 3804 13510 - 13539 Apply scala.Byte.!= RichInput.this.in.readByte().!=(KryoJsonSerialization.this.TerminalByte)
362 3805 13541 - 13543 Literal <nosymbol> ()
362 3806 13541 - 13541 Apply org.locationtech.geomesa.features.kryo.json.KryoJsonSerialization.RichInput.while$4 while$4()
362 3807 13541 - 13543 Block <nosymbol> { (); while$4() }
362 3808 13503 - 13503 Literal <nosymbol> ()
362 3809 13503 - 13503 Block <nosymbol> ()