• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright 2021 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 @file:Suppress("NOTHING_TO_INLINE")
17 @file:JvmName("FlexBuffers")
18 package com.google.flatbuffers.kotlin
19 
20 import kotlin.jvm.JvmName
21 
22 /**
23  * Reads a FlexBuffer message in ReadBuf and returns [Reference] to
24  * the root element.
25  * @param buffer ReadBuf containing FlexBuffer message
26  * @return [Reference] to the root object
27  */
28 public fun getRoot(buffer: ReadBuffer): Reference {
29   var end: Int = buffer.limit
30   val byteWidth = buffer[--end].toInt()
31   val packetType = buffer[--end].toInt()
32   end -= byteWidth // The root data item.
33   return Reference(buffer, end, ByteWidth(byteWidth), packetType)
34 }
35 
36 /**
37  * Represents an generic element in the buffer. It can be specialized into scalar types, using for example,
38  * [Reference.toInt], or casted into Flexbuffer object types, like [Reference.toMap] or [Reference.toBlob].
39  */
40 @Suppress("NOTHING_TO_INLINE")
41 public class Reference internal constructor(
42   internal val buffer: ReadBuffer,
43   internal val end: Int,
44   internal val parentWidth: ByteWidth,
45   internal val byteWidth: ByteWidth,
46   internal val type: FlexBufferType
47 ) {
48 
49   internal constructor(bb: ReadBuffer, end: Int, parentWidth: ByteWidth, packedType: Int) :
50     this(bb, end, parentWidth, ByteWidth(1 shl (packedType and 3)), FlexBufferType((packedType shr 2)))
51 
52   /**
53    * Checks whether the element is null type
54    * @return true if null type
55    */
56   public val isNull: Boolean get() = type == T_NULL
57 
58   /**
59    * Checks whether the element is boolean type
60    * @return true if boolean type
61    */
62   public val isBoolean: Boolean get() = type == T_BOOL
63 
64   /**
65    * Checks whether the element type is numeric (signed/unsigned integers and floats)
66    * @return true if numeric type
67    */
68   public val isNumeric: Boolean get() = isIntOrUInt || isFloat
69 
70   /**
71    * Checks whether the element type is signed or unsigned integers
72    * @return true if an integer type
73    */
74   public val isIntOrUInt: Boolean get() = isInt || isUInt
75 
76   /**
77    * Checks whether the element type is float
78    * @return true if a float type
79    */
80   public val isFloat: Boolean get() = type == T_FLOAT || type == T_INDIRECT_FLOAT
81 
82   /**
83    * Checks whether the element type is signed integer
84    * @return true if a signed integer type
85    */
86   public val isInt: Boolean get() = type == T_INT || type == T_INDIRECT_INT
87 
88   /**
89    * Checks whether the element type is signed integer
90    * @return true if a signed integer type
91    */
92   public val isUInt: Boolean get() = type == T_UINT || type == T_INDIRECT_UINT
93 
94   /**
95    * Checks whether the element type is string
96    * @return true if a string type
97    */
98   public val isString: Boolean get() = type == T_STRING
99 
100   /**
101    * Checks whether the element type is key
102    * @return true if a key type
103    */
104   public val isKey: Boolean get() = type == T_KEY
105 
106   /**
107    * Checks whether the element type is vector or a map. [TypedVector] are considered different types and will return
108    * false.
109    * @return true if a vector type
110    */
111   public val isVector: Boolean get() = type == T_VECTOR || type == T_MAP
112 
113   /**
114    * Checks whether the element type is typed vector
115    * @return true if a typed vector type
116    */
117   public val isTypedVector: Boolean get() = type.isTypedVector()
118 
119   /**
120    * Checks whether the element type is a map
121    * @return true if a map type
122    */
123   public val isMap: Boolean get() = type == T_MAP
124 
125   /**
126    * Checks whether the element type is a blob
127    * @return true if a blob type
128    */
129   public val isBlob: Boolean get() = type == T_BLOB
130 
131   /**
132    * Assumes [Reference] as a [Vector] and returns a [Reference] at index [index].
133    */
getnull134   public operator fun get(index: Int): Reference = toVector()[index]
135 
136   /**
137    * Assumes [Reference] as a [Map] and returns a [Reference] for the value at key [key].
138    */
139   public operator fun get(key: String): Reference = toMap()[key]
140 
141   /**
142    * Returns element as a [Boolean].
143    * If element type is not boolean, it will be casted to integer and compared against 0
144    * @return element as [Boolean]
145    */
146   public fun toBoolean(): Boolean = if (isBoolean) buffer.getBoolean(end) else toUInt() != 0u
147 
148   /**
149    * Returns element as [Byte].
150    *  For vector types, it will return size of the vector.
151    *  For String type, it will be parsed as integer.
152    *  Unsigned elements will become signed (with possible overflow).
153    *  Float elements will be casted to [Byte].
154    * @return [Byte] or 0 if fail to convert element to integer.
155    */
156   public fun toByte(): Byte = toULong().toByte()
157 
158   /**
159    * Returns element as [Short].
160    *  For vector types, it will return size of the vector.
161    *  For String type, it will type to be parsed as integer.
162    *  Unsigned elements will become signed (with possible overflow).
163    *  Float elements will be casted to [Short]
164    * @return [Short] or 0 if fail to convert element to integer.
165    */
166   public fun toShort(): Short = toULong().toShort()
167 
168   /**
169    * Returns element as [Int].
170    *  For vector types, it will return size of the vector.
171    *  For String type, it will type to be parsed as integer.
172    *  Unsigned elements will become signed (with possible overflow).
173    *  Float elements will be casted to [Int]
174    * @return [Int] or 0 if fail to convert element to integer.
175    */
176   public fun toInt(): Int = toULong().toInt()
177 
178   /**
179    * Returns element as [Long].
180    * For vector types, it will return size of the vector
181    * For String type, it will type to be parsed as integer
182    * Unsigned elements will become negative
183    * Float elements will be casted to integer
184    * @return [Long] integer or 0 if fail to convert element to long.
185    */
186   public fun toLong(): Long = toULong().toLong()
187 
188   /**
189    * Returns element as [UByte].
190    *  For vector types, it will return size of the vector.
191    *  For String type, it will type to be parsed as integer.
192    *  Negative elements will become unsigned counterpart.
193    *  Float elements will be casted to [UByte]
194    * @return [UByte] or 0 if fail to convert element to integer.
195    */
196   public fun toUByte(): UByte = toULong().toUByte()
197 
198   /**
199    * Returns element as [UShort].
200    *  For vector types, it will return size of the vector.
201    *  For String type, it will type to be parsed as integer.
202    *  Negative elements will become unsigned counterpart.
203    *  Float elements will be casted to [UShort]
204    * @return [UShort] or 0 if fail to convert element to integer.
205    */
206   public fun toUShort(): UShort = toULong().toUShort()
207 
208   /**
209    * Returns element as [UInt].
210    *  For vector types, it will return size of the vector.
211    *  For String type, it will type to be parsed as integer.
212    *  Negative elements will become unsigned counterpart.
213    *  Float elements will be casted to [UInt]
214    * @return [UInt] or 0 if fail to convert element to integer.
215    */
216   public fun toUInt(): UInt = toULong().toUInt()
217 
218   /**
219    * Returns element as  [ULong] integer.
220    * For vector types, it will return size of the vector
221    * For String type, it will type to be parsed as integer
222    * Negative elements will become unsigned counterpart.
223    * Float elements will be casted to integer
224    * @return [ULong] integer or 0 if fail to convert element to long.
225    */
226   public fun toULong(): ULong = resolve { pos: Int, width: ByteWidth ->
227     when (type) {
228       T_INDIRECT_INT, T_INDIRECT_UINT, T_INT, T_BOOL, T_UINT -> buffer.readULong(pos, width)
229       T_FLOAT, T_INDIRECT_FLOAT -> buffer.readFloat(pos, width).toULong()
230       T_STRING -> toString().toULong()
231       T_VECTOR -> toVector().size.toULong()
232       else -> 0UL
233     }
234   }
235 
236   /**
237    * Returns element as  [Float].
238    * For vector types, it will return size of the vector
239    * For String type, it will type to be parsed as [Float]
240    * Float elements will be casted to integer
241    * @return [Float] integer or 0 if fail to convert element to long.
242    */
posnull243   public fun toFloat(): Float = resolve { pos: Int, width: ByteWidth ->
244     when (type) {
245       T_INDIRECT_FLOAT, T_FLOAT -> buffer.readFloat(pos, width).toFloat()
246       T_INT -> buffer.readInt(end, parentWidth).toFloat()
247       T_UINT, T_BOOL -> buffer.readUInt(end, parentWidth).toFloat()
248       T_INDIRECT_INT -> buffer.readInt(pos, width).toFloat()
249       T_INDIRECT_UINT -> buffer.readUInt(pos, width).toFloat()
250       T_NULL -> 0.0f
251       T_STRING -> toString().toFloat()
252       T_VECTOR -> toVector().size.toFloat()
253       else -> 0f
254     }
255   }
256 
257   /**
258    * Returns element as  [Double].
259    * For vector types, it will return size of the vector
260    * For String type, it will type to be parsed as [Double]
261    * @return [Float] integer or 0 if fail to convert element to long.
262    */
toDoublenull263   public fun toDouble(): Double = resolve { pos: Int, width: ByteWidth ->
264     when (type) {
265       T_INDIRECT_FLOAT, T_FLOAT -> buffer.readFloat(pos, width)
266       T_INT -> buffer.readInt(pos, width).toDouble()
267       T_UINT, T_BOOL -> buffer.readUInt(pos, width).toDouble()
268       T_INDIRECT_INT -> buffer.readInt(pos, width).toDouble()
269       T_INDIRECT_UINT -> buffer.readUInt(pos, width).toDouble()
270       T_NULL -> 0.0
271       T_STRING -> toString().toDouble()
272       T_VECTOR -> toVector().size.toDouble()
273       else -> 0.0
274     }
275   }
276 
277   /**
278    * Returns element as [Key] or invalid key.
279    */
toKeynull280   public fun toKey(): Key = when (type) {
281     T_KEY -> Key(buffer, buffer.indirect(end, parentWidth))
282     else -> nullKey()
283   }
284   /**
285    * Returns element as a [String]
286    * @return element as [String] or empty [String] if fail
287    */
toStringnull288   override fun toString(): String = when (type) {
289     T_STRING -> {
290       val start = buffer.indirect(end, parentWidth)
291       val size = buffer.readULong(start - byteWidth, byteWidth).toInt()
292       buffer.getString(start, size)
293     }
294     T_KEY -> buffer.getKeyString(buffer.indirect(end, parentWidth))
295     T_MAP -> "{ ${toMap().entries.joinToString(", ") { "${it.key}: ${it.value}"}} }"
296     T_VECTOR, T_VECTOR_BOOL, T_VECTOR_FLOAT, T_VECTOR_INT,
297     T_VECTOR_UINT, T_VECTOR_KEY, T_VECTOR_STRING_DEPRECATED -> "[ ${toVector().joinToString(", ") { it.toString() }} ]"
298     T_INT -> toLong().toString()
299     T_UINT -> toULong().toString()
300     T_FLOAT -> toDouble().toString()
301     else -> "${type.typeToString()}(end=$end)"
302   }
303 
304   /**
305    * Returns element as a [ByteArray], converting scalar types when possible.
306    * @return element as [ByteArray] or empty [ByteArray] if fail.
307    */
toByteArraynull308   public fun toByteArray(): ByteArray {
309     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
310     return when (type) {
311       T_VECTOR_INT -> ByteArray(vec.size) { vec.getInt(it).toByte() }
312       T_VECTOR_UINT -> ByteArray(vec.size) { vec.getUInt(it).toByte() }
313       T_VECTOR -> ByteArray(vec.size) { vec[it].toByte() }
314       T_VECTOR_FLOAT -> ByteArray(vec.size) { vec.getFloat(it).toInt().toByte() }
315       else -> ByteArray(0)
316     }
317   }
318 
319   /**
320    * Returns element as a [ByteArray], converting scalar types when possible.
321    * @return element as [ByteArray] or empty [ByteArray] if fail.
322    */
toShortArraynull323   public fun toShortArray(): ShortArray {
324     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
325     return when (type) {
326       T_VECTOR_INT -> ShortArray(vec.size) { vec.getInt(it).toShort() }
327       T_VECTOR_UINT -> ShortArray(vec.size) { vec.getUInt(it).toShort() }
328       T_VECTOR -> ShortArray(vec.size) { vec[it].toShort() }
329       T_VECTOR_FLOAT -> ShortArray(vec.size) { vec.getFloat(it).toInt().toShort() }
330       else -> ShortArray(0)
331     }
332   }
333 
334   /**
335    * Returns element as a [IntArray], converting scalar types when possible.
336    * @return element as [IntArray] or empty [IntArray] if fail.
337    */
toIntArraynull338   public fun toIntArray(): IntArray {
339     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
340     return when (type) {
341       T_VECTOR_INT -> IntArray(vec.size) { vec.getInt(it).toInt() }
342       T_VECTOR_UINT -> IntArray(vec.size) { vec.getUInt(it).toInt() }
343       T_VECTOR -> IntArray(vec.size) { vec[it].toInt() }
344       T_VECTOR_FLOAT -> IntArray(vec.size) { vec.getFloat(it).toInt() }
345       else -> IntArray(0)
346     }
347   }
348 
349   /**
350    * Returns element as a [LongArray], converting scalar types when possible.
351    * @return element as [LongArray] or empty [LongArray] if fail.
352    */
toLongArraynull353   public fun toLongArray(): LongArray {
354     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
355     return when (type) {
356       T_VECTOR_INT -> LongArray(vec.size) { vec.getInt(it) }
357       T_VECTOR_UINT -> LongArray(vec.size) { vec.getInt(it) }
358       T_VECTOR -> LongArray(vec.size) { vec[it].toLong() }
359       T_VECTOR_FLOAT -> LongArray(vec.size) { vec.getFloat(it).toLong() }
360       else -> LongArray(0)
361     }
362   }
363 
364   /**
365    * Returns element as a [UByteArray], converting scalar types when possible.
366    * @return element as [UByteArray] or empty [UByteArray] if fail.
367    */
toUByteArraynull368   public fun toUByteArray(): UByteArray {
369     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
370     return when (type) {
371       T_VECTOR_INT -> UByteArray(vec.size) { vec.getInt(it).toUByte() }
372       T_VECTOR_UINT -> UByteArray(vec.size) { vec.getUInt(it).toUByte() }
373       T_VECTOR -> UByteArray(vec.size) { vec[it].toUByte() }
374       T_VECTOR_FLOAT -> UByteArray(vec.size) { vec.getFloat(it).toInt().toUByte() }
375       else -> UByteArray(0)
376     }
377   }
378 
379   /**
380    * Returns element as a [UIntArray], converting scalar types when possible.
381    * @return element as [UIntArray] or empty [UIntArray] if fail.
382    */
toUShortArraynull383   public fun toUShortArray(): UShortArray {
384     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
385     return when (type) {
386       T_VECTOR_INT -> UShortArray(vec.size) { vec.getInt(it).toUShort() }
387       T_VECTOR_UINT -> UShortArray(vec.size) { vec.getUInt(it).toUShort() }
388       T_VECTOR -> UShortArray(vec.size) { vec[it].toUShort() }
389       T_VECTOR_FLOAT -> UShortArray(vec.size) { vec.getFloat(it).toUInt().toUShort() }
390       else -> UShortArray(0)
391     }
392   }
393 
394   /**
395    * Returns element as a [UIntArray], converting scalar types when possible.
396    * @return element as [UIntArray] or empty [UIntArray] if fail.
397    */
toUIntArraynull398   public fun toUIntArray(): UIntArray {
399     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
400     return when (type) {
401       T_VECTOR_INT -> UIntArray(vec.size) { vec.getInt(it).toUInt() }
402       T_VECTOR_UINT -> UIntArray(vec.size) { vec.getUInt(it).toUInt() }
403       T_VECTOR -> UIntArray(vec.size) { vec[it].toUInt() }
404       T_VECTOR_FLOAT -> UIntArray(vec.size) { vec.getFloat(it).toUInt() }
405       else -> UIntArray(0)
406     }
407   }
408 
409   /**
410    * Returns element as a [ULongArray], converting scalar types when possible.
411    * @return element as [ULongArray] or empty [ULongArray] if fail.
412    */
toULongArraynull413   public fun toULongArray(): ULongArray {
414     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
415     return when (type) {
416       T_VECTOR_INT -> ULongArray(vec.size) { vec.getUInt(it) }
417       T_VECTOR_UINT -> ULongArray(vec.size) { vec.getUInt(it) }
418       T_VECTOR -> ULongArray(vec.size) { vec[it].toULong() }
419       T_VECTOR_FLOAT -> ULongArray(vec.size) { vec.getFloat(it).toULong() }
420       else -> ULongArray(0)
421     }
422   }
423 
424   /**
425    * Returns element as a [FloatArray], converting scalar types when possible.
426    * @return element as [FloatArray] or empty [FloatArray] if fail.
427    */
toFloatArraynull428   public fun toFloatArray(): FloatArray {
429     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
430     return when (type) {
431       T_VECTOR_FLOAT -> FloatArray(vec.size) { vec.getFloat(it).toFloat() }
432       T_VECTOR_INT -> FloatArray(vec.size) { vec.getInt(it).toFloat() }
433       T_VECTOR_UINT -> FloatArray(vec.size) { vec.getUInt(it).toFloat() }
434       T_VECTOR -> FloatArray(vec.size) { vec[it].toFloat() }
435       else -> FloatArray(0)
436     }
437   }
438 
439   /**
440    * Returns element as a [DoubleArray], converting scalar types when possible.
441    * @return element as [DoubleArray] or empty [DoubleArray] if fail.
442    */
toDoubleArraynull443   public fun toDoubleArray(): DoubleArray {
444     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
445     return when (type) {
446       T_VECTOR_FLOAT -> DoubleArray(vec.size) { vec[it].toDouble() }
447       T_VECTOR_INT -> DoubleArray(vec.size) { vec[it].toDouble() }
448       T_VECTOR_UINT -> DoubleArray(vec.size) { vec[it].toDouble() }
449       T_VECTOR -> DoubleArray(vec.size) { vec[it].toDouble() }
450       else -> DoubleArray(0)
451     }
452   }
453 
454   /**
455    * Returns element as a [Vector]
456    * @return element as [Vector] or empty [Vector] if fail
457    */
toVectornull458   public fun toVector(): Vector {
459     return when {
460       isVector -> Vector(buffer, buffer.indirect(end, parentWidth), byteWidth)
461       isTypedVector -> TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
462       else -> emptyVector()
463     }
464   }
465 
466   /**
467    * Returns element as a [Blob]
468    * @return element as [Blob] or empty [Blob] if fail
469    */
toBlobnull470   public fun toBlob(): Blob {
471     return when (type) {
472       T_BLOB, T_STRING -> Blob(buffer, buffer.indirect(end, parentWidth), byteWidth)
473       else -> emptyBlob()
474     }
475   }
476 
477   /**
478    * Returns element as a [Map].
479    * @return element as [Map] or empty [Map] if fail
480    */
toMapnull481   public fun toMap(): Map = when (type) {
482     T_MAP -> Map(buffer, buffer.indirect(end, parentWidth), byteWidth)
483     else -> emptyMap()
484   }
485 
resolvenull486   private inline fun <T> resolve(crossinline block: (pos: Int, width: ByteWidth) -> T): T {
487     return if (type.isIndirectScalar()) {
488       block(buffer.indirect(end, byteWidth), byteWidth)
489     } else {
490       block(end, parentWidth)
491     }
492   }
493 
equalsnull494   override fun equals(other: Any?): Boolean {
495     if (this === other) return true
496     if (other == null || this::class != other::class) return false
497     other as Reference
498     if (buffer != other.buffer ||
499       end != other.end ||
500       parentWidth != other.parentWidth ||
501       byteWidth != other.byteWidth ||
502       type != other.type
503     ) return false
504     return true
505   }
506 
hashCodenull507   override fun hashCode(): Int {
508     var result = buffer.hashCode()
509     result = 31 * result + end
510     result = 31 * result + parentWidth.value
511     result = 31 * result + byteWidth.value
512     result = 31 * result + type.hashCode()
513     return result
514   }
515 }
516 
517 /**
518  * Represents any element that has a size property to it, like: [Map], [Vector] and [TypedVector].
519  */
520 public open class Sized internal constructor(
521   public val buffer: ReadBuffer,
522   public val end: Int,
523   public val byteWidth: ByteWidth
524 ) {
525   public open val size: Int = buffer.readSize(end, byteWidth)
526 }
527 
528 /**
529  * Represent an array of bytes in the buffer.
530  */
531 public open class Blob internal constructor(
532   buffer: ReadBuffer,
533   end: Int,
534   byteWidth: ByteWidth
535 ) : Sized(buffer, end, byteWidth) {
536   /**
537    * Return [Blob] as [ReadBuffer]
538    * @return blob as [ReadBuffer]
539    */
datanull540   public fun data(): ReadBuffer = buffer.slice(end, size)
541 
542   /**
543    * Copy [Blob] into a [ByteArray]
544    * @return A [ByteArray] containing the blob data.
545    */
546   public fun toByteArray(): ByteArray {
547     val result = ByteArray(size)
548     for (i in 0 until size) {
549       result[i] = buffer[end + i]
550     }
551     return result
552   }
553 
554   /**
555    * Return individual byte at a given position
556    * @param pos position of the byte to be read
557    */
getnull558   public operator fun get(pos: Int): Byte {
559     if (pos !in 0..size) error("$pos index out of bounds. Should be in range 0..$size")
560     return buffer[end + pos]
561   }
562 
toStringnull563   override fun toString(): String = buffer.getString(end, size)
564 }
565 
566 /**
567  * [Vector] represents an array of elements in the buffer. The element can be of any type.
568  */
569 public open class Vector internal constructor(
570   buffer: ReadBuffer,
571   end: Int,
572   byteWidth: ByteWidth
573 ) : Collection<Reference>,
574   Sized(buffer, end, byteWidth) {
575 
576   /**
577    * Returns a [Reference] from the [Vector] at position [index]. Returns a null reference
578    * @param index position in the vector.
579    * @return [Reference] for a key or a null [Reference] if not found.
580    */
581   public open operator fun get(index: Int): Reference {
582     if (index >= size) return nullReference()
583     val packedType = buffer[(end + size * byteWidth.value + index)].toInt()
584     val objEnd = end + index * byteWidth
585     return Reference(buffer, objEnd, byteWidth, packedType)
586   }
587 
588   // overrides from Collection<Reference>
589 
590   override fun contains(element: Reference): Boolean = find { it == element } != null
591 
592   override fun containsAll(elements: Collection<Reference>): Boolean {
593     elements.forEach { if (!contains(it)) return false }
594     return true
595   }
596 
597   override fun isEmpty(): Boolean = size == 0
598 
599   override fun iterator(): Iterator<Reference> = object : Iterator<Reference> {
600     var position = 0
601     override fun hasNext(): Boolean = position != size
602     override fun next(): Reference = get(position++)
603   }
604 }
605 
606 /**
607  * [TypedVector] represents an array of scalar elements of the same type in the buffer.
608  */
609 public open class TypedVector(
610   private val elementType: FlexBufferType,
611   buffer: ReadBuffer,
612   end: Int,
613   byteWidth: ByteWidth
614 ) : Vector(buffer, end, byteWidth) {
615 
616   /**
617    * Returns a [Reference] from the [TypedVector] at position [index]. Returns a null reference
618    * @param index position in the vector.
619    * @return [Reference] for a key or a null [Reference] if not found.
620    */
getnull621   override operator fun get(index: Int): Reference {
622     if (index >= size) return nullReference()
623     val childPos: Int = end + index * byteWidth
624     return Reference(buffer, childPos, byteWidth, ByteWidth(1), elementType)
625   }
626 
resolveAtnull627   private inline fun <T> resolveAt(index: Int, crossinline block: (Int, ByteWidth) -> T): T {
628     val childPos: Int = end + index * byteWidth
629     return block(childPos, byteWidth)
630   }
631 
posnull632   internal fun getBoolean(index: Int): Boolean = resolveAt(index) { pos: Int, _: ByteWidth -> buffer.getBoolean(pos) }
getIntnull633   internal fun getInt(index: Int): Long = resolveAt(index) { pos: Int, width: ByteWidth -> buffer.readLong(pos, width) }
getUIntnull634   internal fun getUInt(index: Int): ULong = resolveAt(index) { pos: Int, width: ByteWidth -> buffer.readULong(pos, width) }
posnull635   internal fun getFloat(index: Int): Double = resolveAt(index) { pos: Int, width: ByteWidth -> buffer.readFloat(pos, width) }
636 }
637 
638 /**
639  * Represents a key element in the buffer. Keys are
640  * used to reference objects in a [Map]
641  */
642 public data class Key(
643   public val buffer: ReadBuffer,
644   public val start: Int,
645   public val end: Int = buffer.findFirst(ZeroByte, start)
646 ) {
647 
648   val sizeInBytes: Int = end - start
649 
650   private val codePoint = CharArray(2)
651 
652   val sizeInChars: Int
653     get() {
654       var count = 0
655       var i = start
656       while (i < end) {
657         val size = codePointSizeInBytes(i)
658         i += size
659         count += if (size == 4) 2 else 1
660       }
661       return count
662     }
663 
getnull664   public operator fun get(index: Int): Char {
665     var count = 0
666     var i = start
667     var size = 0
668     // we loop over the bytes to find the right position for the "char" at index i
669     while (i < end && count < index) {
670       size = codePointSizeInBytes(i)
671       i += size
672       // 4 bytes utf8 are 2 chars wide, the rest is on char.
673       count += if (size == 4) 2 else 1
674     }
675     return when {
676       count == index -> {
677         Utf8.decodeUtf8CodePoint(buffer, i, codePoint)
678         codePoint[0]
679       }
680       count == index + 1 && size == 4 -> {
681         Utf8.decodeUtf8CodePoint(buffer, i - size, codePoint)
682         codePoint[1]
683       }
684       else -> error("Invalid count=$count, index=$index")
685     }
686   }
687 
codePointSizeInBytesnull688   private inline fun codePointSizeInBytes(pos: Int): Int {
689     val b = buffer[pos]
690     return when {
691       Utf8.isOneByte(b) -> 1
692       Utf8.isTwoBytes(b) -> 2
693       Utf8.isThreeBytes(b) -> 3
694       else -> 4
695     }
696   }
697 
toStringnull698   override fun toString(): String = if (sizeInBytes > 0) buffer.getString(start, sizeInBytes) else ""
699 
700   /**
701    * Checks whether Key is invalid or not.
702    */
703   public fun isInvalid(): Boolean = sizeInBytes <= 0
704 }
705 
706 /**
707  * A Map class that provide support to access Key-Value data from Flexbuffers.
708  */
709 public class Map internal constructor(buffer: ReadBuffer, end: Int, byteWidth: ByteWidth) :
710   Sized(buffer, end, byteWidth),
711   kotlin.collections.Map<Key, Reference> {
712 
713   // used for accessing the key vector elements
714   private var keyVectorEnd: Int
715   private var keyVectorByteWidth: ByteWidth
716   init {
717     val keysOffset = end - (3 * byteWidth) // 3 is number of prefixed fields
718     keyVectorEnd = buffer.indirect(keysOffset, byteWidth)
719     keyVectorByteWidth = ByteWidth(buffer.readInt(keysOffset + byteWidth, byteWidth))
720   }
721 
722   /**
723    * Returns a [Reference] from the [Map] at position [index]. Returns a null reference
724    * @param index position in the map
725    * @return [Reference] for a key or a null [Reference] if not found.
726    */
727   public operator fun get(index: Int): Reference {
728     if (index >= size) return nullReference()
729     val packedPos = end + size * byteWidth + index
730     val packedType = buffer[packedPos].toInt()
731     val objEnd = end + index * byteWidth
732     return Reference(buffer, objEnd, byteWidth, packedType)
733   }
734 
735   /**
736    * Returns a [Reference] from the [Map] for a given [String] [key].
737    * @param key access key to element on map
738    * @return [Reference] for a key or a null [Reference] if not found.
739    */
740   public operator fun get(key: String): Reference {
741     val index: Int = binarySearch(key)
742     return if (index in 0 until size) {
743       get(index)
744     } else nullReference()
745   }
746 
747   /**
748    * Returns a [Reference] from the [Map] for a given [Key] [key].
749    * @param key access key to element on map
750    * @return [Reference] for a key or a null [Reference] if not found.
751    */
752   override operator fun get(key: Key): Reference {
753     val index = binarySearch(key)
754     return if (index in 0 until size) {
755       get(index)
756     } else nullReference()
757   }
758 
759   /**
760    * Checks whether the map contains a [key].
761    * @param key [String]
762    * @return true if key is found in the map, otherwise false.
763    */
764   public operator fun contains(key: String): Boolean = binarySearch(key) >= 0
765 
766   /**
767    * Returns a [Key] for a given position [index] in the [Map].
768    * @param index of the key in the map
769    * @return a Key for the given index. Out of bounds indexes returns invalid keys.
770    */
771   public fun keyAt(index: Int): Key {
772     val childPos: Int = keyVectorEnd + index * keyVectorByteWidth
773     return Key(buffer, buffer.indirect(childPos, keyVectorByteWidth))
774   }
775 
776   /**
777    * Returns a [Key] as [String] for a given position [index] in the [Map].
778    * @param index of the key in the map
779    * @return a Key for the given index. Out of bounds indexes returns empty string.
780    */
781   public fun keyAsString(index: Int): String {
782     val childPos: Int = keyVectorEnd + index * keyVectorByteWidth
783     val start = buffer.indirect(childPos, keyVectorByteWidth)
784     val end = buffer.findFirst(ZeroByte, start)
785     return if (end > start) buffer.getString(start, end - start) else ""
786   }
787 
788   // Overrides from kotlin.collections.Map<Key, Reference>
789 
790   public data class Entry(override val key: Key, override val value: Reference) :
791     kotlin.collections.Map.Entry<Key, Reference>
792 
793   override val entries: Set<kotlin.collections.Map.Entry<Key, Reference>>
794     get() = keys.map { Entry(it, get(it.toString())) }.toSet()
795 
796   override val keys: Set<Key>
797     get() {
798       val set = LinkedHashSet<Key>(size)
799       for (i in 0 until size) {
800         val key = keyAt(i)
801         set.add(key)
802       }
803       return set
804     }
805 
806   /**
807    * Returns a [Vector] for accessing all values in the [Map].
808    * @return [Vector] of values.
809    */
810   override val values: Collection<Reference>
811     get() = Vector(buffer, end, byteWidth)
812 
813   override fun containsKey(key: Key): Boolean {
814     for (i in 0 until size) {
815       if (key == keyAt(i))
816         return true
817     }
818     return false
819   }
820 
821   override fun containsValue(value: Reference): Boolean = values.contains(value)
822 
823   override fun isEmpty(): Boolean = size == 0
824 
825   // Performs a binary search on a key vector and return index of the key in key vector
826   private fun binarySearch(searchedKey: String) = binarySearch { compareCharSequence(it, searchedKey) }
827   // Performs a binary search on a key vector and return index of the key in key vector
828   private fun binarySearch(key: Key): Int = binarySearch { compareKeys(it, key.start) }
829 
830   private inline fun binarySearch(crossinline comparisonBlock: (Int) -> Int): Int {
831     var low = 0
832     var high = size - 1
833     while (low <= high) {
834       val mid = low + high ushr 1
835       val keyPos: Int = buffer.indirect(keyVectorEnd + mid * keyVectorByteWidth, keyVectorByteWidth)
836       val cmp: Int = comparisonBlock(keyPos)
837       if (cmp < 0) low = mid + 1 else if (cmp > 0) high = mid - 1 else return mid // key found
838     }
839     return -(low + 1) // key not found
840   }
841 
842   // compares a CharSequence against a T_KEY
843   private fun compareKeys(start: Int, other: Int): Int {
844     var bufferPos = start
845     var otherPos = other
846     val limit: Int = buffer.limit
847     var c1: Byte = ZeroByte
848     var c2: Byte = ZeroByte
849     while (otherPos < limit) {
850       c1 = buffer[bufferPos++]
851       c2 = buffer[otherPos++]
852       when {
853         c1 == ZeroByte -> return c1 - c2
854         c1 != c2 -> return c1 - c2
855       }
856     }
857     return c1 - c2
858   }
859 
860   // compares a CharSequence against a [CharSequence]
861   private fun compareCharSequence(start: Int, other: CharSequence): Int {
862     var bufferPos = start
863     var otherPos = 0
864     val limit: Int = buffer.limit
865     val otherLimit = other.length
866     // special loop for ASCII characters. Most of keys should be ASCII only, so this
867     // loop should be optimized for that.
868     // breaks if a multi-byte character is found
869     while (otherPos < otherLimit) {
870       val c2 = other[otherPos]
871       // not a single byte codepoint
872       if (c2.toInt() >= 0x80) {
873         break
874       }
875       val b: Byte = buffer[bufferPos]
876       when {
877         b == ZeroByte -> return -c2.toInt()
878         b < 0 -> break
879         b != c2.toByte() -> return b - c2.toByte()
880       }
881       ++bufferPos
882       ++otherPos
883     }
884     if (bufferPos < limit)
885       return 0
886 
887     val comparisonBuffer = ByteArray(4)
888     while (bufferPos < limit) {
889       val sizeInBuff = Utf8.encodeUtf8CodePoint(other, otherPos, comparisonBuffer)
890       if (sizeInBuff == 0) {
891         return buffer[bufferPos].toInt()
892       }
893       for (i in 0 until sizeInBuff) {
894         val bufferByte: Byte = buffer[bufferPos++]
895         val otherByte: Byte = comparisonBuffer[i]
896         when {
897           bufferByte == ZeroByte -> return -otherByte
898           bufferByte != otherByte -> return bufferByte - otherByte
899         }
900       }
901       otherPos += if (sizeInBuff == 4) 2 else 1
902     }
903     return 0
904   }
905 }
906