• 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   public 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 ->
298       "[ ${toVector().joinToString(", ") { it.toString() }} ]"
299     T_INT -> toLong().toString()
300     T_UINT -> toULong().toString()
301     T_FLOAT -> toDouble().toString()
302     else -> "${type.typeToString()}(end=$end)"
303   }
304 
305   /**
306    * Returns element as a [ByteArray], converting scalar types when possible.
307    * @return element as [ByteArray] or empty [ByteArray] if fail.
308    */
toByteArraynull309   public fun toByteArray(): ByteArray {
310     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
311     return when (type) {
312       T_VECTOR_INT -> ByteArray(vec.size) { vec.getInt(it).toByte() }
313       T_VECTOR_UINT -> ByteArray(vec.size) { vec.getUInt(it).toByte() }
314       T_VECTOR -> ByteArray(vec.size) { vec[it].toByte() }
315       T_VECTOR_FLOAT -> ByteArray(vec.size) { vec.getFloat(it).toInt().toByte() }
316       else -> ByteArray(0)
317     }
318   }
319 
320   /**
321    * Returns element as a [ByteArray], converting scalar types when possible.
322    * @return element as [ByteArray] or empty [ByteArray] if fail.
323    */
toShortArraynull324   public fun toShortArray(): ShortArray {
325     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
326     return when (type) {
327       T_VECTOR_INT -> ShortArray(vec.size) { vec.getInt(it).toShort() }
328       T_VECTOR_UINT -> ShortArray(vec.size) { vec.getUInt(it).toShort() }
329       T_VECTOR -> ShortArray(vec.size) { vec[it].toShort() }
330       T_VECTOR_FLOAT -> ShortArray(vec.size) { vec.getFloat(it).toInt().toShort() }
331       else -> ShortArray(0)
332     }
333   }
334 
335   /**
336    * Returns element as a [IntArray], converting scalar types when possible.
337    * @return element as [IntArray] or empty [IntArray] if fail.
338    */
toIntArraynull339   public fun toIntArray(): IntArray {
340     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
341     return when (type) {
342       T_VECTOR_INT -> IntArray(vec.size) { vec.getInt(it).toInt() }
343       T_VECTOR_UINT -> IntArray(vec.size) { vec.getUInt(it).toInt() }
344       T_VECTOR -> IntArray(vec.size) { vec[it].toInt() }
345       T_VECTOR_FLOAT -> IntArray(vec.size) { vec.getFloat(it).toInt() }
346       else -> IntArray(0)
347     }
348   }
349 
350   /**
351    * Returns element as a [LongArray], converting scalar types when possible.
352    * @return element as [LongArray] or empty [LongArray] if fail.
353    */
toLongArraynull354   public fun toLongArray(): LongArray {
355     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
356     return when (type) {
357       T_VECTOR_INT -> LongArray(vec.size) { vec.getInt(it) }
358       T_VECTOR_UINT -> LongArray(vec.size) { vec.getInt(it) }
359       T_VECTOR -> LongArray(vec.size) { vec[it].toLong() }
360       T_VECTOR_FLOAT -> LongArray(vec.size) { vec.getFloat(it).toLong() }
361       else -> LongArray(0)
362     }
363   }
364 
365   /**
366    * Returns element as a [UByteArray], converting scalar types when possible.
367    * @return element as [UByteArray] or empty [UByteArray] if fail.
368    */
toUByteArraynull369   public fun toUByteArray(): UByteArray {
370     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
371     return when (type) {
372       T_VECTOR_INT -> UByteArray(vec.size) { vec.getInt(it).toUByte() }
373       T_VECTOR_UINT -> UByteArray(vec.size) { vec.getUInt(it).toUByte() }
374       T_VECTOR -> UByteArray(vec.size) { vec[it].toUByte() }
375       T_VECTOR_FLOAT -> UByteArray(vec.size) { vec.getFloat(it).toInt().toUByte() }
376       else -> UByteArray(0)
377     }
378   }
379 
380   /**
381    * Returns element as a [UIntArray], converting scalar types when possible.
382    * @return element as [UIntArray] or empty [UIntArray] if fail.
383    */
toUShortArraynull384   public fun toUShortArray(): UShortArray {
385     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
386     return when (type) {
387       T_VECTOR_INT -> UShortArray(vec.size) { vec.getInt(it).toUShort() }
388       T_VECTOR_UINT -> UShortArray(vec.size) { vec.getUInt(it).toUShort() }
389       T_VECTOR -> UShortArray(vec.size) { vec[it].toUShort() }
390       T_VECTOR_FLOAT -> UShortArray(vec.size) { vec.getFloat(it).toUInt().toUShort() }
391       else -> UShortArray(0)
392     }
393   }
394 
395   /**
396    * Returns element as a [UIntArray], converting scalar types when possible.
397    * @return element as [UIntArray] or empty [UIntArray] if fail.
398    */
toUIntArraynull399   public fun toUIntArray(): UIntArray {
400     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
401     return when (type) {
402       T_VECTOR_INT -> UIntArray(vec.size) { vec.getInt(it).toUInt() }
403       T_VECTOR_UINT -> UIntArray(vec.size) { vec.getUInt(it).toUInt() }
404       T_VECTOR -> UIntArray(vec.size) { vec[it].toUInt() }
405       T_VECTOR_FLOAT -> UIntArray(vec.size) { vec.getFloat(it).toUInt() }
406       else -> UIntArray(0)
407     }
408   }
409 
410   /**
411    * Returns element as a [ULongArray], converting scalar types when possible.
412    * @return element as [ULongArray] or empty [ULongArray] if fail.
413    */
toULongArraynull414   public fun toULongArray(): ULongArray {
415     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
416     return when (type) {
417       T_VECTOR_INT -> ULongArray(vec.size) { vec.getUInt(it) }
418       T_VECTOR_UINT -> ULongArray(vec.size) { vec.getUInt(it) }
419       T_VECTOR -> ULongArray(vec.size) { vec[it].toULong() }
420       T_VECTOR_FLOAT -> ULongArray(vec.size) { vec.getFloat(it).toULong() }
421       else -> ULongArray(0)
422     }
423   }
424 
425   /**
426    * Returns element as a [FloatArray], converting scalar types when possible.
427    * @return element as [FloatArray] or empty [FloatArray] if fail.
428    */
toFloatArraynull429   public fun toFloatArray(): FloatArray {
430     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
431     return when (type) {
432       T_VECTOR_FLOAT -> FloatArray(vec.size) { vec.getFloat(it).toFloat() }
433       T_VECTOR_INT -> FloatArray(vec.size) { vec.getInt(it).toFloat() }
434       T_VECTOR_UINT -> FloatArray(vec.size) { vec.getUInt(it).toFloat() }
435       T_VECTOR -> FloatArray(vec.size) { vec[it].toFloat() }
436       else -> FloatArray(0)
437     }
438   }
439 
440   /**
441    * Returns element as a [DoubleArray], converting scalar types when possible.
442    * @return element as [DoubleArray] or empty [DoubleArray] if fail.
443    */
toDoubleArraynull444   public fun toDoubleArray(): DoubleArray {
445     val vec = TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
446     return when (type) {
447       T_VECTOR_FLOAT -> DoubleArray(vec.size) { vec[it].toDouble() }
448       T_VECTOR_INT -> DoubleArray(vec.size) { vec[it].toDouble() }
449       T_VECTOR_UINT -> DoubleArray(vec.size) { vec[it].toDouble() }
450       T_VECTOR -> DoubleArray(vec.size) { vec[it].toDouble() }
451       else -> DoubleArray(0)
452     }
453   }
454 
455   /**
456    * Returns element as a [Vector]
457    * @return element as [Vector] or empty [Vector] if fail
458    */
toVectornull459   public fun toVector(): Vector {
460     return when {
461       isVector -> Vector(buffer, buffer.indirect(end, parentWidth), byteWidth)
462       isTypedVector -> TypedVector(type.toElementTypedVector(), buffer, buffer.indirect(end, parentWidth), byteWidth)
463       else -> emptyVector()
464     }
465   }
466 
467   /**
468    * Returns element as a [Blob]
469    * @return element as [Blob] or empty [Blob] if fail
470    */
toBlobnull471   public fun toBlob(): Blob {
472     return when (type) {
473       T_BLOB, T_STRING -> Blob(buffer, buffer.indirect(end, parentWidth), byteWidth)
474       else -> emptyBlob()
475     }
476   }
477 
478   /**
479    * Returns element as a [Map].
480    * @return element as [Map] or empty [Map] if fail
481    */
toMapnull482   public fun toMap(): Map = when (type) {
483     T_MAP -> Map(buffer, buffer.indirect(end, parentWidth), byteWidth)
484     else -> emptyMap()
485   }
486 
resolvenull487   private inline fun <T> resolve(crossinline block: (pos: Int, width: ByteWidth) -> T): T {
488     return if (type.isIndirectScalar()) {
489       block(buffer.indirect(end, byteWidth), byteWidth)
490     } else {
491       block(end, parentWidth)
492     }
493   }
494 
equalsnull495   override fun equals(other: Any?): Boolean {
496     if (this === other) return true
497     if (other == null || this::class != other::class) return false
498     other as Reference
499     if (buffer != other.buffer ||
500       end != other.end ||
501       parentWidth != other.parentWidth ||
502       byteWidth != other.byteWidth ||
503       type != other.type
504     ) return false
505     return true
506   }
507 
hashCodenull508   override fun hashCode(): Int {
509     var result = buffer.hashCode()
510     result = 31 * result + end
511     result = 31 * result + parentWidth.value
512     result = 31 * result + byteWidth.value
513     result = 31 * result + type.hashCode()
514     return result
515   }
516 }
517 
518 /**
519  * Represents any element that has a size property to it, like: [Map], [Vector] and [TypedVector].
520  */
521 public open class Sized internal constructor(
522   public val buffer: ReadBuffer,
523   public val end: Int,
524   public val byteWidth: ByteWidth
525 ) {
526   public open val size: Int = buffer.readSize(end, byteWidth)
527 }
528 
529 /**
530  * Represent an array of bytes in the buffer.
531  */
532 public open class Blob internal constructor(
533   buffer: ReadBuffer,
534   end: Int,
535   byteWidth: ByteWidth
536 ) : Sized(buffer, end, byteWidth) {
537   /**
538    * Return [Blob] as [ReadBuffer]
539    * @return blob as [ReadBuffer]
540    */
datanull541   public fun data(): ReadBuffer = buffer.slice(end, size)
542 
543   /**
544    * Copy [Blob] into a [ByteArray]
545    * @return A [ByteArray] containing the blob data.
546    */
547   public fun toByteArray(): ByteArray {
548     val result = ByteArray(size)
549     for (i in 0 until size) {
550       result[i] = buffer[end + i]
551     }
552     return result
553   }
554 
555   /**
556    * Return individual byte at a given position
557    * @param pos position of the byte to be read
558    */
getnull559   public operator fun get(pos: Int): Byte {
560     if (pos !in 0..size) error("$pos index out of bounds. Should be in range 0..$size")
561     return buffer[end + pos]
562   }
563 
toStringnull564   override fun toString(): String = buffer.getString(end, size)
565 }
566 
567 /**
568  * [Vector] represents an array of elements in the buffer. The element can be of any type.
569  */
570 public open class Vector internal constructor(
571   buffer: ReadBuffer,
572   end: Int,
573   byteWidth: ByteWidth
574 ) : Collection<Reference>,
575   Sized(buffer, end, byteWidth) {
576 
577   /**
578    * Returns a [Reference] from the [Vector] at position [index]. Returns a null reference
579    * @param index position in the vector.
580    * @return [Reference] for a key or a null [Reference] if not found.
581    */
582   public open operator fun get(index: Int): Reference {
583     if (index >= size) return nullReference()
584     val packedType = buffer[(end + size * byteWidth.value + index)].toInt()
585     val objEnd = end + index * byteWidth
586     return Reference(buffer, objEnd, byteWidth, packedType)
587   }
588 
589   // overrides from Collection<Reference>
590 
591   override fun contains(element: Reference): Boolean = find { it == element } != null
592 
593   override fun containsAll(elements: Collection<Reference>): Boolean {
594     elements.forEach { if (!contains(it)) return false }
595     return true
596   }
597 
598   override fun isEmpty(): Boolean = size == 0
599 
600   override fun iterator(): Iterator<Reference> = object : Iterator<Reference> {
601     var position = 0
602     override fun hasNext(): Boolean = position != size
603     override fun next(): Reference = get(position++)
604   }
605 }
606 
607 /**
608  * [TypedVector] represents an array of scalar elements of the same type in the buffer.
609  */
610 public open class TypedVector(
611   private val elementType: FlexBufferType,
612   buffer: ReadBuffer,
613   end: Int,
614   byteWidth: ByteWidth
615 ) : Vector(buffer, end, byteWidth) {
616 
617   /**
618    * Returns a [Reference] from the [TypedVector] at position [index]. Returns a null reference
619    * @param index position in the vector.
620    * @return [Reference] for a key or a null [Reference] if not found.
621    */
getnull622   override operator fun get(index: Int): Reference {
623     if (index >= size) return nullReference()
624     val childPos: Int = end + index * byteWidth
625     return Reference(buffer, childPos, byteWidth, ByteWidth(1), elementType)
626   }
627 
resolveAtnull628   private inline fun <T> resolveAt(index: Int, crossinline block: (Int, ByteWidth) -> T): T {
629     val childPos: Int = end + index * byteWidth
630     return block(childPos, byteWidth)
631   }
632 
getBooleannull633   internal fun getBoolean(index: Int): Boolean = resolveAt(index) {
634       pos: Int, _: ByteWidth -> buffer.getBoolean(pos)
635   }
getIntnull636   internal fun getInt(index: Int): Long = resolveAt(index) {
637       pos: Int, width: ByteWidth -> buffer.readLong(pos, width)
638   }
getUIntnull639   internal fun getUInt(index: Int): ULong = resolveAt(index) {
640       pos: Int, width: ByteWidth -> buffer.readULong(pos, width)
641   }
getFloatnull642   internal fun getFloat(index: Int): Double = resolveAt(index) {
643       pos: Int, width: ByteWidth -> buffer.readFloat(pos, width)
644   }
645 }
646 
647 /**
648  * Represents a key element in the buffer. Keys are
649  * used to reference objects in a [Map]
650  */
651 public data class Key(
652   public val buffer: ReadBuffer,
653   public val start: Int,
654   public val end: Int = buffer.findFirst(ZeroByte, start)
655 ) {
656 
657   val sizeInBytes: Int = end - start
658 
659   private val codePoint = CharArray(2)
660 
661   val sizeInChars: Int
662     get() {
663       var count = 0
664       var i = start
665       while (i < end) {
666         val size = codePointSizeInBytes(i)
667         i += size
668         count += if (size == 4) 2 else 1
669       }
670       return count
671     }
672 
getnull673   public operator fun get(index: Int): Char {
674     var count = 0
675     var i = start
676     var size = 0
677     // we loop over the bytes to find the right position for the "char" at index i
678     while (i < end && count < index) {
679       size = codePointSizeInBytes(i)
680       i += size
681       // 4 bytes utf8 are 2 chars wide, the rest is on char.
682       count += if (size == 4) 2 else 1
683     }
684     return when {
685       count == index -> {
686         Utf8.decodeUtf8CodePoint(buffer, i, codePoint)
687         codePoint[0]
688       }
689       count == index + 1 && size == 4 -> {
690         Utf8.decodeUtf8CodePoint(buffer, i - size, codePoint)
691         codePoint[1]
692       }
693       else -> error("Invalid count=$count, index=$index")
694     }
695   }
696 
codePointSizeInBytesnull697   private inline fun codePointSizeInBytes(pos: Int): Int {
698     val b = buffer[pos]
699     return when {
700       Utf8.isOneByte(b) -> 1
701       Utf8.isTwoBytes(b) -> 2
702       Utf8.isThreeBytes(b) -> 3
703       else -> 4
704     }
705   }
706 
toStringnull707   override fun toString(): String = if (sizeInBytes > 0) buffer.getString(start, sizeInBytes) else ""
708 
709   /**
710    * Checks whether Key is invalid or not.
711    */
712   public fun isInvalid(): Boolean = sizeInBytes <= 0
713 }
714 
715 /**
716  * A Map class that provide support to access Key-Value data from Flexbuffers.
717  */
718 public class Map
719   internal constructor(buffer: ReadBuffer, end: Int, byteWidth: ByteWidth):
720   Sized(buffer, end, byteWidth),
721   kotlin.collections.Map<Key, Reference> {
722 
723   // used for accessing the key vector elements
724   private var keyVectorEnd: Int
725   private var keyVectorByteWidth: ByteWidth
726   init {
727     val keysOffset = end - (3 * byteWidth) // 3 is number of prefixed fields
728     keyVectorEnd = buffer.indirect(keysOffset, byteWidth)
729     keyVectorByteWidth = ByteWidth(buffer.readInt(keysOffset + byteWidth, byteWidth))
730   }
731 
732   /**
733    * Returns a [Reference] from the [Map] at position [index]. Returns a null reference
734    * @param index position in the map
735    * @return [Reference] for a key or a null [Reference] if not found.
736    */
737   public operator fun get(index: Int): Reference {
738     if (index >= size) return nullReference()
739     val packedPos = end + size * byteWidth + index
740     val packedType = buffer[packedPos].toInt()
741     val objEnd = end + index * byteWidth
742     return Reference(buffer, objEnd, byteWidth, packedType)
743   }
744 
745   /**
746    * Returns a [Reference] from the [Map] for a given [String] [key].
747    * @param key access key to element on map
748    * @return [Reference] for a key or a null [Reference] if not found.
749    */
750   public operator fun get(key: String): Reference {
751     val index: Int = binarySearch(key)
752     return if (index in 0 until size) {
753       get(index)
754     } else nullReference()
755   }
756 
757   /**
758    * Returns a [Reference] from the [Map] for a given [Key] [key].
759    * @param key access key to element on map
760    * @return [Reference] for a key or a null [Reference] if not found.
761    */
762   override operator fun get(key: Key): Reference {
763     val index = binarySearch(key)
764     return if (index in 0 until size) {
765       get(index)
766     } else nullReference()
767   }
768 
769   /**
770    * Checks whether the map contains a [key].
771    * @param key [String]
772    * @return true if key is found in the map, otherwise false.
773    */
774   public operator fun contains(key: String): Boolean = binarySearch(key) >= 0
775 
776   /**
777    * Returns a [Key] 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 invalid keys.
780    */
781   public fun keyAt(index: Int): Key {
782     val childPos: Int = keyVectorEnd + index * keyVectorByteWidth
783     return Key(buffer, buffer.indirect(childPos, keyVectorByteWidth))
784   }
785 
786   /**
787    * Returns a [Key] as [String] for a given position [index] in the [Map].
788    * @param index of the key in the map
789    * @return a Key for the given index. Out of bounds indexes returns empty string.
790    */
791   public fun keyAsString(index: Int): String {
792     val childPos: Int = keyVectorEnd + index * keyVectorByteWidth
793     val start = buffer.indirect(childPos, keyVectorByteWidth)
794     val end = buffer.findFirst(ZeroByte, start)
795     return if (end > start) buffer.getString(start, end - start) else ""
796   }
797 
798   // Overrides from kotlin.collections.Map<Key, Reference>
799 
800   public data class Entry(override val key: Key, override val value: Reference) :
801     kotlin.collections.Map.Entry<Key, Reference>
802 
803   override val entries: Set<kotlin.collections.Map.Entry<Key, Reference>>
804     get() = keys.map { Entry(it, get(it.toString())) }.toSet()
805 
806   override val keys: Set<Key>
807     get() {
808       val set = LinkedHashSet<Key>(size)
809       for (i in 0 until size) {
810         val key = keyAt(i)
811         set.add(key)
812       }
813       return set
814     }
815 
816   /**
817    * Returns a [Vector] for accessing all values in the [Map].
818    * @return [Vector] of values.
819    */
820   override val values: Collection<Reference>
821     get() = Vector(buffer, end, byteWidth)
822 
823   override fun containsKey(key: Key): Boolean {
824     for (i in 0 until size) {
825       if (key == keyAt(i))
826         return true
827     }
828     return false
829   }
830 
831   override fun containsValue(value: Reference): Boolean = values.contains(value)
832 
833   override fun isEmpty(): Boolean = size == 0
834 
835   // Performs a binary search on a key vector and return index of the key in key vector
836   private fun binarySearch(searchedKey: String) = binarySearch { compareCharSequence(it, searchedKey) }
837   // Performs a binary search on a key vector and return index of the key in key vector
838   private fun binarySearch(key: Key): Int = binarySearch { compareKeys(it, key.start) }
839 
840   private inline fun binarySearch(crossinline comparisonBlock: (Int) -> Int): Int {
841     var low = 0
842     var high = size - 1
843     while (low <= high) {
844       val mid = low + high ushr 1
845       val keyPos: Int = buffer.indirect(keyVectorEnd + mid * keyVectorByteWidth, keyVectorByteWidth)
846       val cmp: Int = comparisonBlock(keyPos)
847       if (cmp < 0) low = mid + 1 else if (cmp > 0) high = mid - 1 else return mid // key found
848     }
849     return -(low + 1) // key not found
850   }
851 
852   // compares a CharSequence against a T_KEY
853   private fun compareKeys(start: Int, other: Int): Int {
854     var bufferPos = start
855     var otherPos = other
856     val limit: Int = buffer.limit
857     var c1: Byte = ZeroByte
858     var c2: Byte = ZeroByte
859     while (otherPos < limit) {
860       c1 = buffer[bufferPos++]
861       c2 = buffer[otherPos++]
862       when {
863         c1 == ZeroByte -> return c1 - c2
864         c1 != c2 -> return c1 - c2
865       }
866     }
867     return c1 - c2
868   }
869 
870   // compares a CharSequence against a [CharSequence]
871   private fun compareCharSequence(start: Int, other: CharSequence): Int {
872     var bufferPos = start
873     var otherPos = 0
874     val limit: Int = buffer.limit
875     val otherLimit = other.length
876     // special loop for ASCII characters. Most of keys should be ASCII only, so this
877     // loop should be optimized for that.
878     // breaks if a multi-byte character is found
879     while (otherPos < otherLimit) {
880       val c2 = other[otherPos]
881       // not a single byte codepoint
882       if (c2.code >= 0x80) {
883         break
884       }
885       val b: Byte = buffer[bufferPos]
886       when {
887         b == ZeroByte -> return -c2.code
888         b < 0 -> break
889         b != c2.code.toByte() -> return b - c2.code.toByte()
890       }
891       ++bufferPos
892       ++otherPos
893     }
894     if (bufferPos < limit)
895       return 0
896 
897     val comparisonBuffer = ByteArray(4)
898     while (bufferPos < limit) {
899       val sizeInBuff = Utf8.encodeUtf8CodePoint(other, otherPos, comparisonBuffer)
900       if (sizeInBuff == 0) {
901         return buffer[bufferPos].toInt()
902       }
903       for (i in 0 until sizeInBuff) {
904         val bufferByte: Byte = buffer[bufferPos++]
905         val otherByte: Byte = comparisonBuffer[i]
906         when {
907           bufferByte == ZeroByte -> return -otherByte
908           bufferByte != otherByte -> return bufferByte - otherByte
909         }
910       }
911       otherPos += if (sizeInBuff == 4) 2 else 1
912     }
913     return 0
914   }
915 }
916