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