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 an 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, size: Int): String 119 120 /** 121 * Expose [ReadBuffer] as an array of bytes. 122 * This method is meant to be as efficient as possible, so for a array-backed [ReadBuffer], it should 123 * return its own internal data. In case access to internal data is not possible, 124 * a copy of the data into an array of bytes might occur. 125 * @return [ReadBuffer] as an array of bytes 126 */ 127 public fun data(): ByteArray 128 129 /** 130 * Creates a new [ReadBuffer] point to a region of the current buffer, starting at [start] with size [size]. 131 * @param start starting position of the [ReadBuffer] 132 * @param size in bytes of the [ReadBuffer] 133 * @return [ReadBuffer] slice. 134 */ 135 public fun slice(start: Int, size: Int): ReadBuffer 136 137 /** 138 * Defines the size of the message in the buffer. It also determines last position that buffer 139 * can be read. Last byte to be accessed is in position `limit() -1`. 140 * @return indicate last position 141 */ 142 public val limit: Int 143 } 144 145 /** 146 * Interface to represent a read-write buffers. This interface will be used to access and write FlexBuffer messages. 147 */ 148 public interface ReadWriteBuffer : ReadBuffer { 149 /** 150 * Clears (resets) the buffer so that it can be reused. Write position will be set to the start. 151 */ 152 public fun clear() 153 154 /** 155 * Put a [Boolean] into the buffer at [writePosition] . Booleans as stored as single byte. 156 * Write position will be incremented. 157 * @return [Boolean] element 158 */ 159 public fun put(value: Boolean) 160 161 /** 162 * Put an array of bytes into the buffer at [writePosition]. Write position will be incremented. 163 * @param value the data to be copied 164 * @param start initial position on value to be copied 165 * @param length amount of bytes to be copied 166 */ 167 public fun put(value: ByteArray, start: Int, length: Int) 168 169 /** 170 * Write a [Byte] into the buffer at [writePosition]. Write position will be incremented. 171 */ 172 public fun put(value: Byte) 173 174 /** 175 * Write a [UByte] into the buffer at [writePosition]. Write position will be incremented. 176 */ 177 public fun put(value: UByte) 178 179 /** 180 * Write a [Short] into in the buffer at [writePosition]. Write position will be incremented. 181 */ 182 public fun put(value: Short) 183 184 /** 185 * Writea [UShort] into in the buffer at [writePosition]. Write position will be incremented. 186 */ 187 public fun put(value: UShort) 188 189 /** 190 * Write a [Int] in the buffer at [writePosition]. Write position will be incremented. 191 */ 192 public fun put(value: Int) 193 194 /** 195 * Write a [UInt] into in the buffer at [writePosition]. Write position will be incremented. 196 */ 197 public fun put(value: UInt) 198 199 /** 200 * Write a [Long] into in the buffer at [writePosition]. Write position will be 201 * incremented. 202 */ 203 public fun put(value: Long) 204 205 /** 206 * Write a [ULong] into in the buffer at [writePosition]. Write position will be 207 * incremented. 208 */ 209 public fun put(value: ULong) 210 211 /** 212 * Write a 32-bit [Float] into the buffer at [writePosition]. Write position will be 213 * incremented. 214 */ 215 public fun put(value: Float) 216 217 /** 218 * Write a 64-bit [Double] into the buffer at [writePosition]. Write position will be 219 * incremented. 220 */ 221 public fun put(value: Double) 222 223 /** 224 * Write a [String] encoded as UTF-8 into the buffer at [writePosition]. Write position will be incremented. 225 * @return size in bytes of the encoded string 226 */ 227 public fun put(value: String, encodedLength: Int = -1): Int 228 229 /** 230 * Write an array of bytes into the buffer. 231 * @param dstIndex initial position where [src] will be copied into. 232 * @param src the data to be copied. 233 * @param srcStart initial position on [src] that will be copied. 234 * @param srcLength amount of bytes to be copied 235 */ 236 public operator fun set(dstIndex: Int, src: ByteArray, srcStart: Int, srcLength: Int) 237 238 /** 239 * Write [Boolean] into a given position [index] on the buffer. Booleans as stored as single byte. 240 * @param index position of the element in buffer 241 */ 242 public operator fun set(index: Int, value: Boolean) 243 244 /** 245 * Write [Byte] into a given position [index] on the buffer. 246 * @param index position of the element in the buffer 247 */ 248 public operator fun set(index: Int, value: Byte) 249 250 /** 251 * Write [UByte] into a given position [index] on the buffer. 252 * @param index position of the element in the buffer 253 */ 254 public operator fun set(index: Int, value: UByte) 255 256 /** 257 Short 258 * @param index position of the element in [ReadBuffer] 259 */ 260 public fun set(index: Int, value: Short) 261 262 /** 263 * Write [UShort] into a given position [index] on the buffer. 264 * @param index position of the element in [ReadBuffer] 265 */ 266 public fun set(index: Int, value: UShort) 267 268 /** 269 * Write [Int] into a given position [index] on the buffer. 270 * @param index position of the element in [ReadBuffer] 271 */ 272 public fun set(index: Int, value: Int) 273 274 /** 275 * Write [UInt] into a given position [index] on the buffer. 276 * @param index position of the element in [ReadBuffer] 277 */ 278 public fun set(index: Int, value: UInt) 279 280 /** 281 * Write [Long] into a given position [index] on the buffer. 282 * @param index position of the element in [ReadBuffer] 283 */ 284 public fun set(index: Int, value: Long) 285 286 /** 287 * Write [ULong] into a given position [index] on the buffer. 288 * @param index position of the element in [ReadBuffer] 289 */ 290 public fun set(index: Int, value: ULong) 291 292 /** 293 * Write [Float] into a given position [index] on the buffer. 294 * @param index position of the element in [ReadBuffer] 295 */ 296 public fun set(index: Int, value: Float) 297 298 /** 299 * Write [Double] into a given position [index] on the buffer. 300 * @param index position of the element in [ReadBuffer] 301 */ 302 public fun set(index: Int, value: Double) 303 304 /** 305 * Current position of the buffer to be written. It will be automatically updated on [put] operations. 306 */ 307 public var writePosition: Int 308 309 /** 310 * Defines the size of the message in the buffer. It also determines last position that buffer 311 * can be read or write. Last byte to be accessed is in position `limit() -1`. 312 * @return indicate last position 313 */ 314 override val limit: Int 315 316 /** 317 * Request capacity of the buffer. In case buffer is already larger 318 * than the requested, this method will just return true. Otherwise 319 * It might try to resize the buffer. In case of being unable to allocate 320 * enough memory, an exception will be thrown. 321 */ 322 public fun requestCapacity(capacity: Int) 323 } 324 325 public open class ArrayReadBuffer(protected var buffer: ByteArray, override val limit: Int = buffer.size) : ReadBuffer { 326 findFirstnull327 override fun findFirst(value: Byte, start: Int, end: Int): Int { 328 val e = min(end, limit) 329 val s = max(0, start) 330 for (i in s until e) if (buffer[i] == value) return i 331 return -1 332 } 333 getBooleannull334 override fun getBoolean(index: Int): Boolean = buffer[index] != 0.toByte() 335 336 override operator fun get(index: Int): Byte = buffer[index] 337 338 override fun getUByte(index: Int): UByte = buffer.getUByte(index) 339 340 override fun getShort(index: Int): Short = buffer.getShort(index) 341 342 override fun getUShort(index: Int): UShort = buffer.getUShort(index) 343 344 override fun getInt(index: Int): Int = buffer.getInt(index) 345 346 override fun getUInt(index: Int): UInt = buffer.getUInt(index) 347 348 override fun getLong(index: Int): Long = buffer.getLong(index) 349 350 override fun getULong(index: Int): ULong = buffer.getULong(index) 351 352 override fun getFloat(index: Int): Float = buffer.getFloat(index) 353 354 override fun getDouble(index: Int): Double = buffer.getDouble(index) 355 356 override fun getString(start: Int, size: Int): String = buffer.decodeToString(start, start + size) 357 358 override fun data(): ByteArray = buffer 359 360 override fun slice(start: Int, size: Int): ReadBuffer = ArrayReadBuffer(buffer, limit) 361 } 362 /** 363 * Implements `[ReadWriteBuffer]` using [ByteArray] as backing buffer. Using array of bytes are 364 * usually faster than `ByteBuffer`. 365 * 366 * This class is not thread-safe, meaning that 367 * it must operate on a single thread. Operating from 368 * multiple thread leads into a undefined behavior 369 * 370 * All operations assumes Little Endian byte order. 371 */ 372 public class ArrayReadWriteBuffer( 373 buffer: ByteArray, 374 override var writePosition: Int = 0 375 ) : ArrayReadBuffer(buffer, writePosition), ReadWriteBuffer { 376 377 public constructor(initialCapacity: Int = 10) : this(ByteArray(initialCapacity)) 378 379 override val limit: Int get() = writePosition 380 381 override fun clear(): Unit = run { writePosition = 0 } 382 383 override fun put(value: Boolean) { 384 set(writePosition, value) 385 writePosition++ 386 } 387 388 override fun put(value: ByteArray, start: Int, length: Int) { 389 set(writePosition, value, start, length) 390 writePosition += length 391 } 392 393 override fun put(value: Byte) { 394 set(writePosition, value) 395 writePosition++ 396 } 397 398 override fun put(value: UByte) { 399 set(writePosition, value) 400 writePosition++ 401 } 402 403 override fun put(value: Short) { 404 set(writePosition, value) 405 writePosition += 2 406 } 407 408 override fun put(value: UShort) { 409 set(writePosition, value) 410 writePosition += 2 411 } 412 413 override fun put(value: Int) { 414 set(writePosition, value) 415 writePosition += 4 416 } 417 418 override fun put(value: UInt) { 419 set(writePosition, value) 420 writePosition += 4 421 } 422 423 override fun put(value: Long) { 424 set(writePosition, value) 425 writePosition += 8 426 } 427 428 override fun put(value: ULong) { 429 set(writePosition, value) 430 writePosition += 8 431 } 432 433 override fun put(value: Float) { 434 set(writePosition, value) 435 writePosition += 4 436 } 437 438 override fun put(value: Double) { 439 set(writePosition, value) 440 writePosition += 8 441 } 442 443 override fun put(value: String, encodedLength: Int): Int { 444 val length = if (encodedLength != -1) encodedLength else Utf8.encodedLength(value) 445 withCapacity(writePosition + length) { 446 writePosition = setString(writePosition, value) 447 } 448 return length 449 } 450 451 override fun set(index: Int, value: Boolean) { 452 set(index, if (value) 1.toByte() else 0.toByte()) 453 } 454 455 override operator fun set(dstIndex: Int, src: ByteArray, srcStart: Int, srcLength: Int) { 456 withCapacity(dstIndex + (srcLength + srcStart)) { 457 src.copyInto(buffer, dstIndex, srcStart, srcStart + srcLength) 458 } 459 } 460 461 override operator fun set(index: Int, value: Byte): Unit = withCapacity(index + 1) { set(index, value) } 462 override operator fun set(index: Int, value: UByte): Unit = withCapacity(index + 1) { setUByte(index, value) } 463 override operator fun set(index: Int, value: Short): Unit = withCapacity(index + 2) { setShort(index, value) } 464 override operator fun set(index: Int, value: UShort): Unit = withCapacity(index + 2) { setUShort(index, value) } 465 override operator fun set(index: Int, value: Int): Unit = withCapacity(index + 4) { setInt(index, value) } 466 override operator fun set(index: Int, value: UInt): Unit = withCapacity(index + 4) { setUInt(index, value) } 467 override operator fun set(index: Int, value: Long): Unit = withCapacity(index + 8) { setLong(index, value) } 468 override operator fun set(index: Int, value: ULong): Unit = withCapacity(index + 8) { setULong(index, value) } 469 override operator fun set(index: Int, value: Float): Unit = withCapacity(index + 4) { setFloat(index, value) } 470 override operator fun set(index: Int, value: Double): Unit = withCapacity(index + 8) { setDouble(index, value) } 471 472 override fun requestCapacity(capacity: Int) { 473 if (capacity < 0) error("Capacity may not be negative (likely a previous int overflow)") 474 475 if (buffer.size >= capacity) return 476 // implemented in the same growing fashion as ArrayList 477 val oldCapacity = buffer.size 478 var newCapacity = oldCapacity + (oldCapacity shr 1) 479 if (newCapacity < capacity) { // Note: this also catches newCapacity int overflow 480 newCapacity = capacity 481 } 482 buffer = buffer.copyOf(newCapacity) 483 } 484 485 private inline fun withCapacity(size: Int, crossinline action: ByteArray.() -> Unit) { 486 requestCapacity(size) 487 buffer.action() 488 } 489 } 490