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 package com.google.flatbuffers.kotlin 17 18 import kotlin.math.max 19 import kotlin.math.min 20 21 /** 22 * Represent a chunk of data, where FlexBuffers will be read from. 23 */ 24 public interface ReadBuffer { 25 26 /** 27 * Scan through the buffer for first byte matching value. 28 * @param value to be match 29 * @param start inclusive initial position to start searching 30 * @param end exclusive final position of the search 31 * @return position of a match or -1 32 */ findFirstnull33 public fun findFirst(value: Byte, start: Int, end: Int = limit): Int 34 35 /** 36 * Read boolean from the buffer. Booleans as stored as a single byte 37 * @param index position of the element in [ReadBuffer] 38 * @return [Boolean] element 39 */ 40 public fun getBoolean(index: Int): Boolean 41 42 /** 43 * Read a [Byte] from the buffer. 44 * @param index position of the element in [ReadBuffer] 45 * @return a byte 46 */ 47 public operator fun get(index: Int): Byte 48 49 /** 50 * Read a [UByte] from the buffer. 51 * @param index position of the element in [ReadBuffer] 52 * @return a [UByte] 53 */ 54 public fun getUByte(index: Int): UByte 55 56 /** 57 * Read a [Short] from the buffer. 58 * @param index position of the element in [ReadBuffer] 59 * @return a [Short] 60 */ 61 public fun getShort(index: Int): Short 62 63 /** 64 * Read a [UShort] from the buffer. 65 * @param index position of the element in [ReadBuffer] 66 * @return a [UShort] 67 */ 68 public fun getUShort(index: Int): UShort 69 70 /** 71 * Read a [Int] from the buffer. 72 * @param index position of the element in [ReadBuffer] 73 * @return an [Int] 74 */ 75 public fun getInt(index: Int): Int 76 77 /** 78 * Read a [UInt] from the buffer. 79 * @param index position of the element in [ReadBuffer] 80 * @return an [UInt] 81 */ 82 public fun getUInt(index: Int): UInt 83 84 /** 85 * Read a [Long] from the buffer. 86 * @param index position of the element in [ReadBuffer] 87 * @return a [Long] 88 */ 89 public fun getLong(index: Int): Long 90 91 /** 92 * Read a [ULong] from the buffer. 93 * @param index position of the element in [ReadBuffer] 94 * @return a [ULong] 95 */ 96 public fun getULong(index: Int): ULong 97 98 /** 99 * Read a 32-bit float from the buffer. 100 * @param index position of the element in [ReadBuffer] 101 * @return a float 102 */ 103 public fun getFloat(index: Int): Float 104 105 /** 106 * Read a 64-bit float from the buffer. 107 * @param index position of the element in [ReadBuffer] 108 * @return a double 109 */ 110 public fun getDouble(index: Int): Double 111 112 /** 113 * Read a UTF-8 string from the buffer. 114 * @param start initial element of the string 115 * @param size size of the string in bytes. 116 * @return a `String` 117 */ 118 public fun getString(start: Int = 0, size: Int = limit): String 119 120 /** 121 * Read a ByteArray from the buffer. 122 * @param start position from the [ReadBuffer] to be read 123 * @param length maximum number of bytes to be written in the buffer 124 */ 125 public fun getBytes(array: ByteArray, start: Int, length: Int = array.size) 126 127 /** 128 * Expose [ReadBuffer] as an array of bytes. 129 * This method is meant to be as efficient as possible, so for an array-backed [ReadBuffer], it should 130 * return its own internal data. In case access to internal data is not possible, 131 * a copy of the data into an array of bytes might occur. 132 * @return [ReadBuffer] as an array of bytes 133 */ 134 public fun data(): ByteArray 135 136 /** 137 * Creates a new [ReadBuffer] point to a region of the current buffer, starting at [start] with size [size]. 138 * @param start starting position of the [ReadBuffer] 139 * @param size in bytes of the [ReadBuffer] 140 * @return [ReadBuffer] slice. 141 */ 142 public fun slice(start: Int, size: Int): ReadBuffer 143 144 /** 145 * Defines the size of the message in the buffer. It also determines last position that buffer 146 * can be read. Last byte to be accessed is in position `limit() -1`. 147 * @return indicate last position 148 */ 149 public val limit: Int 150 } 151 152 /** 153 * Interface to represent a read-write buffers. This interface will be used to access and write FlexBuffer messages. 154 */ 155 public interface ReadWriteBuffer : ReadBuffer { 156 /** 157 * Clears (resets) the buffer so that it can be reused. Write position will be set to the start. 158 */ 159 public fun clear() 160 161 /** 162 * Request capacity of the buffer relative to [writePosition]. In case buffer is already larger 163 * than the requested, this method will just return true. Otherwise, 164 * It might try to resize the buffer. In case of being unable to allocate 165 * enough memory, an exception will be thrown. 166 * @param additional capacity in bytes to be added on top of [writePosition] 167 * @param copyAtEnd copy current data at the end of new underlying buffer 168 * @return new capacity in bytes 169 */ 170 public fun requestAdditionalCapacity(additional: Int, copyAtEnd: Boolean = false): Int = 171 requestCapacity(writePosition + additional, copyAtEnd) 172 173 /** 174 * Request capacity of the buffer in absolute values. In case buffer is already larger 175 * than the requested the method is a no-op. Otherwise, 176 * It might try to resize the buffer. In case of being unable to allocate 177 * enough memory, an exception will be thrown. 178 * @param capacity new capacity 179 * @param copyAtEnd copy current data at the end of new underlying buffer 180 * @return new capacity in bytes 181 */ 182 public fun requestCapacity(capacity: Int, copyAtEnd: Boolean = false): Int 183 184 /** 185 * Put a [Boolean] into the buffer at [writePosition] . Booleans as stored as single byte. 186 * Write position will be incremented. 187 * @return [Boolean] element 188 */ 189 public fun put(value: Boolean) 190 191 /** 192 * Put an array of bytes into the buffer at [writePosition]. Write position will be incremented. 193 * @param value the data to be copied 194 * @param start initial position on value to be copied 195 * @param length amount of bytes to be copied 196 */ 197 public fun put(value: ByteArray, start: Int = 0, length: Int = value.size) 198 199 /** 200 * Put an array of bytes into the buffer at [writePosition]. Write position will be incremented. 201 * @param value [ReadBuffer] the data to be copied 202 * @param start initial position on value to be copied 203 * @param length amount of bytes to be copied 204 */ 205 public fun put(value: ReadBuffer, start: Int = 0, length: Int = value.limit - start) 206 207 /** 208 * Write a [Byte] into the buffer at [writePosition]. Write position will be incremented. 209 */ 210 public fun put(value: Byte) 211 212 /** 213 * Write a [UByte] into the buffer at [writePosition]. Write position will be incremented. 214 */ 215 public fun put(value: UByte) 216 217 /** 218 * Write a [Short] into in the buffer at [writePosition]. Write position will be incremented. 219 */ 220 public fun put(value: Short) 221 222 /** 223 * Write a [UShort] into in the buffer at [writePosition]. Write position will be incremented. 224 */ 225 public fun put(value: UShort) 226 227 /** 228 * Write a [Int] in the buffer at [writePosition]. Write position will be incremented. 229 */ 230 public fun put(value: Int) 231 232 /** 233 * Write a [UInt] into in the buffer at [writePosition]. Write position will be incremented. 234 */ 235 public fun put(value: UInt) 236 237 /** 238 * Write a [Long] into in the buffer at [writePosition]. Write position will be 239 * incremented. 240 */ 241 public fun put(value: Long) 242 243 /** 244 * Write a [ULong] into in the buffer at [writePosition]. Write position will be 245 * incremented. 246 */ 247 public fun put(value: ULong) 248 249 /** 250 * Write a 32-bit [Float] into the buffer at [writePosition]. Write position will be 251 * incremented. 252 */ 253 public fun put(value: Float) 254 255 /** 256 * Write a 64-bit [Double] into the buffer at [writePosition]. Write position will be 257 * incremented. 258 */ 259 public fun put(value: Double) 260 261 /** 262 * Write a [String] encoded as UTF-8 into the buffer at [writePosition]. Write position will be incremented. 263 * @return size in bytes of the encoded string 264 */ 265 public fun put(value: CharSequence, encodedLength: Int = -1): Int 266 267 /** 268 * Write an array of bytes into the buffer. 269 * @param dstIndex initial position where [src] will be copied into. 270 * @param src the data to be copied. 271 * @param srcStart initial position on [src] that will be copied. 272 * @param srcLength amount of bytes to be copied 273 */ 274 public fun set(dstIndex: Int, src: ByteArray, srcStart: Int = 0, srcLength: Int = src.size) 275 276 /** 277 * Write an array of bytes into the buffer. 278 * @param dstIndex initial position where [src] will be copied into. 279 * @param src the data to be copied. 280 * @param srcStart initial position on [src] that will be copied. 281 * @param srcLength amount of bytes to be copied 282 */ 283 public operator fun set(dstIndex: Int, src: ReadBuffer, srcStart: Int = 0, srcLength: Int) 284 285 /** 286 * Write [Boolean] into a given position [index] on the buffer. Booleans as stored as single byte. 287 * @param index position of the element in buffer 288 */ 289 public operator fun set(index: Int, value: Boolean) 290 291 /** 292 * Write [Byte] into a given position [index] on the buffer. 293 * @param index position of the element in the buffer 294 */ 295 public operator fun set(index: Int, value: Byte) 296 297 /** 298 * Write [UByte] into a given position [index] on the buffer. 299 * @param index position of the element in the buffer 300 */ 301 public operator fun set(index: Int, value: UByte) 302 303 /** 304 Short 305 * @param index position of the element in [ReadBuffer] 306 */ 307 public fun set(index: Int, value: Short) 308 309 /** 310 * Write [UShort] into a given position [index] on the buffer. 311 * @param index position of the element in [ReadBuffer] 312 */ 313 public fun set(index: Int, value: UShort) 314 315 /** 316 * Write [Int] into a given position [index] on the buffer. 317 * @param index position of the element in [ReadBuffer] 318 */ 319 public fun set(index: Int, value: Int) 320 321 /** 322 * Write [UInt] into a given position [index] on the buffer. 323 * @param index position of the element in [ReadBuffer] 324 */ 325 public fun set(index: Int, value: UInt) 326 327 /** 328 * Write [Long] into a given position [index] on the buffer. 329 * @param index position of the element in [ReadBuffer] 330 */ 331 public fun set(index: Int, value: Long) 332 333 /** 334 * Write [ULong] into a given position [index] on the buffer. 335 * @param index position of the element in [ReadBuffer] 336 */ 337 public fun set(index: Int, value: ULong) 338 339 /** 340 * Write [Float] into a given position [index] on the buffer. 341 * @param index position of the element in [ReadBuffer] 342 */ 343 public fun set(index: Int, value: Float) 344 345 /** 346 * Write [Double] into a given position [index] on the buffer. 347 * @param index position of the element in [ReadBuffer] 348 */ 349 public fun set(index: Int, value: Double) 350 351 public fun fill(value: Byte, start: Int, end: Int) 352 353 /** 354 * Current position of the buffer to be written. It will be automatically updated on [put] operations. 355 */ 356 public var writePosition: Int 357 358 /** 359 * Creates a new [ReadWriteBuffer] point to a region of the current buffer, starting at [offset] with size [size]. 360 * @param offset starting position of the [ReadWriteBuffer] 361 * @param size in bytes of the [ReadWriteBuffer] 362 * @return [ReadWriteBuffer] slice. 363 */ 364 public fun writeSlice(offset: Int, size: Int): ReadWriteBuffer 365 366 /** 367 * Special operation where we increase the backed buffer size to [capacity] 368 * and shift all already written data to the end of the buffer. 369 * 370 * This function is mostly used when creating a Flatbuffer message, as 371 * data is written from the end of the buffer towards index 0. 372 * @param capacity required in bytes 373 * @return new capacity in bytes 374 */ 375 public fun moveWrittenDataToEnd(capacity: Int): Int 376 377 /** 378 * Maximum size in bytes that the backed buffer supports. 379 */ 380 public val capacity: Int 381 382 /** 383 * Defines last relative position of the backed buffer that can be written. 384 * Any addition to the buffer that goes beyond will throw an exception 385 * instead of regrow the buffer (default behavior). 386 */ 387 public val writeLimit: Int 388 } 389 390 public open class ArrayReadBuffer(protected var buffer: ByteArray, 391 // offsets writePosition against backed buffer e.g. offset = 1, writePosition = 1 392 // will write first byte at position 2 of the backed buffer 393 internal val offset: Int = 0, 394 override val limit: Int = buffer.size - offset) : ReadBuffer { 395 396 findFirstnull397 override fun findFirst(value: Byte, start: Int, end: Int): Int { 398 val e = min(end, limit) 399 val s = max(0, this.offset + start) 400 for (i in s until e) if (buffer[i] == value) return i 401 return -1 402 } 403 getBooleannull404 override fun getBoolean(index: Int): Boolean = buffer[offset + index] != 0.toByte() 405 406 override operator fun get(index: Int): Byte = buffer[offset + index] 407 408 override fun getUByte(index: Int): UByte = buffer.getUByte(offset + index) 409 410 override fun getShort(index: Int): Short = buffer.getShort(offset + index) 411 412 override fun getUShort(index: Int): UShort = buffer.getUShort(offset + index) 413 414 override fun getInt(index: Int): Int = buffer.getInt(offset + index) 415 416 override fun getUInt(index: Int): UInt = buffer.getUInt(offset + index) 417 418 override fun getLong(index: Int): Long = buffer.getLong(offset + index) 419 420 override fun getULong(index: Int): ULong = buffer.getULong(offset + index) 421 422 override fun getFloat(index: Int): Float = buffer.getFloat(offset + index) 423 424 override fun getDouble(index: Int): Double = buffer.getDouble(offset + index) 425 426 override fun getString(start: Int, size: Int): String = buffer.decodeToString(this.offset + start, 427 this.offset + start + size) 428 429 override fun getBytes(array: ByteArray, start: Int, length: Int) { 430 val end = min(this.offset + start + length, buffer.size) 431 var j = 0 432 for (i in this.offset + start until end) { 433 array[j++] = buffer[i] 434 } 435 } 436 datanull437 override fun data(): ByteArray = buffer 438 439 override fun slice(start: Int, size: Int): ReadBuffer = ArrayReadBuffer(buffer, this.offset + start, size) 440 } 441 /** 442 * Implements `[ReadWriteBuffer]` using [ByteArray] as backing buffer. Using array of bytes are 443 * usually faster than `ByteBuffer`. 444 * 445 * This class is not thread-safe, meaning that 446 * it must operate on a single thread. Operating from 447 * multiple thread leads into an undefined behavior 448 * 449 * All operations assume Little Endian byte order. 450 */ 451 452 public class ArrayReadWriteBuffer( 453 buffer: ByteArray, 454 offset: Int = 0, 455 // Defines last position of the backed buffer that can be written. 456 // Any addition to the buffer that goes beyond will throw an exception 457 // instead of regrow the buffer (default behavior). 458 public override val writeLimit: Int = -1, 459 override var writePosition: Int = offset 460 ) : ArrayReadBuffer(buffer, offset, writePosition), ReadWriteBuffer { 461 462 public constructor(initialCapacity: Int = 10) : this(ByteArray(initialCapacity)) 463 464 override val limit: Int get() = writePosition 465 466 override fun clear(): Unit = run { writePosition = 0 } 467 468 override fun put(value: Boolean) { 469 set(writePosition, value) 470 writePosition++ 471 } 472 473 override fun put(value: ByteArray, start: Int, length: Int) { 474 set(writePosition, value, start, length) 475 writePosition += length 476 } 477 478 override fun put(value: ReadBuffer, start: Int, length: Int) { 479 set(writePosition, value, start, length) 480 writePosition += length 481 } 482 483 override fun put(value: Byte) { 484 set(writePosition, value) 485 writePosition++ 486 } 487 488 override fun put(value: UByte) { 489 set(writePosition, value) 490 writePosition++ 491 } 492 493 override fun put(value: Short) { 494 set(writePosition, value) 495 writePosition += 2 496 } 497 498 override fun put(value: UShort) { 499 set(writePosition, value) 500 writePosition += 2 501 } 502 503 override fun put(value: Int) { 504 set(writePosition, value) 505 writePosition += 4 506 } 507 508 override fun put(value: UInt) { 509 set(writePosition, value) 510 writePosition += 4 511 } 512 513 override fun put(value: Long) { 514 set(writePosition, value) 515 writePosition += 8 516 } 517 518 override fun put(value: ULong) { 519 set(writePosition, value) 520 writePosition += 8 521 } 522 523 override fun put(value: Float) { 524 set(writePosition, value) 525 writePosition += 4 526 } 527 528 override fun put(value: Double) { 529 set(writePosition, value) 530 writePosition += 8 531 } 532 533 override fun put(value: CharSequence, encodedLength: Int): Int { 534 val length = if (encodedLength != -1) encodedLength else Utf8.encodedLength(value) 535 writePosition = buffer.setCharSequence(writePosition, value) 536 return length 537 } 538 539 override fun set(index: Int, value: Boolean) { 540 buffer[index] = if (value) 1.toByte() else 0.toByte() 541 } 542 543 override fun set(dstIndex: Int, src: ByteArray, srcStart: Int, srcLength: Int) { 544 src.copyInto(buffer, dstIndex, srcStart, srcStart + srcLength) 545 } 546 547 override operator fun set(dstIndex: Int, src: ReadBuffer, srcStart: Int, srcLength: Int) { 548 when(src) { 549 is ArrayReadBuffer -> { 550 src.data().copyInto(buffer, dstIndex, src.offset + srcStart, src.offset + srcStart + srcLength) 551 } 552 else -> { 553 for (i in 0 until srcLength) { 554 buffer[dstIndex + i] = src[srcStart + i] 555 } 556 } 557 } 558 } 559 560 override operator fun set(index: Int, value: Byte) { buffer[index] = value } 561 override operator fun set(index: Int, value: UByte) { buffer.setUByte(index, value) } 562 override operator fun set(index: Int, value: Short) { buffer.setShort(index, value) } 563 override operator fun set(index: Int, value: UShort) { buffer.setUShort(index, value) } 564 override operator fun set(index: Int, value: Int) { buffer.setInt(index, value) } 565 override operator fun set(index: Int, value: UInt) { buffer.setUInt(index, value) } 566 override operator fun set(index: Int, value: Long) { buffer.setLong(index, value) } 567 override operator fun set(index: Int, value: ULong) { buffer.setULong(index, value) } 568 override operator fun set(index: Int, value: Float) { buffer.setFloat(index, value) } 569 override operator fun set(index: Int, value: Double) { buffer.setDouble(index, value) } 570 override fun fill(value: Byte, start: Int, end: Int) { buffer.fill(value, start, end) } 571 572 /** 573 * Request capacity of the buffer. In case buffer is already larger 574 * than the requested, it is a no-op. Otherwise, 575 * It might try to resize the buffer. In case of being unable to allocate 576 * enough memory, an exception will be thrown. 577 * @param capacity new capacity 578 * @param copyAtEnd copy current data at the end of new underlying buffer 579 */ 580 override fun requestCapacity(capacity: Int, copyAtEnd: Boolean): Int { 581 if (capacity < 0) error("Capacity may not be negative (likely a previous int overflow)") 582 583 if (buffer.size >= capacity) return buffer.size 584 585 if (writeLimit > 0 && writeLimit + offset >= buffer.size) error("Buffer in writeLimit mode. In writeLimit mode" + 586 " the buffer does not grow automatically and any write beyond writeLimit will throw exception. " + 587 "(writeLimit: $writeLimit, newCapacity: $capacity") 588 // implemented in the same growing fashion as ArrayList 589 val oldCapacity = buffer.size 590 if (oldCapacity == Int.MAX_VALUE - 8) { // Ensure we don't grow beyond what fits in an int. 591 error("FlatBuffers: cannot grow buffer beyond 2 gigabytes.") 592 } 593 //(old_buf_size & 0xC0000000) != 0 ? MAX_BUFFER_SIZE : old_buf_size << 1; 594 var newCapacity = 8 595 while (newCapacity < capacity) { // Note: this also catches newCapacity int overflow 596 newCapacity = if (newCapacity and -0x40000000 != 0) Int.MAX_VALUE - 8 else newCapacity shl 1 597 } 598 val newBuffer = ByteArray(newCapacity) 599 600 buffer.copyInto(newBuffer, if (copyAtEnd) newBuffer.size - buffer.size else 0) 601 buffer = newBuffer 602 return newCapacity 603 } 604 605 override fun writeSlice(offset: Int, size: Int): ReadWriteBuffer { 606 return ArrayReadWriteBuffer(this.buffer, offset=offset, writeLimit=size) 607 } 608 609 override fun moveWrittenDataToEnd(capacity: Int): Int = requestCapacity(capacity, true) 610 611 override val capacity: Int 612 get() = buffer.size 613 614 } 615 616 public val emptyBuffer: ReadWriteBuffer = ArrayReadWriteBuffer(ByteArray(1)) 617