• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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