1 /* 2 * 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 18 package com.google.flatbuffers.kotlin 19 20 public class FlexBuffersBuilder( 21 public val buffer: ReadWriteBuffer, 22 private val shareFlag: Int = SHARE_KEYS 23 ) { 24 25 public constructor(initialCapacity: Int = 1024, shareFlag: Int = SHARE_KEYS) : 26 this(ArrayReadWriteBuffer(initialCapacity), shareFlag) 27 28 private val stringValuePool: HashMap<String, Value> = HashMap() 29 private val stringKeyPool: HashMap<String, Int> = HashMap() 30 private val stack: MutableList<Value> = mutableListOf() 31 private var finished: Boolean = false 32 33 /** 34 * Reset the FlexBuffersBuilder by purging all data that it holds. Buffer might 35 * keep its capacity after a reset. 36 */ clearnull37 public fun clear() { 38 buffer.clear() 39 stringValuePool.clear() 40 stringKeyPool.clear() 41 stack.clear() 42 finished = false 43 } 44 45 /** 46 * Finish writing the message into the buffer. After that no other element must 47 * be inserted into the buffer. Also, you must call this function before start using the 48 * FlexBuffer message 49 * @return [ReadBuffer] containing the FlexBuffer message 50 */ finishnull51 public fun finish(): ReadBuffer { 52 // If you hit this assert, you likely have objects that were never included 53 // in a parent. You need to have exactly one root to finish a buffer. 54 // Check your Start/End calls are matched, and all objects are inside 55 // some other object. 56 if (stack.size != 1) error("There is must be only on object as root. Current ${stack.size}.") 57 // Write root value. 58 val byteWidth = align(stack[0].elemWidth(buffer.writePosition, 0)) 59 writeAny(stack[0], byteWidth) 60 // Write root type. 61 buffer.put(stack[0].storedPackedType()) 62 // Write root size. Normally determined by parent, but root has no parent :) 63 buffer.put(byteWidth.value.toByte()) 64 this.finished = true 65 return buffer // TODO: make a read-only shallow copy 66 } 67 68 /** 69 * Insert a single [Boolean] into the buffer 70 * @param value true or false 71 */ <lambda>null72 public fun put(value: Boolean): Unit = run { this[null] = value } 73 74 /** 75 * Insert a null reference into the buffer. A key must be present if element is inserted into a map. 76 */ putNullnull77 public fun putNull(key: String? = null): Unit = 78 run { stack.add(Value(T_NULL, putKey(key), W_8, 0UL)) } 79 80 /** 81 * Insert a single [Boolean] into the buffer. A key must be present if element is inserted into a map. 82 */ setnull83 public operator fun set(key: String? = null, value: Boolean): Unit = 84 run { stack.add(Value(T_BOOL, putKey(key), W_8, if (value) 1UL else 0UL)) } 85 86 /** 87 * Insert a single [Byte] into the buffer 88 */ putnull89 public fun put(value: Byte): Unit = set(null, value.toLong()) 90 91 /** 92 * Insert a single [Byte] into the buffer. A key must be present if element is inserted into a map. 93 */ 94 public operator fun set(key: String? = null, value: Byte): Unit = set(key, value.toLong()) 95 96 /** 97 * Insert a single [Short] into the buffer. 98 */ 99 public fun put(value: Short): Unit = set(null, value.toLong()) 100 101 /** 102 * Insert a single [Short] into the buffer. A key must be present if element is inserted into a map. 103 */ 104 public inline operator fun set(key: String? = null, value: Short): Unit = set(key, value.toLong()) 105 106 /** 107 * Insert a single [Int] into the buffer. 108 */ 109 public fun put(value: Int): Unit = set(null, value.toLong()) 110 111 /** 112 * Insert a single [Int] into the buffer. A key must be present if element is inserted into a map. 113 */ 114 public inline operator fun set(key: String? = null, value: Int): Unit = set(key, value.toLong()) 115 116 /** 117 * Insert a single [Long] into the buffer. 118 */ 119 public fun put(value: Long): Unit = set(null, value) 120 121 /** 122 * Insert a single [Long] into the buffer. A key must be present if element is inserted into a map. 123 */ 124 public operator fun set(key: String? = null, value: Long): Unit = 125 run { stack.add(Value(T_INT, putKey(key), value.toULong().widthInUBits(), value.toULong())) } 126 127 /** 128 * Insert a single [UByte] into the buffer 129 */ putnull130 public fun put(value: UByte): Unit = set(null, value.toULong()) 131 132 /** 133 * Insert a single [UByte] into the buffer. A key must be present if element is inserted into a map. 134 */ 135 public inline operator fun set(key: String? = null, value: UByte): Unit = set(key, value.toULong()) 136 137 /** 138 * Insert a single [UShort] into the buffer. 139 */ 140 public fun put(value: UShort): Unit = set(null, value.toULong()) 141 142 /** 143 * Insert a single [UShort] into the buffer. A key must be present if element is inserted into a map. 144 */ 145 private inline operator fun set(key: String? = null, value: UShort): Unit = set(key, value.toULong()) 146 147 /** 148 * Insert a single [UInt] into the buffer. 149 */ 150 public fun put(value: UInt): Unit = set(null, value.toULong()) 151 152 /** 153 * Insert a single [UInt] into the buffer. A key must be present if element is inserted into a map. 154 */ 155 private inline operator fun set(key: String? = null, value: UInt): Unit = set(key, value.toULong()) 156 157 /** 158 * Insert a single [ULong] into the buffer. 159 */ 160 public fun put(value: ULong): Unit = set(null, value) 161 162 /** 163 * Insert a single [ULong] into the buffer. A key must be present if element is inserted into a map. 164 */ 165 public operator fun set(key: String? = null, value: ULong): Unit = 166 run { stack.add(Value(T_UINT, putKey(key), value.widthInUBits(), value)) } 167 168 /** 169 * Insert a single [Float] into the buffer. 170 */ <lambda>null171 public fun put(value: Float): Unit = run { this[null] = value } 172 173 /** 174 * Insert a single [Float] into the buffer. A key must be present if element is inserted into a map. 175 */ setnull176 public operator fun set(key: String? = null, value: Float): Unit = 177 run { stack.add(Value(T_FLOAT, putKey(key), W_32, dValue = value.toDouble())) } 178 179 /** 180 * Insert a single [Double] into the buffer. 181 */ <lambda>null182 public fun put(value: Double): Unit = run { this[null] = value } 183 184 /** 185 * Insert a single [Double] into the buffer. A key must be present if element is inserted into a map. 186 */ setnull187 public operator fun set(key: String? = null, value: Double): Unit = 188 run { stack.add(Value(T_FLOAT, putKey(key), W_64, dValue = value)) } 189 190 /** 191 * Insert a single [String] into the buffer. 192 */ putnull193 public fun put(value: String): Int = set(null, value) 194 195 /** 196 * Insert a single [String] into the buffer. A key must be present if element is inserted into a map. 197 */ 198 public operator fun set(key: String? = null, value: String): Int { 199 val iKey = putKey(key) 200 val holder = if (shareFlag and SHARE_STRINGS != 0) { 201 stringValuePool.getOrPut(value) { writeString(iKey, value).also { stringValuePool[value] = it } }.copy(key = iKey) 202 } else { 203 writeString(iKey, value) 204 } 205 stack.add(holder) 206 return holder.iValue.toInt() 207 } 208 209 /** 210 * Adds a [ByteArray] into the message as a [Blob]. 211 * @param value byte array 212 * @return position in buffer as the start of byte array 213 */ putnull214 public fun put(value: ByteArray): Int = set(null, value) 215 216 /** 217 * Adds a [ByteArray] into the message as a [Blob]. A key must be present if element is inserted into a map. 218 * @param value byte array 219 * @return position in buffer as the start of byte array 220 */ 221 public operator fun set(key: String? = null, value: ByteArray): Int { 222 val element = writeBlob(putKey(key), value, T_BLOB, false) 223 stack.add(element) 224 return element.iValue.toInt() 225 } 226 227 /** 228 * Adds a [IntArray] into the message as a typed vector of fixed size. 229 * @param value [IntArray] 230 * @return position in buffer as the start of byte array 231 */ putnull232 public fun put(value: IntArray): Int = set(null, value) 233 234 /** 235 * Adds a [IntArray] into the message as a typed vector of fixed size. 236 * A key must be present if element is inserted into a map. 237 * @param value [IntArray] 238 * @return position in buffer as the start of byte array 239 */ 240 public operator fun set(key: String? = null, value: IntArray): Int = 241 setTypedVector(key, value.size, T_VECTOR_INT, value.widthInUBits()) { writeIntArray(value, it) } 242 243 /** 244 * Adds a [ShortArray] into the message as a typed vector of fixed size. 245 * @param value [ShortArray] 246 * @return position in buffer as the start of byte array 247 */ putnull248 public fun put(value: ShortArray): Int = set(null, value) 249 250 /** 251 * Adds a [ShortArray] into the message as a typed vector of fixed size. 252 * A key must be present if element is inserted into a map. 253 * @param value [ShortArray] 254 * @return position in buffer as the start of byte array 255 */ 256 public operator fun set(key: String? = null, value: ShortArray): Int = 257 setTypedVector(key, value.size, T_VECTOR_INT, value.widthInUBits()) { writeIntArray(value, it) } 258 259 /** 260 * Adds a [LongArray] into the message as a typed vector of fixed size. 261 * @param value [LongArray] 262 * @return position in buffer as the start of byte array 263 */ putnull264 public fun put(value: LongArray): Int = set(null, value) 265 266 /** 267 * Adds a [LongArray] into the message as a typed vector of fixed size. 268 * A key must be present if element is inserted into a map. 269 * @param value [LongArray] 270 * @return position in buffer as the start of byte array 271 */ 272 public operator fun set(key: String? = null, value: LongArray): Int = 273 setTypedVector(key, value.size, T_VECTOR_INT, value.widthInUBits()) { writeIntArray(value, it) } 274 275 /** 276 * Adds a [FloatArray] into the message as a typed vector of fixed size. 277 * @param value [FloatArray] 278 * @return position in buffer as the start of byte array 279 */ putnull280 public fun put(value: FloatArray): Int = set(null, value) 281 282 /** 283 * Adds a [FloatArray] into the message as a typed vector of fixed size. 284 * A key must be present if element is inserted into a map. 285 * @param value [FloatArray] 286 * @return position in buffer as the start of byte array 287 */ 288 public operator fun set(key: String? = null, value: FloatArray): Int = 289 setTypedVector(key, value.size, T_VECTOR_FLOAT, W_32) { writeFloatArray(value) } 290 291 /** 292 * Adds a [DoubleArray] into the message as a typed vector of fixed size. 293 * @param value [DoubleArray] 294 * @return position in buffer as the start of byte array 295 */ putnull296 public fun put(value: DoubleArray): Int = set(null, value) 297 298 /** 299 * Adds a [DoubleArray] into the message as a typed vector of fixed size. 300 * A key must be present if element is inserted into a map. 301 * @param value [DoubleArray] 302 * @return position in buffer as the start of byte array 303 */ 304 public operator fun set(key: String? = null, value: DoubleArray): Int = 305 setTypedVector(key, value.size, T_VECTOR_FLOAT, W_64) { writeFloatArray(value) } 306 307 /** 308 * Adds a [UByteArray] into the message as a typed vector of fixed size. 309 * @param value [UByteArray] 310 * @return position in buffer as the start of byte array 311 */ putnull312 public fun put(value: UByteArray): Int = set(null, value) 313 314 /** 315 * Adds a [UByteArray] into the message as a typed vector of fixed size. 316 * A key must be present if element is inserted into a map. 317 * @param value [UByteArray] 318 * @return position in buffer as the start of byte array 319 */ 320 public operator fun set(key: String? = null, value: UByteArray): Int = 321 setTypedVec(key) { value.forEach { put(it) } } 322 323 /** 324 * Adds a [UShortArray] into the message as a typed vector of fixed size. 325 * @param value [UShortArray] 326 * @return position in buffer as the start of byte array 327 */ putnull328 public fun put(value: UShortArray): Int = set(null, value) 329 330 /** 331 * Adds a [UShortArray] into the message as a typed vector of fixed size. 332 * A key must be present if element is inserted into a map. 333 * @param value [UShortArray] 334 * @return position in buffer as the start of byte array 335 */ 336 public operator fun set(key: String? = null, value: UShortArray): Int = 337 setTypedVec(key) { value.forEach { put(it) } } 338 339 /** 340 * Adds a [UIntArray] into the message as a typed vector of fixed size. 341 * @param value [UIntArray] 342 * @return position in buffer as the start of byte array 343 */ putnull344 public fun put(value: UIntArray): Int = set(null, value) 345 346 /** 347 * Adds a [UIntArray] into the message as a typed vector of fixed size. 348 * A key must be present if element is inserted into a map. 349 * @param value [UIntArray] 350 * @return position in buffer as the start of byte array 351 */ 352 public fun set(key: String? = null, value: UIntArray): Int = 353 setTypedVec(key) { value.forEach { put(it) } } 354 355 /** 356 * Adds a [ULongArray] into the message as a typed vector of fixed size. 357 * @param value [ULongArray] 358 * @return position in buffer as the start of byte array 359 */ putnull360 public fun put(value: ULongArray): Int = set(null, value) 361 362 /** 363 * Adds a [ULongArray] into the message as a typed vector of fixed size. 364 * A key must be present if element is inserted into a map. 365 * @param value [ULongArray] 366 * @return position in buffer as the start of byte array 367 */ 368 public operator fun set(key: String? = null, value: ULongArray): Int = 369 setTypedVec(key) { value.forEach { put(it) } } 370 371 /** 372 * Creates a new vector will all elements inserted in [block]. 373 * @param block where elements will be inserted 374 * @return position in buffer as the start of byte array 375 */ putVectornull376 public inline fun putVector(crossinline block: FlexBuffersBuilder.() -> Unit): Int { 377 val pos = startVector() 378 this.block() 379 return endVector(pos) 380 } 381 382 /** 383 * Creates a new typed vector will all elements inserted in [block]. 384 * @param block where elements will be inserted 385 * @return position in buffer as the start of byte array 386 */ putTypedVectornull387 public inline fun putTypedVector(crossinline block: FlexBuffersBuilder.() -> Unit): Int { 388 val pos = startVector() 389 this.block() 390 return endTypedVector(pos) 391 } 392 393 /** 394 * Helper function to return position for starting a new vector. 395 */ startVectornull396 public fun startVector(): Int = stack.size 397 398 /** 399 * Finishes a vector element. The initial position of the vector must be passed 400 * @param position position at the start of the vector 401 */ 402 public fun endVector(position: Int): Int = endVector(null, position) 403 404 /** 405 * Finishes a vector element. The initial position of the vector must be passed 406 * @param position position at the start of the vector 407 */ 408 public fun endVector(key: String? = null, position: Int): Int = 409 endAnyVector(position) { createVector(putKey(key), position, stack.size - position) } 410 /** 411 * Finishes a typed vector element. The initial position of the vector must be passed 412 * @param position position at the start of the vector 413 */ endTypedVectornull414 public fun endTypedVector(position: Int): Int = endTypedVector(position, null) 415 416 /** 417 * Helper function to return position for starting a new vector. 418 */ 419 public fun startMap(): Int = stack.size 420 421 /** 422 * Creates a new map will all elements inserted in [block]. 423 * @param block where elements will be inserted 424 * @return position in buffer as the start of byte array 425 */ 426 public inline fun putMap(key: String? = null, crossinline block: FlexBuffersBuilder.() -> Unit): Int { 427 val pos = startMap() 428 this.block() 429 return endMap(pos, key) 430 } 431 432 /** 433 * Finishes a map, but writing the information in the buffer 434 * @param key key used to store element in map 435 * @return Reference to the map 436 */ endMapnull437 public fun endMap(start: Int, key: String? = null): Int { 438 stack.subList(start, stack.size).sortWith(keyComparator) 439 val length = stack.size - start 440 val keys = createKeyVector(start, length) 441 val vec = putMap(putKey(key), start, length, keys) 442 // Remove temp elements and return map. 443 while (stack.size > start) { 444 stack.removeAt(stack.size - 1) 445 } 446 stack.add(vec) 447 return vec.iValue.toInt() 448 } 449 setTypedVectornull450 private inline fun setTypedVector( 451 key: String? = null, 452 length: Int, 453 vecType: FlexBufferType, 454 bitWidth: BitWidth, 455 crossinline writeBlock: (ByteWidth) -> Unit 456 ): Int { 457 val keyPos = putKey(key) 458 val byteWidth = align(bitWidth) 459 // Write vector. First the keys width/offset if available, and size. 460 // write the size 461 writeInt(length, byteWidth) 462 463 // Then the actual data. 464 val vloc: Int = buffer.writePosition 465 writeBlock(byteWidth) 466 stack.add(Value(vecType, keyPos, bitWidth, vloc.toULong())) 467 return vloc 468 } 469 setTypedVecnull470 private inline fun setTypedVec(key: String? = null, crossinline block: FlexBuffersBuilder.() -> Unit): Int { 471 val pos = startVector() 472 this.block() 473 return endTypedVector(pos, key) 474 } 475 endTypedVectornull476 public fun endTypedVector(position: Int, key: String? = null): Int = 477 endAnyVector(position) { createTypedVector(putKey(key), position, stack.size - position) } 478 endAnyVectornull479 private inline fun endAnyVector(start: Int, crossinline creationBlock: () -> Value): Int { 480 val vec = creationBlock() 481 // Remove temp elements and return vector. 482 while (stack.size > start) { 483 stack.removeLast() 484 } 485 stack.add(vec) 486 return vec.iValue.toInt() 487 } 488 putKeynull489 private inline fun putKey(key: String? = null): Int { 490 if (key == null) return -1 491 return if ((shareFlag and SHARE_KEYS) != 0) { 492 stringKeyPool.getOrPut(key) { 493 val pos: Int = buffer.writePosition 494 buffer.put(key) 495 buffer.put(ZeroByte) 496 pos 497 } 498 } else { 499 val pos: Int = buffer.writePosition 500 buffer.put(key) 501 buffer.put(ZeroByte) 502 pos 503 } 504 } 505 writeAnynull506 private fun writeAny(toWrite: Value, byteWidth: ByteWidth) = when (toWrite.type) { 507 T_NULL, T_BOOL, T_INT, T_UINT -> writeInt(toWrite.iValue, byteWidth) 508 T_FLOAT -> writeDouble(toWrite.dValue, byteWidth) 509 else -> writeOffset(toWrite.iValue.toInt(), byteWidth) 510 } 511 writeStringnull512 private fun writeString(key: Int, s: String): Value { 513 val size = Utf8.encodedLength(s) 514 val bitWidth = size.toULong().widthInUBits() 515 val byteWidth = align(bitWidth) 516 517 writeInt(size, byteWidth) 518 519 val sloc: Int = buffer.writePosition 520 if (size > 0) 521 buffer.put(s, size) 522 buffer.put(ZeroByte) 523 return Value(T_STRING, key, bitWidth, sloc.toULong()) 524 } 525 writeDoublenull526 private fun writeDouble(toWrite: Double, byteWidth: ByteWidth): Unit = when (byteWidth.value) { 527 4 -> buffer.put(toWrite.toFloat()) 528 8 -> buffer.put(toWrite) 529 else -> Unit 530 } 531 writeOffsetnull532 private fun writeOffset(toWrite: Int, byteWidth: ByteWidth) { 533 val relativeOffset = (buffer.writePosition - toWrite) 534 if (byteWidth.value != 8 && relativeOffset >= 1L shl byteWidth.value * 8) error("invalid offset $relativeOffset, writer pos ${buffer.writePosition}") 535 writeInt(relativeOffset, byteWidth) 536 } 537 writeBlobnull538 private inline fun writeBlob(key: Int, blob: ByteArray, type: FlexBufferType, trailing: Boolean): Value { 539 val bitWidth = blob.size.toULong().widthInUBits() 540 val byteWidth = align(bitWidth) 541 542 writeInt(blob.size, byteWidth) 543 544 val sloc: Int = buffer.writePosition 545 buffer.put(blob, 0, blob.size) 546 if (trailing) { 547 buffer.put(ZeroByte) 548 } 549 return Value(type, key, bitWidth, sloc.toULong()) 550 } 551 writeIntArraynull552 private fun writeIntArray(value: IntArray, byteWidth: ByteWidth) = 553 writeIntegerArray(0, value.size, byteWidth) { value[it].toULong() } 554 writeIntArraynull555 private fun writeIntArray(value: ShortArray, byteWidth: ByteWidth) = 556 writeIntegerArray(0, value.size, byteWidth) { value[it].toULong() } 557 writeIntArraynull558 private fun writeIntArray(value: LongArray, byteWidth: ByteWidth) = 559 writeIntegerArray(0, value.size, byteWidth) { value[it].toULong() } 560 writeFloatArraynull561 private fun writeFloatArray(value: FloatArray) { 562 val byteWidth = Float.SIZE_BYTES 563 // since we know we are writing an array, we can avoid multiple copy/growth of the buffer by requesting 564 // the right size on the spot 565 buffer.requestCapacity(buffer.writePosition + (value.size * byteWidth)) 566 value.forEach { buffer.put(it) } 567 } 568 writeFloatArraynull569 private fun writeFloatArray(value: DoubleArray) { 570 val byteWidth = Double.SIZE_BYTES 571 // since we know we are writing an array, we can avoid multiple copy/growth of the buffer by requesting 572 // the right size on the spot 573 buffer.requestCapacity(buffer.writePosition + (value.size * byteWidth)) 574 value.forEach { buffer.put(it) } 575 } 576 writeIntegerArraynull577 private inline fun writeIntegerArray( 578 start: Int, 579 size: Int, 580 byteWidth: ByteWidth, 581 crossinline valueBlock: (Int) -> ULong 582 ) { 583 // since we know we are writing an array, we can avoid multiple copy/growth of the buffer by requesting 584 // the right size on the spot 585 buffer.requestCapacity(buffer.writePosition + (size * byteWidth)) 586 return when (byteWidth.value) { 587 1 -> for (i in start until start + size) { 588 buffer.put(valueBlock(i).toUByte()) 589 } 590 2 -> for (i in start until start + size) { 591 buffer.put(valueBlock(i).toUShort()) 592 } 593 4 -> for (i in start until start + size) { 594 buffer.put(valueBlock(i).toUInt()) 595 } 596 8 -> for (i in start until start + size) { 597 buffer.put(valueBlock(i)) 598 } 599 else -> Unit 600 } 601 } 602 writeIntnull603 private fun writeInt(value: Int, byteWidth: ByteWidth) = when (byteWidth.value) { 604 1 -> buffer.put(value.toUByte()) 605 2 -> buffer.put(value.toUShort()) 606 4 -> buffer.put(value.toUInt()) 607 8 -> buffer.put(value.toULong()) 608 else -> Unit 609 } 610 writeIntnull611 private fun writeInt(value: ULong, byteWidth: ByteWidth) = when (byteWidth.value) { 612 1 -> buffer.put(value.toUByte()) 613 2 -> buffer.put(value.toUShort()) 614 4 -> buffer.put(value.toUInt()) 615 8 -> buffer.put(value) 616 else -> Unit 617 } 618 619 // Align to prepare for writing a scalar with a certain size. 620 // returns the amounts of bytes needed to be written. alignnull621 private fun align(alignment: BitWidth): ByteWidth { 622 val byteWidth = 1 shl alignment.value 623 var padBytes = paddingBytes(buffer.writePosition, byteWidth) 624 while (padBytes-- != 0) { 625 buffer.put(ZeroByte) 626 } 627 return ByteWidth(byteWidth) 628 } 629 calculateKeyVectorBitWidthnull630 private fun calculateKeyVectorBitWidth(start: Int, length: Int): BitWidth { 631 val bitWidth = length.toULong().widthInUBits() 632 var width = bitWidth 633 val prefixElems = 1 634 // Check bit widths and types for all elements. 635 for (i in start until stack.size) { 636 val elemWidth = elemWidth(T_KEY, W_8, stack[i].key.toLong(), buffer.writePosition, i + prefixElems) 637 width = width.max(elemWidth) 638 } 639 return width 640 } 641 createKeyVectornull642 private fun createKeyVector(start: Int, length: Int): Value { 643 // Figure out smallest bit width we can store this vector with. 644 val bitWidth = calculateKeyVectorBitWidth(start, length) 645 val byteWidth = align(bitWidth) 646 // Write vector. First the keys width/offset if available, and size. 647 writeInt(length, byteWidth) 648 // Then the actual data. 649 val vloc = buffer.writePosition.toULong() 650 for (i in start until stack.size) { 651 val pos = stack[i].key 652 if (pos == -1) error("invalid position $pos for key") 653 writeOffset(stack[i].key, byteWidth) 654 } 655 // Then the types. 656 return Value(T_VECTOR_KEY, -1, bitWidth, vloc) 657 } 658 createVectornull659 private inline fun createVector(key: Int, start: Int, length: Int, keys: Value? = null): Value { 660 return createAnyVector(key, start, length, T_VECTOR, keys) { 661 // add types since we are not creating a typed vector. 662 for (i in start until stack.size) { 663 buffer.put(stack[i].storedPackedType(it)) 664 } 665 } 666 } 667 putMapnull668 private fun putMap(key: Int, start: Int, length: Int, keys: Value? = null): Value { 669 return createAnyVector(key, start, length, T_MAP, keys) { 670 // add types since we are not creating a typed vector. 671 for (i in start until stack.size) { 672 buffer.put(stack[i].storedPackedType(it)) 673 } 674 } 675 } 676 createTypedVectornull677 private inline fun createTypedVector(key: Int, start: Int, length: Int, keys: Value? = null): Value { 678 // We assume the callers of this method guarantees all elements are of the same type. 679 val elementType: FlexBufferType = stack[start].type 680 for (i in start + 1 until length) { 681 if (elementType != stack[i].type) error("TypedVector does not support array of different element types") 682 } 683 if (!elementType.isTypedVectorElementType()) error("TypedVector does not support this element type") 684 return createAnyVector(key, start, length, elementType.toTypedVector(), keys) 685 } 686 createAnyVectornull687 private inline fun createAnyVector( 688 key: Int, 689 start: Int, 690 length: Int, 691 type: FlexBufferType, 692 keys: Value? = null, 693 crossinline typeBlock: (BitWidth) -> Unit = {} 694 ): Value { 695 // Figure out smallest bit width we can store this vector with. 696 var bitWidth = W_8.max(length.toULong().widthInUBits()) 697 var prefixElems = 1 698 if (keys != null) { 699 // If this vector is part of a map, we will pre-fix an offset to the keys 700 // to this vector. 701 bitWidth = bitWidth.max(keys.elemWidth(buffer.writePosition, 0)) 702 prefixElems += 2 703 } 704 // Check bit widths and types for all elements. 705 for (i in start until stack.size) { 706 val elemWidth = stack[i].elemWidth(buffer.writePosition, i + prefixElems) 707 bitWidth = bitWidth.max(elemWidth) 708 } 709 val byteWidth = align(bitWidth) 710 // Write vector. First the keys width/offset if available, and size. 711 if (keys != null) { 712 writeOffset(keys.iValue.toInt(), byteWidth) 713 writeInt(1 shl keys.minBitWidth.value, byteWidth) 714 } 715 // write the size 716 writeInt(length, byteWidth) 717 718 // Then the actual data. 719 val vloc: Int = buffer.writePosition 720 for (i in start until stack.size) { 721 writeAny(stack[i], byteWidth) 722 } 723 724 // Optionally you can introduce the types for non-typed vector 725 typeBlock(bitWidth) 726 return Value(type, key, bitWidth, vloc.toULong()) 727 } 728 729 // A lambda to sort map keys 730 internal val keyComparator = object : Comparator<Value> { comparenull731 override fun compare(a: Value, b: Value): Int { 732 var ia: Int = a.key 733 var io: Int = b.key 734 var c1: Byte 735 var c2: Byte 736 do { 737 c1 = buffer[ia] 738 c2 = buffer[io] 739 if (c1.toInt() == 0) return c1 - c2 740 ia++ 741 io++ 742 } while (c1 == c2) 743 return c1 - c2 744 } 745 } 746 747 public companion object { 748 /** 749 * No keys or strings will be shared 750 */ 751 public const val SHARE_NONE: Int = 0 752 753 /** 754 * Keys will be shared between elements. Identical keys will only be serialized once, thus possibly saving space. 755 * But serialization performance might be slower and consumes more memory. 756 */ 757 public const val SHARE_KEYS: Int = 1 758 759 /** 760 * Strings will be shared between elements. Identical strings will only be serialized once, thus possibly saving space. 761 * But serialization performance might be slower and consumes more memory. This is ideal if you expect many repeated 762 * strings on the message. 763 */ 764 public const val SHARE_STRINGS: Int = 2 765 766 /** 767 * Strings and keys will be shared between elements. 768 */ 769 public const val SHARE_KEYS_AND_STRINGS: Int = 3 770 } 771 } 772