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