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