xref: /aosp_15_r20/external/flatbuffers/swift/Sources/FlatBuffers/FlatBufferBuilder.swift (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Worker /*
2*890232f2SAndroid Build Coastguard Worker  * Copyright 2021 Google Inc. All rights reserved.
3*890232f2SAndroid Build Coastguard Worker  *
4*890232f2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*890232f2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*890232f2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*890232f2SAndroid Build Coastguard Worker  *
8*890232f2SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*890232f2SAndroid Build Coastguard Worker  *
10*890232f2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*890232f2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*890232f2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*890232f2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*890232f2SAndroid Build Coastguard Worker  * limitations under the License.
15*890232f2SAndroid Build Coastguard Worker  */
16*890232f2SAndroid Build Coastguard Worker 
17*890232f2SAndroid Build Coastguard Worker #if !os(WASI)
18*890232f2SAndroid Build Coastguard Worker import Foundation
19*890232f2SAndroid Build Coastguard Worker #else
20*890232f2SAndroid Build Coastguard Worker import SwiftOverlayShims
21*890232f2SAndroid Build Coastguard Worker #endif
22*890232f2SAndroid Build Coastguard Worker 
23*890232f2SAndroid Build Coastguard Worker /// ``FlatBufferBuilder`` builds a `FlatBuffer` through manipulating its internal state.
24*890232f2SAndroid Build Coastguard Worker ///
25*890232f2SAndroid Build Coastguard Worker /// This is done by creating a ``ByteBuffer`` that hosts the incoming data and
26*890232f2SAndroid Build Coastguard Worker /// has a hardcoded growth limit of `2GiB` which is set by the Flatbuffers standards.
27*890232f2SAndroid Build Coastguard Worker ///
28*890232f2SAndroid Build Coastguard Worker /// ```swift
29*890232f2SAndroid Build Coastguard Worker /// var builder = FlatBufferBuilder()
30*890232f2SAndroid Build Coastguard Worker /// ```
31*890232f2SAndroid Build Coastguard Worker /// The builder should be always created as a variable, since it would be passed into the writers
32*890232f2SAndroid Build Coastguard Worker ///
33*890232f2SAndroid Build Coastguard Worker @frozen
34*890232f2SAndroid Build Coastguard Worker public struct FlatBufferBuilder {
35*890232f2SAndroid Build Coastguard Worker 
36*890232f2SAndroid Build Coastguard Worker   /// Storage for the Vtables used in the buffer are stored in here, so they would be written later in EndTable
37*890232f2SAndroid Build Coastguard Worker   @usableFromInline internal var _vtableStorage = VTableStorage()
38*890232f2SAndroid Build Coastguard Worker   /// Flatbuffer data will be written into
39*890232f2SAndroid Build Coastguard Worker   @usableFromInline internal var _bb: ByteBuffer
40*890232f2SAndroid Build Coastguard Worker 
41*890232f2SAndroid Build Coastguard Worker   /// Reference Vtables that were already written to the buffer
42*890232f2SAndroid Build Coastguard Worker   private var _vtables: [UOffset] = []
43*890232f2SAndroid Build Coastguard Worker   /// A check if the buffer is being written into by a different table
44*890232f2SAndroid Build Coastguard Worker   private var isNested = false
45*890232f2SAndroid Build Coastguard Worker   /// Dictonary that stores a map of all the strings that were written to the buffer
46*890232f2SAndroid Build Coastguard Worker   private var stringOffsetMap: [String: Offset] = [:]
47*890232f2SAndroid Build Coastguard Worker   /// A check to see if finish(::) was ever called to retreive data object
48*890232f2SAndroid Build Coastguard Worker   private var finished = false
49*890232f2SAndroid Build Coastguard Worker   /// A check to see if the buffer should serialize Default values
50*890232f2SAndroid Build Coastguard Worker   private var serializeDefaults: Bool
51*890232f2SAndroid Build Coastguard Worker 
52*890232f2SAndroid Build Coastguard Worker   /// Current alignment for the buffer
53*890232f2SAndroid Build Coastguard Worker   var _minAlignment: Int = 0 {
54*890232f2SAndroid Build Coastguard Worker     didSet {
55*890232f2SAndroid Build Coastguard Worker       _bb.alignment = _minAlignment
56*890232f2SAndroid Build Coastguard Worker     }
57*890232f2SAndroid Build Coastguard Worker   }
58*890232f2SAndroid Build Coastguard Worker 
59*890232f2SAndroid Build Coastguard Worker   /// Gives a read access to the buffer's size
60*890232f2SAndroid Build Coastguard Worker   public var size: UOffset { _bb.size }
61*890232f2SAndroid Build Coastguard Worker 
62*890232f2SAndroid Build Coastguard Worker   #if !os(WASI)
63*890232f2SAndroid Build Coastguard Worker   /// Data representation of the buffer
64*890232f2SAndroid Build Coastguard Worker   ///
65*890232f2SAndroid Build Coastguard Worker   /// Should only be used after ``finish(offset:addPrefix:)`` is called
66*890232f2SAndroid Build Coastguard Worker   public var data: Data {
67*890232f2SAndroid Build Coastguard Worker     assert(finished, "Data shouldn't be called before finish()")
68*890232f2SAndroid Build Coastguard Worker     return Data(
69*890232f2SAndroid Build Coastguard Worker       bytes: _bb.memory.advanced(by: _bb.writerIndex),
70*890232f2SAndroid Build Coastguard Worker       count: _bb.capacity &- _bb.writerIndex)
71*890232f2SAndroid Build Coastguard Worker   }
72*890232f2SAndroid Build Coastguard Worker   #endif
73*890232f2SAndroid Build Coastguard Worker 
74*890232f2SAndroid Build Coastguard Worker   /// Returns the underlying bytes in the ``ByteBuffer``
75*890232f2SAndroid Build Coastguard Worker   ///
76*890232f2SAndroid Build Coastguard Worker   /// Note: This should be used with caution.
77*890232f2SAndroid Build Coastguard Worker   public var fullSizedByteArray: [UInt8] {
78*890232f2SAndroid Build Coastguard Worker     let ptr = UnsafeBufferPointer(
79*890232f2SAndroid Build Coastguard Worker       start: _bb.memory.assumingMemoryBound(to: UInt8.self),
80*890232f2SAndroid Build Coastguard Worker       count: _bb.capacity)
81*890232f2SAndroid Build Coastguard Worker     return Array(ptr)
82*890232f2SAndroid Build Coastguard Worker   }
83*890232f2SAndroid Build Coastguard Worker 
84*890232f2SAndroid Build Coastguard Worker   /// Returns the written bytes into the ``ByteBuffer``
85*890232f2SAndroid Build Coastguard Worker   ///
86*890232f2SAndroid Build Coastguard Worker   /// Should only be used after ``finish(offset:addPrefix:)`` is called
87*890232f2SAndroid Build Coastguard Worker   public var sizedByteArray: [UInt8] {
88*890232f2SAndroid Build Coastguard Worker     assert(finished, "Data shouldn't be called before finish()")
89*890232f2SAndroid Build Coastguard Worker     return _bb.underlyingBytes
90*890232f2SAndroid Build Coastguard Worker   }
91*890232f2SAndroid Build Coastguard Worker 
92*890232f2SAndroid Build Coastguard Worker   /// Returns the original ``ByteBuffer``
93*890232f2SAndroid Build Coastguard Worker   ///
94*890232f2SAndroid Build Coastguard Worker   /// Returns the current buffer that was just created
95*890232f2SAndroid Build Coastguard Worker   /// with the offsets, and data written to it.
96*890232f2SAndroid Build Coastguard Worker   public var buffer: ByteBuffer { _bb }
97*890232f2SAndroid Build Coastguard Worker 
98*890232f2SAndroid Build Coastguard Worker   /// Returns a newly created sized ``ByteBuffer``
99*890232f2SAndroid Build Coastguard Worker   ///
100*890232f2SAndroid Build Coastguard Worker   /// returns a new buffer that is sized to the data written
101*890232f2SAndroid Build Coastguard Worker   /// to the main buffer
102*890232f2SAndroid Build Coastguard Worker   public var sizedBuffer: ByteBuffer {
103*890232f2SAndroid Build Coastguard Worker     assert(finished, "Data shouldn't be called before finish()")
104*890232f2SAndroid Build Coastguard Worker     return ByteBuffer(
105*890232f2SAndroid Build Coastguard Worker       memory: _bb.memory.advanced(by: _bb.reader),
106*890232f2SAndroid Build Coastguard Worker       count: Int(_bb.size))
107*890232f2SAndroid Build Coastguard Worker   }
108*890232f2SAndroid Build Coastguard Worker 
109*890232f2SAndroid Build Coastguard Worker   // MARK: - Init
110*890232f2SAndroid Build Coastguard Worker 
111*890232f2SAndroid Build Coastguard Worker   /// Initialize the buffer with a size
112*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
113*890232f2SAndroid Build Coastguard Worker   ///   - initialSize: Initial size for the buffer
114*890232f2SAndroid Build Coastguard Worker   ///   - force: Allows default to be serialized into the buffer
115*890232f2SAndroid Build Coastguard Worker   ///
116*890232f2SAndroid Build Coastguard Worker   /// This initializes a new builder with an initialSize that would initialize
117*890232f2SAndroid Build Coastguard Worker   /// a new ``ByteBuffer``. ``FlatBufferBuilder`` by default doesnt serialize defaults
118*890232f2SAndroid Build Coastguard Worker   /// however the builder can be force by passing true for `serializeDefaults`
119*890232f2SAndroid Build Coastguard Worker   public init(
120*890232f2SAndroid Build Coastguard Worker     initialSize: Int32 = 1024,
121*890232f2SAndroid Build Coastguard Worker     serializeDefaults force: Bool = false)
122*890232f2SAndroid Build Coastguard Worker   {
123*890232f2SAndroid Build Coastguard Worker     assert(initialSize > 0, "Size should be greater than zero!")
124*890232f2SAndroid Build Coastguard Worker     guard isLitteEndian else {
125*890232f2SAndroid Build Coastguard Worker       fatalError(
126*890232f2SAndroid Build Coastguard Worker         "Reading/Writing a buffer in big endian machine is not supported on swift")
127*890232f2SAndroid Build Coastguard Worker     }
128*890232f2SAndroid Build Coastguard Worker     serializeDefaults = force
129*890232f2SAndroid Build Coastguard Worker     _bb = ByteBuffer(initialSize: Int(initialSize))
130*890232f2SAndroid Build Coastguard Worker   }
131*890232f2SAndroid Build Coastguard Worker 
132*890232f2SAndroid Build Coastguard Worker   /// Clears the builder and the buffer from the written data.
clearnull133*890232f2SAndroid Build Coastguard Worker   mutating public func clear() {
134*890232f2SAndroid Build Coastguard Worker     _minAlignment = 0
135*890232f2SAndroid Build Coastguard Worker     isNested = false
136*890232f2SAndroid Build Coastguard Worker     stringOffsetMap.removeAll(keepingCapacity: true)
137*890232f2SAndroid Build Coastguard Worker     _vtables.removeAll(keepingCapacity: true)
138*890232f2SAndroid Build Coastguard Worker     _vtableStorage.clear()
139*890232f2SAndroid Build Coastguard Worker     _bb.clear()
140*890232f2SAndroid Build Coastguard Worker   }
141*890232f2SAndroid Build Coastguard Worker 
142*890232f2SAndroid Build Coastguard Worker   // MARK: - Create Tables
143*890232f2SAndroid Build Coastguard Worker 
144*890232f2SAndroid Build Coastguard Worker   /// Checks if the required fields were serialized into the buffer
145*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
146*890232f2SAndroid Build Coastguard Worker   ///   - table: offset for the table
147*890232f2SAndroid Build Coastguard Worker   ///   - fields: Array of all the important fields to be serialized
148*890232f2SAndroid Build Coastguard Worker   ///
149*890232f2SAndroid Build Coastguard Worker   /// *NOTE: Never call this function, this is only supposed to be called
150*890232f2SAndroid Build Coastguard Worker   /// by the generated code*
151*890232f2SAndroid Build Coastguard Worker   @inline(__always)
requirenull152*890232f2SAndroid Build Coastguard Worker   mutating public func require(table: Offset, fields: [Int32]) {
153*890232f2SAndroid Build Coastguard Worker     for field in fields {
154*890232f2SAndroid Build Coastguard Worker       let start = _bb.capacity &- Int(table.o)
155*890232f2SAndroid Build Coastguard Worker       let startTable = start &- Int(_bb.read(def: Int32.self, position: start))
156*890232f2SAndroid Build Coastguard Worker       let isOkay = _bb.read(
157*890232f2SAndroid Build Coastguard Worker         def: VOffset.self,
158*890232f2SAndroid Build Coastguard Worker         position: startTable &+ Int(field)) != 0
159*890232f2SAndroid Build Coastguard Worker       assert(isOkay, "Flatbuffers requires the following field")
160*890232f2SAndroid Build Coastguard Worker     }
161*890232f2SAndroid Build Coastguard Worker   }
162*890232f2SAndroid Build Coastguard Worker 
163*890232f2SAndroid Build Coastguard Worker   /// Finished the buffer by adding the file id and then calling finish
164*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
165*890232f2SAndroid Build Coastguard Worker   ///   - offset: Offset of the table
166*890232f2SAndroid Build Coastguard Worker   ///   - fileId: Takes the fileId
167*890232f2SAndroid Build Coastguard Worker   ///   - prefix: if false it wont add the size of the buffer
168*890232f2SAndroid Build Coastguard Worker   ///
169*890232f2SAndroid Build Coastguard Worker   /// ``finish(offset:fileId:addPrefix:)`` should be called at the end of creating
170*890232f2SAndroid Build Coastguard Worker   /// a table
171*890232f2SAndroid Build Coastguard Worker   /// ```swift
172*890232f2SAndroid Build Coastguard Worker   /// var root = SomeObject
173*890232f2SAndroid Build Coastguard Worker   ///   .createObject(&builder,
174*890232f2SAndroid Build Coastguard Worker   ///   name: nameOffset)
175*890232f2SAndroid Build Coastguard Worker   /// builder.finish(
176*890232f2SAndroid Build Coastguard Worker   ///   offset: root,
177*890232f2SAndroid Build Coastguard Worker   ///   fileId: "ax1a",
178*890232f2SAndroid Build Coastguard Worker   ///   addPrefix: true)
179*890232f2SAndroid Build Coastguard Worker   /// ```
180*890232f2SAndroid Build Coastguard Worker   /// File id would append a file id name at the end of the written bytes before,
181*890232f2SAndroid Build Coastguard Worker   /// finishing the buffer.
182*890232f2SAndroid Build Coastguard Worker   ///
183*890232f2SAndroid Build Coastguard Worker   /// Whereas, if `addPrefix` is true, the written bytes would
184*890232f2SAndroid Build Coastguard Worker   /// include the size of the current buffer.
185*890232f2SAndroid Build Coastguard Worker   mutating public func finish(
186*890232f2SAndroid Build Coastguard Worker     offset: Offset,
187*890232f2SAndroid Build Coastguard Worker     fileId: String,
188*890232f2SAndroid Build Coastguard Worker     addPrefix prefix: Bool = false)
189*890232f2SAndroid Build Coastguard Worker   {
190*890232f2SAndroid Build Coastguard Worker     let size = MemoryLayout<UOffset>.size
191*890232f2SAndroid Build Coastguard Worker     preAlign(
192*890232f2SAndroid Build Coastguard Worker       len: size &+ (prefix ? size : 0) &+ FileIdLength,
193*890232f2SAndroid Build Coastguard Worker       alignment: _minAlignment)
194*890232f2SAndroid Build Coastguard Worker     assert(fileId.count == FileIdLength, "Flatbuffers requires file id to be 4")
195*890232f2SAndroid Build Coastguard Worker     _bb.push(string: fileId, len: 4)
196*890232f2SAndroid Build Coastguard Worker     finish(offset: offset, addPrefix: prefix)
197*890232f2SAndroid Build Coastguard Worker   }
198*890232f2SAndroid Build Coastguard Worker 
199*890232f2SAndroid Build Coastguard Worker   /// Finished the buffer by adding the file id, offset, and prefix to it.
200*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
201*890232f2SAndroid Build Coastguard Worker   ///   - offset: Offset of the table
202*890232f2SAndroid Build Coastguard Worker   ///   - prefix: if false it wont add the size of the buffer
203*890232f2SAndroid Build Coastguard Worker   ///
204*890232f2SAndroid Build Coastguard Worker   /// ``finish(offset:addPrefix:)`` should be called at the end of creating
205*890232f2SAndroid Build Coastguard Worker   /// a table
206*890232f2SAndroid Build Coastguard Worker   /// ```swift
207*890232f2SAndroid Build Coastguard Worker   /// var root = SomeObject
208*890232f2SAndroid Build Coastguard Worker   ///   .createObject(&builder,
209*890232f2SAndroid Build Coastguard Worker   ///   name: nameOffset)
210*890232f2SAndroid Build Coastguard Worker   /// builder.finish(
211*890232f2SAndroid Build Coastguard Worker   ///   offset: root,
212*890232f2SAndroid Build Coastguard Worker   ///   addPrefix: true)
213*890232f2SAndroid Build Coastguard Worker   /// ```
214*890232f2SAndroid Build Coastguard Worker   /// If `addPrefix` is true, the written bytes would
215*890232f2SAndroid Build Coastguard Worker   /// include the size of the current buffer.
216*890232f2SAndroid Build Coastguard Worker   mutating public func finish(
217*890232f2SAndroid Build Coastguard Worker     offset: Offset,
218*890232f2SAndroid Build Coastguard Worker     addPrefix prefix: Bool = false)
219*890232f2SAndroid Build Coastguard Worker   {
220*890232f2SAndroid Build Coastguard Worker     notNested()
221*890232f2SAndroid Build Coastguard Worker     let size = MemoryLayout<UOffset>.size
222*890232f2SAndroid Build Coastguard Worker     preAlign(len: size &+ (prefix ? size : 0), alignment: _minAlignment)
223*890232f2SAndroid Build Coastguard Worker     push(element: refer(to: offset.o))
224*890232f2SAndroid Build Coastguard Worker     if prefix { push(element: _bb.size) }
225*890232f2SAndroid Build Coastguard Worker     _vtableStorage.clear()
226*890232f2SAndroid Build Coastguard Worker     finished = true
227*890232f2SAndroid Build Coastguard Worker   }
228*890232f2SAndroid Build Coastguard Worker 
229*890232f2SAndroid Build Coastguard Worker   /// ``startTable(with:)`` will let the builder know, that a new object is being serialized.
230*890232f2SAndroid Build Coastguard Worker   ///
231*890232f2SAndroid Build Coastguard Worker   /// The function will fatalerror if called while there is another object being serialized.
232*890232f2SAndroid Build Coastguard Worker   /// ```swift
233*890232f2SAndroid Build Coastguard Worker   /// let start = Monster
234*890232f2SAndroid Build Coastguard Worker   ///   .startMonster(&fbb)
235*890232f2SAndroid Build Coastguard Worker   /// ```
236*890232f2SAndroid Build Coastguard Worker   /// - Parameter numOfFields: Number of elements to be written to the buffer
237*890232f2SAndroid Build Coastguard Worker   /// - Returns: Offset of the newly started table
238*890232f2SAndroid Build Coastguard Worker   @inline(__always)
startTablenull239*890232f2SAndroid Build Coastguard Worker   mutating public func startTable(with numOfFields: Int) -> UOffset {
240*890232f2SAndroid Build Coastguard Worker     notNested()
241*890232f2SAndroid Build Coastguard Worker     isNested = true
242*890232f2SAndroid Build Coastguard Worker     _vtableStorage.start(count: numOfFields)
243*890232f2SAndroid Build Coastguard Worker     return _bb.size
244*890232f2SAndroid Build Coastguard Worker   }
245*890232f2SAndroid Build Coastguard Worker 
246*890232f2SAndroid Build Coastguard Worker   /// ``endTable(at:)`` will let the ``FlatBufferBuilder`` know that the
247*890232f2SAndroid Build Coastguard Worker   /// object that's written to it is completed
248*890232f2SAndroid Build Coastguard Worker   ///
249*890232f2SAndroid Build Coastguard Worker   /// This would be called after all the elements are serialized,
250*890232f2SAndroid Build Coastguard Worker   /// it will add the current vtable into the ``ByteBuffer``.
251*890232f2SAndroid Build Coastguard Worker   /// The functions will `fatalError` in case the object is called
252*890232f2SAndroid Build Coastguard Worker   /// without ``startTable(with:)``, or the object has exceeded  the limit of 2GB.
253*890232f2SAndroid Build Coastguard Worker   ///
254*890232f2SAndroid Build Coastguard Worker   /// - Parameter startOffset:Start point of the object written
255*890232f2SAndroid Build Coastguard Worker   /// - returns: The root of the table
endTablenull256*890232f2SAndroid Build Coastguard Worker   mutating public func endTable(at startOffset: UOffset)  -> UOffset {
257*890232f2SAndroid Build Coastguard Worker     assert(isNested, "Calling endtable without calling starttable")
258*890232f2SAndroid Build Coastguard Worker     let sizeofVoffset = MemoryLayout<VOffset>.size
259*890232f2SAndroid Build Coastguard Worker     let vTableOffset = push(element: SOffset(0))
260*890232f2SAndroid Build Coastguard Worker 
261*890232f2SAndroid Build Coastguard Worker     let tableObjectSize = vTableOffset &- startOffset
262*890232f2SAndroid Build Coastguard Worker     assert(tableObjectSize < 0x10000, "Buffer can't grow beyond 2 Gigabytes")
263*890232f2SAndroid Build Coastguard Worker     let _max = Int(_vtableStorage.maxOffset) &+ sizeofVoffset
264*890232f2SAndroid Build Coastguard Worker 
265*890232f2SAndroid Build Coastguard Worker     _bb.fill(padding: _max)
266*890232f2SAndroid Build Coastguard Worker     _bb.write(
267*890232f2SAndroid Build Coastguard Worker       value: VOffset(tableObjectSize),
268*890232f2SAndroid Build Coastguard Worker       index: _bb.writerIndex &+ sizeofVoffset,
269*890232f2SAndroid Build Coastguard Worker       direct: true)
270*890232f2SAndroid Build Coastguard Worker     _bb.write(value: VOffset(_max), index: _bb.writerIndex, direct: true)
271*890232f2SAndroid Build Coastguard Worker 
272*890232f2SAndroid Build Coastguard Worker     var itr = 0
273*890232f2SAndroid Build Coastguard Worker     while itr < _vtableStorage.writtenIndex {
274*890232f2SAndroid Build Coastguard Worker       let loaded = _vtableStorage.load(at: itr)
275*890232f2SAndroid Build Coastguard Worker       itr = itr &+ _vtableStorage.size
276*890232f2SAndroid Build Coastguard Worker       guard loaded.offset != 0 else { continue }
277*890232f2SAndroid Build Coastguard Worker       let _index = (_bb.writerIndex &+ Int(loaded.position))
278*890232f2SAndroid Build Coastguard Worker       _bb.write(
279*890232f2SAndroid Build Coastguard Worker         value: VOffset(vTableOffset &- loaded.offset),
280*890232f2SAndroid Build Coastguard Worker         index: _index,
281*890232f2SAndroid Build Coastguard Worker         direct: true)
282*890232f2SAndroid Build Coastguard Worker     }
283*890232f2SAndroid Build Coastguard Worker 
284*890232f2SAndroid Build Coastguard Worker     _vtableStorage.clear()
285*890232f2SAndroid Build Coastguard Worker     let vt_use = _bb.size
286*890232f2SAndroid Build Coastguard Worker 
287*890232f2SAndroid Build Coastguard Worker     var isAlreadyAdded: Int?
288*890232f2SAndroid Build Coastguard Worker 
289*890232f2SAndroid Build Coastguard Worker     let vt2 = _bb.memory.advanced(by: _bb.writerIndex)
290*890232f2SAndroid Build Coastguard Worker     let len2 = vt2.load(fromByteOffset: 0, as: Int16.self)
291*890232f2SAndroid Build Coastguard Worker 
292*890232f2SAndroid Build Coastguard Worker     for table in _vtables {
293*890232f2SAndroid Build Coastguard Worker       let position = _bb.capacity &- Int(table)
294*890232f2SAndroid Build Coastguard Worker       let vt1 = _bb.memory.advanced(by: position)
295*890232f2SAndroid Build Coastguard Worker       let len1 = _bb.read(def: Int16.self, position: position)
296*890232f2SAndroid Build Coastguard Worker       if len2 != len1 || 0 != memcmp(vt1, vt2, Int(len2)) { continue }
297*890232f2SAndroid Build Coastguard Worker 
298*890232f2SAndroid Build Coastguard Worker       isAlreadyAdded = Int(table)
299*890232f2SAndroid Build Coastguard Worker       break
300*890232f2SAndroid Build Coastguard Worker     }
301*890232f2SAndroid Build Coastguard Worker 
302*890232f2SAndroid Build Coastguard Worker     if let offset = isAlreadyAdded {
303*890232f2SAndroid Build Coastguard Worker       let vTableOff = Int(vTableOffset)
304*890232f2SAndroid Build Coastguard Worker       let space = _bb.capacity &- vTableOff
305*890232f2SAndroid Build Coastguard Worker       _bb.write(value: Int32(offset &- vTableOff), index: space, direct: true)
306*890232f2SAndroid Build Coastguard Worker       _bb.pop(_bb.capacity &- space)
307*890232f2SAndroid Build Coastguard Worker     } else {
308*890232f2SAndroid Build Coastguard Worker       _bb.write(value: Int32(vt_use &- vTableOffset), index: Int(vTableOffset))
309*890232f2SAndroid Build Coastguard Worker       _vtables.append(_bb.size)
310*890232f2SAndroid Build Coastguard Worker     }
311*890232f2SAndroid Build Coastguard Worker     isNested = false
312*890232f2SAndroid Build Coastguard Worker     return vTableOffset
313*890232f2SAndroid Build Coastguard Worker   }
314*890232f2SAndroid Build Coastguard Worker 
315*890232f2SAndroid Build Coastguard Worker   // MARK: - Builds Buffer
316*890232f2SAndroid Build Coastguard Worker 
317*890232f2SAndroid Build Coastguard Worker   /// Asserts to see if the object is not nested
318*890232f2SAndroid Build Coastguard Worker   @inline(__always)
319*890232f2SAndroid Build Coastguard Worker   @usableFromInline
notNestednull320*890232f2SAndroid Build Coastguard Worker   mutating internal func notNested()  {
321*890232f2SAndroid Build Coastguard Worker     assert(!isNested, "Object serialization must not be nested")
322*890232f2SAndroid Build Coastguard Worker   }
323*890232f2SAndroid Build Coastguard Worker 
324*890232f2SAndroid Build Coastguard Worker   /// Changes the minimuim alignment of the buffer
325*890232f2SAndroid Build Coastguard Worker   /// - Parameter size: size of the current alignment
326*890232f2SAndroid Build Coastguard Worker   @inline(__always)
327*890232f2SAndroid Build Coastguard Worker   @usableFromInline
minAlignmentnull328*890232f2SAndroid Build Coastguard Worker   mutating internal func minAlignment(size: Int) {
329*890232f2SAndroid Build Coastguard Worker     if size > _minAlignment {
330*890232f2SAndroid Build Coastguard Worker       _minAlignment = size
331*890232f2SAndroid Build Coastguard Worker     }
332*890232f2SAndroid Build Coastguard Worker   }
333*890232f2SAndroid Build Coastguard Worker 
334*890232f2SAndroid Build Coastguard Worker   /// Gets the padding for the current element
335*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
336*890232f2SAndroid Build Coastguard Worker   ///   - bufSize: Current size of the buffer + the offset of the object to be written
337*890232f2SAndroid Build Coastguard Worker   ///   - elementSize: Element size
338*890232f2SAndroid Build Coastguard Worker   @inline(__always)
339*890232f2SAndroid Build Coastguard Worker   @usableFromInline
340*890232f2SAndroid Build Coastguard Worker   mutating internal func padding(
341*890232f2SAndroid Build Coastguard Worker     bufSize: UInt32,
342*890232f2SAndroid Build Coastguard Worker     elementSize: UInt32) -> UInt32
343*890232f2SAndroid Build Coastguard Worker   {
344*890232f2SAndroid Build Coastguard Worker     ((~bufSize) &+ 1) & (elementSize - 1)
345*890232f2SAndroid Build Coastguard Worker   }
346*890232f2SAndroid Build Coastguard Worker 
347*890232f2SAndroid Build Coastguard Worker   /// Prealigns the buffer before writting a new object into the buffer
348*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
349*890232f2SAndroid Build Coastguard Worker   ///   - len:Length of the object
350*890232f2SAndroid Build Coastguard Worker   ///   - alignment: Alignment type
351*890232f2SAndroid Build Coastguard Worker   @inline(__always)
352*890232f2SAndroid Build Coastguard Worker   @usableFromInline
preAlignnull353*890232f2SAndroid Build Coastguard Worker   mutating internal func preAlign(len: Int, alignment: Int) {
354*890232f2SAndroid Build Coastguard Worker     minAlignment(size: alignment)
355*890232f2SAndroid Build Coastguard Worker     _bb.fill(padding: Int(padding(
356*890232f2SAndroid Build Coastguard Worker       bufSize: _bb.size &+ UOffset(len),
357*890232f2SAndroid Build Coastguard Worker       elementSize: UOffset(alignment))))
358*890232f2SAndroid Build Coastguard Worker   }
359*890232f2SAndroid Build Coastguard Worker 
360*890232f2SAndroid Build Coastguard Worker   /// Prealigns the buffer before writting a new object into the buffer
361*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
362*890232f2SAndroid Build Coastguard Worker   ///   - len: Length of the object
363*890232f2SAndroid Build Coastguard Worker   ///   - type: Type of the object to be written
364*890232f2SAndroid Build Coastguard Worker   @inline(__always)
365*890232f2SAndroid Build Coastguard Worker   @usableFromInline
preAlign<T: Scalar>null366*890232f2SAndroid Build Coastguard Worker   mutating internal func preAlign<T: Scalar>(len: Int, type: T.Type) {
367*890232f2SAndroid Build Coastguard Worker     preAlign(len: len, alignment: MemoryLayout<T>.size)
368*890232f2SAndroid Build Coastguard Worker   }
369*890232f2SAndroid Build Coastguard Worker 
370*890232f2SAndroid Build Coastguard Worker   /// Refers to an object that's written in the buffer
371*890232f2SAndroid Build Coastguard Worker   /// - Parameter off: the objects index value
372*890232f2SAndroid Build Coastguard Worker   @inline(__always)
373*890232f2SAndroid Build Coastguard Worker   @usableFromInline
refernull374*890232f2SAndroid Build Coastguard Worker   mutating internal func refer(to off: UOffset) -> UOffset {
375*890232f2SAndroid Build Coastguard Worker     let size = MemoryLayout<UOffset>.size
376*890232f2SAndroid Build Coastguard Worker     preAlign(len: size, alignment: size)
377*890232f2SAndroid Build Coastguard Worker     return _bb.size &- off &+ UInt32(size)
378*890232f2SAndroid Build Coastguard Worker   }
379*890232f2SAndroid Build Coastguard Worker 
380*890232f2SAndroid Build Coastguard Worker   /// Tracks the elements written into the buffer
381*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
382*890232f2SAndroid Build Coastguard Worker   ///   - offset: The offset of the element witten
383*890232f2SAndroid Build Coastguard Worker   ///   - position: The position of the element
384*890232f2SAndroid Build Coastguard Worker   @inline(__always)
385*890232f2SAndroid Build Coastguard Worker   @usableFromInline
tracknull386*890232f2SAndroid Build Coastguard Worker   mutating internal func track(offset: UOffset, at position: VOffset) {
387*890232f2SAndroid Build Coastguard Worker     _vtableStorage.add(loc: FieldLoc(offset: offset, position: position))
388*890232f2SAndroid Build Coastguard Worker   }
389*890232f2SAndroid Build Coastguard Worker 
390*890232f2SAndroid Build Coastguard Worker   // MARK: - Inserting Vectors
391*890232f2SAndroid Build Coastguard Worker 
392*890232f2SAndroid Build Coastguard Worker   /// ``startVector(_:elementSize:)`` creates a new vector within buffer
393*890232f2SAndroid Build Coastguard Worker   ///
394*890232f2SAndroid Build Coastguard Worker   /// The function checks if there is a current object being written, if
395*890232f2SAndroid Build Coastguard Worker   /// the check passes it creates a buffer alignment of `length * elementSize`
396*890232f2SAndroid Build Coastguard Worker   /// ```swift
397*890232f2SAndroid Build Coastguard Worker   /// builder.startVector(
398*890232f2SAndroid Build Coastguard Worker   ///   int32Values.count, elementSize: 4)
399*890232f2SAndroid Build Coastguard Worker   /// ```
400*890232f2SAndroid Build Coastguard Worker   ///
401*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
402*890232f2SAndroid Build Coastguard Worker   ///   - len: Length of vector to be created
403*890232f2SAndroid Build Coastguard Worker   ///   - elementSize: Size of object type to be written
404*890232f2SAndroid Build Coastguard Worker   @inline(__always)
startVectornull405*890232f2SAndroid Build Coastguard Worker   mutating public func startVector(_ len: Int, elementSize: Int) {
406*890232f2SAndroid Build Coastguard Worker     notNested()
407*890232f2SAndroid Build Coastguard Worker     isNested = true
408*890232f2SAndroid Build Coastguard Worker     preAlign(len: len &* elementSize, type: UOffset.self)
409*890232f2SAndroid Build Coastguard Worker     preAlign(len: len &* elementSize, alignment: elementSize)
410*890232f2SAndroid Build Coastguard Worker   }
411*890232f2SAndroid Build Coastguard Worker 
412*890232f2SAndroid Build Coastguard Worker   /// ``endVector(len:)`` ends the currently created vector
413*890232f2SAndroid Build Coastguard Worker   ///
414*890232f2SAndroid Build Coastguard Worker   /// Calling ``endVector(len:)`` requires the length, of the current
415*890232f2SAndroid Build Coastguard Worker   /// vector. The length would be pushed to indicate the count of numbers
416*890232f2SAndroid Build Coastguard Worker   /// within the vector. If ``endVector(len:)`` is called without
417*890232f2SAndroid Build Coastguard Worker   /// ``startVector(_:elementSize:)`` it asserts.
418*890232f2SAndroid Build Coastguard Worker   ///
419*890232f2SAndroid Build Coastguard Worker   /// ```swift
420*890232f2SAndroid Build Coastguard Worker   /// let vectorOffset = builder.
421*890232f2SAndroid Build Coastguard Worker   ///   endVector(len: int32Values.count)
422*890232f2SAndroid Build Coastguard Worker   /// ```
423*890232f2SAndroid Build Coastguard Worker   ///
424*890232f2SAndroid Build Coastguard Worker   /// - Parameter len: Length of the buffer
425*890232f2SAndroid Build Coastguard Worker   /// - Returns: Returns the current ``Offset`` in the ``ByteBuffer``
426*890232f2SAndroid Build Coastguard Worker   @inline(__always)
endVectornull427*890232f2SAndroid Build Coastguard Worker   mutating public func endVector(len: Int) -> Offset {
428*890232f2SAndroid Build Coastguard Worker     assert(isNested, "Calling endVector without calling startVector")
429*890232f2SAndroid Build Coastguard Worker     isNested = false
430*890232f2SAndroid Build Coastguard Worker     return Offset(offset: push(element: Int32(len)))
431*890232f2SAndroid Build Coastguard Worker   }
432*890232f2SAndroid Build Coastguard Worker 
433*890232f2SAndroid Build Coastguard Worker   /// Creates a vector of type ``Scalar`` into the ``ByteBuffer``
434*890232f2SAndroid Build Coastguard Worker   ///
435*890232f2SAndroid Build Coastguard Worker   /// ``createVector(_:)-4swl0`` writes a vector of type Scalars into
436*890232f2SAndroid Build Coastguard Worker   /// ``ByteBuffer``. This is a convenient method instead of calling,
437*890232f2SAndroid Build Coastguard Worker   /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``
438*890232f2SAndroid Build Coastguard Worker   /// ```swift
439*890232f2SAndroid Build Coastguard Worker   /// let vectorOffset = builder.
440*890232f2SAndroid Build Coastguard Worker   ///   createVector([1, 2, 3, 4])
441*890232f2SAndroid Build Coastguard Worker   /// ```
442*890232f2SAndroid Build Coastguard Worker   ///
443*890232f2SAndroid Build Coastguard Worker   /// The underlying implementation simply calls ``createVector(_:size:)-4lhrv``
444*890232f2SAndroid Build Coastguard Worker   ///
445*890232f2SAndroid Build Coastguard Worker   /// - Parameter elements: elements to be written into the buffer
446*890232f2SAndroid Build Coastguard Worker   /// - returns: ``Offset`` of the vector
447*890232f2SAndroid Build Coastguard Worker   @inline(__always)
createVector<T: Scalar>null448*890232f2SAndroid Build Coastguard Worker   mutating public func createVector<T: Scalar>(_ elements: [T]) -> Offset {
449*890232f2SAndroid Build Coastguard Worker     createVector(elements, size: elements.count)
450*890232f2SAndroid Build Coastguard Worker   }
451*890232f2SAndroid Build Coastguard Worker 
452*890232f2SAndroid Build Coastguard Worker   ///  Creates a vector of type Scalar in the buffer
453*890232f2SAndroid Build Coastguard Worker   ///
454*890232f2SAndroid Build Coastguard Worker   /// ``createVector(_:)-4swl0`` writes a vector of type Scalars into
455*890232f2SAndroid Build Coastguard Worker   /// ``ByteBuffer``. This is a convenient method instead of calling,
456*890232f2SAndroid Build Coastguard Worker   /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``
457*890232f2SAndroid Build Coastguard Worker   /// ```swift
458*890232f2SAndroid Build Coastguard Worker   /// let vectorOffset = builder.
459*890232f2SAndroid Build Coastguard Worker   ///   createVector([1, 2, 3, 4], size: 4)
460*890232f2SAndroid Build Coastguard Worker   /// ```
461*890232f2SAndroid Build Coastguard Worker   ///
462*890232f2SAndroid Build Coastguard Worker   /// - Parameter elements: Elements to be written into the buffer
463*890232f2SAndroid Build Coastguard Worker   /// - Parameter size: Count of elements
464*890232f2SAndroid Build Coastguard Worker   /// - returns: ``Offset`` of the vector
465*890232f2SAndroid Build Coastguard Worker   @inline(__always)
466*890232f2SAndroid Build Coastguard Worker   mutating public func createVector<T: Scalar>(
467*890232f2SAndroid Build Coastguard Worker     _ elements: [T],
468*890232f2SAndroid Build Coastguard Worker     size: Int) -> Offset
469*890232f2SAndroid Build Coastguard Worker   {
470*890232f2SAndroid Build Coastguard Worker     let size = size
471*890232f2SAndroid Build Coastguard Worker     startVector(size, elementSize: MemoryLayout<T>.size)
472*890232f2SAndroid Build Coastguard Worker     _bb.push(elements: elements)
473*890232f2SAndroid Build Coastguard Worker     return endVector(len: size)
474*890232f2SAndroid Build Coastguard Worker   }
475*890232f2SAndroid Build Coastguard Worker 
476*890232f2SAndroid Build Coastguard Worker   /// Creates a vector of type ``Enum`` into the ``ByteBuffer``
477*890232f2SAndroid Build Coastguard Worker   ///
478*890232f2SAndroid Build Coastguard Worker   /// ``createVector(_:)-9h189`` writes a vector of type ``Enum`` into
479*890232f2SAndroid Build Coastguard Worker   /// ``ByteBuffer``. This is a convenient method instead of calling,
480*890232f2SAndroid Build Coastguard Worker   /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``
481*890232f2SAndroid Build Coastguard Worker   /// ```swift
482*890232f2SAndroid Build Coastguard Worker   /// let vectorOffset = builder.
483*890232f2SAndroid Build Coastguard Worker   ///   createVector([.swift, .cpp])
484*890232f2SAndroid Build Coastguard Worker   /// ```
485*890232f2SAndroid Build Coastguard Worker   ///
486*890232f2SAndroid Build Coastguard Worker   /// The underlying implementation simply calls ``createVector(_:size:)-7cx6z``
487*890232f2SAndroid Build Coastguard Worker   ///
488*890232f2SAndroid Build Coastguard Worker   /// - Parameter elements: elements to be written into the buffer
489*890232f2SAndroid Build Coastguard Worker   /// - returns: ``Offset`` of the vector
490*890232f2SAndroid Build Coastguard Worker   @inline(__always)
createVector<T: Enum>null491*890232f2SAndroid Build Coastguard Worker   mutating public func createVector<T: Enum>(_ elements: [T]) -> Offset {
492*890232f2SAndroid Build Coastguard Worker     createVector(elements, size: elements.count)
493*890232f2SAndroid Build Coastguard Worker   }
494*890232f2SAndroid Build Coastguard Worker 
495*890232f2SAndroid Build Coastguard Worker   /// Creates a vector of type ``Enum`` into the ``ByteBuffer``
496*890232f2SAndroid Build Coastguard Worker   ///
497*890232f2SAndroid Build Coastguard Worker   /// ``createVector(_:)-9h189`` writes a vector of type ``Enum`` into
498*890232f2SAndroid Build Coastguard Worker   /// ``ByteBuffer``. This is a convenient method instead of calling,
499*890232f2SAndroid Build Coastguard Worker   /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``
500*890232f2SAndroid Build Coastguard Worker   /// ```swift
501*890232f2SAndroid Build Coastguard Worker   /// let vectorOffset = builder.
502*890232f2SAndroid Build Coastguard Worker   ///   createVector([.swift, .cpp])
503*890232f2SAndroid Build Coastguard Worker   /// ```
504*890232f2SAndroid Build Coastguard Worker   ///
505*890232f2SAndroid Build Coastguard Worker   /// - Parameter elements: Elements to be written into the buffer
506*890232f2SAndroid Build Coastguard Worker   /// - Parameter size: Count of elements
507*890232f2SAndroid Build Coastguard Worker   /// - returns: ``Offset`` of the vector
508*890232f2SAndroid Build Coastguard Worker   @inline(__always)
509*890232f2SAndroid Build Coastguard Worker   mutating public func createVector<T: Enum>(
510*890232f2SAndroid Build Coastguard Worker     _ elements: [T],
511*890232f2SAndroid Build Coastguard Worker     size: Int) -> Offset
512*890232f2SAndroid Build Coastguard Worker   {
513*890232f2SAndroid Build Coastguard Worker     let size = size
514*890232f2SAndroid Build Coastguard Worker     startVector(size, elementSize: T.byteSize)
515*890232f2SAndroid Build Coastguard Worker     for e in elements.reversed() {
516*890232f2SAndroid Build Coastguard Worker       _bb.push(value: e.value, len: T.byteSize)
517*890232f2SAndroid Build Coastguard Worker     }
518*890232f2SAndroid Build Coastguard Worker     return endVector(len: size)
519*890232f2SAndroid Build Coastguard Worker   }
520*890232f2SAndroid Build Coastguard Worker 
521*890232f2SAndroid Build Coastguard Worker   /// Creates a vector of already written offsets
522*890232f2SAndroid Build Coastguard Worker   ///
523*890232f2SAndroid Build Coastguard Worker   /// ``createVector(ofOffsets:)`` creates a vector of ``Offset`` into
524*890232f2SAndroid Build Coastguard Worker   /// ``ByteBuffer``. This is a convenient method instead of calling,
525*890232f2SAndroid Build Coastguard Worker   /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``.
526*890232f2SAndroid Build Coastguard Worker   ///
527*890232f2SAndroid Build Coastguard Worker   /// The underlying implementation simply calls ``createVector(ofOffsets:len:)``
528*890232f2SAndroid Build Coastguard Worker   ///
529*890232f2SAndroid Build Coastguard Worker   /// ```swift
530*890232f2SAndroid Build Coastguard Worker   /// let namesOffsets = builder.
531*890232f2SAndroid Build Coastguard Worker   ///   createVector(ofOffsets: [name1, name2])
532*890232f2SAndroid Build Coastguard Worker   /// ```
533*890232f2SAndroid Build Coastguard Worker   /// - Parameter offsets: Array of offsets of type ``Offset``
534*890232f2SAndroid Build Coastguard Worker   /// - returns: ``Offset`` of the vector
535*890232f2SAndroid Build Coastguard Worker   @inline(__always)
createVectornull536*890232f2SAndroid Build Coastguard Worker   mutating public func createVector(ofOffsets offsets: [Offset]) -> Offset {
537*890232f2SAndroid Build Coastguard Worker     createVector(ofOffsets: offsets, len: offsets.count)
538*890232f2SAndroid Build Coastguard Worker   }
539*890232f2SAndroid Build Coastguard Worker 
540*890232f2SAndroid Build Coastguard Worker   /// Creates a vector of already written offsets
541*890232f2SAndroid Build Coastguard Worker   ///
542*890232f2SAndroid Build Coastguard Worker   /// ``createVector(ofOffsets:)`` creates a vector of ``Offset`` into
543*890232f2SAndroid Build Coastguard Worker   /// ``ByteBuffer``. This is a convenient method instead of calling,
544*890232f2SAndroid Build Coastguard Worker   /// ``startVector(_:elementSize:)`` and then ``endVector(len:)``
545*890232f2SAndroid Build Coastguard Worker   ///
546*890232f2SAndroid Build Coastguard Worker   /// ```swift
547*890232f2SAndroid Build Coastguard Worker   /// let namesOffsets = builder.
548*890232f2SAndroid Build Coastguard Worker   ///   createVector(ofOffsets: [name1, name2])
549*890232f2SAndroid Build Coastguard Worker   /// ```
550*890232f2SAndroid Build Coastguard Worker   ///
551*890232f2SAndroid Build Coastguard Worker   /// - Parameter offsets: Array of offsets of type ``Offset``
552*890232f2SAndroid Build Coastguard Worker   /// - Parameter size: Count of elements
553*890232f2SAndroid Build Coastguard Worker   /// - returns: ``Offset`` of the vector
554*890232f2SAndroid Build Coastguard Worker   @inline(__always)
555*890232f2SAndroid Build Coastguard Worker   mutating public func createVector(
556*890232f2SAndroid Build Coastguard Worker     ofOffsets offsets: [Offset],
557*890232f2SAndroid Build Coastguard Worker     len: Int) -> Offset
558*890232f2SAndroid Build Coastguard Worker   {
559*890232f2SAndroid Build Coastguard Worker     startVector(len, elementSize: MemoryLayout<Offset>.size)
560*890232f2SAndroid Build Coastguard Worker     for o in offsets.reversed() {
561*890232f2SAndroid Build Coastguard Worker       push(element: o)
562*890232f2SAndroid Build Coastguard Worker     }
563*890232f2SAndroid Build Coastguard Worker     return endVector(len: len)
564*890232f2SAndroid Build Coastguard Worker   }
565*890232f2SAndroid Build Coastguard Worker 
566*890232f2SAndroid Build Coastguard Worker   /// Creates a vector of strings
567*890232f2SAndroid Build Coastguard Worker   ///
568*890232f2SAndroid Build Coastguard Worker   /// ``createVector(ofStrings:)`` creates a vector of `String` into
569*890232f2SAndroid Build Coastguard Worker   /// ``ByteBuffer``. This is a convenient method instead of manually
570*890232f2SAndroid Build Coastguard Worker   /// creating the string offsets, you simply pass it to this function
571*890232f2SAndroid Build Coastguard Worker   /// and it would write the strings into the ``ByteBuffer``.
572*890232f2SAndroid Build Coastguard Worker   /// After that it calls ``createVector(ofOffsets:)``
573*890232f2SAndroid Build Coastguard Worker   ///
574*890232f2SAndroid Build Coastguard Worker   /// ```swift
575*890232f2SAndroid Build Coastguard Worker   /// let namesOffsets = builder.
576*890232f2SAndroid Build Coastguard Worker   ///   createVector(ofStrings: ["Name", "surname"])
577*890232f2SAndroid Build Coastguard Worker   /// ```
578*890232f2SAndroid Build Coastguard Worker   ///
579*890232f2SAndroid Build Coastguard Worker   /// - Parameter str: Array of string
580*890232f2SAndroid Build Coastguard Worker   /// - returns: ``Offset`` of the vector
581*890232f2SAndroid Build Coastguard Worker   @inline(__always)
createVectornull582*890232f2SAndroid Build Coastguard Worker   mutating public func createVector(ofStrings str: [String]) -> Offset {
583*890232f2SAndroid Build Coastguard Worker     var offsets: [Offset] = []
584*890232f2SAndroid Build Coastguard Worker     for s in str {
585*890232f2SAndroid Build Coastguard Worker       offsets.append(create(string: s))
586*890232f2SAndroid Build Coastguard Worker     }
587*890232f2SAndroid Build Coastguard Worker     return createVector(ofOffsets: offsets)
588*890232f2SAndroid Build Coastguard Worker   }
589*890232f2SAndroid Build Coastguard Worker 
590*890232f2SAndroid Build Coastguard Worker   /// Creates a vector of type ``NativeStruct``.
591*890232f2SAndroid Build Coastguard Worker   ///
592*890232f2SAndroid Build Coastguard Worker   /// Any swift struct in the generated code, should confirm to
593*890232f2SAndroid Build Coastguard Worker   /// ``NativeStruct``. Since the generated swift structs are padded
594*890232f2SAndroid Build Coastguard Worker   /// to the `FlatBuffers` standards.
595*890232f2SAndroid Build Coastguard Worker   ///
596*890232f2SAndroid Build Coastguard Worker   /// ```swift
597*890232f2SAndroid Build Coastguard Worker   /// let offsets = builder.
598*890232f2SAndroid Build Coastguard Worker   ///   createVector(ofStructs: [NativeStr(num: 1), NativeStr(num: 2)])
599*890232f2SAndroid Build Coastguard Worker   /// ```
600*890232f2SAndroid Build Coastguard Worker   ///
601*890232f2SAndroid Build Coastguard Worker   /// - Parameter structs: A vector of ``NativeStruct``
602*890232f2SAndroid Build Coastguard Worker   /// - Returns: ``Offset`` of the vector
603*890232f2SAndroid Build Coastguard Worker   @inline(__always)
createVector<T: NativeStruct>null604*890232f2SAndroid Build Coastguard Worker   mutating public func createVector<T: NativeStruct>(ofStructs structs: [T])
605*890232f2SAndroid Build Coastguard Worker     -> Offset
606*890232f2SAndroid Build Coastguard Worker   {
607*890232f2SAndroid Build Coastguard Worker     startVector(
608*890232f2SAndroid Build Coastguard Worker       structs.count * MemoryLayout<T>.size,
609*890232f2SAndroid Build Coastguard Worker       elementSize: MemoryLayout<T>.alignment)
610*890232f2SAndroid Build Coastguard Worker     for i in structs.reversed() {
611*890232f2SAndroid Build Coastguard Worker       _ = create(struct: i)
612*890232f2SAndroid Build Coastguard Worker     }
613*890232f2SAndroid Build Coastguard Worker     return endVector(len: structs.count)
614*890232f2SAndroid Build Coastguard Worker   }
615*890232f2SAndroid Build Coastguard Worker 
616*890232f2SAndroid Build Coastguard Worker   // MARK: - Inserting Structs
617*890232f2SAndroid Build Coastguard Worker 
618*890232f2SAndroid Build Coastguard Worker   /// Writes a ``NativeStruct`` into the ``ByteBuffer``
619*890232f2SAndroid Build Coastguard Worker   ///
620*890232f2SAndroid Build Coastguard Worker   /// Adds a native struct that's build and padded according
621*890232f2SAndroid Build Coastguard Worker   /// to `FlatBuffers` standards. with a predefined position.
622*890232f2SAndroid Build Coastguard Worker   ///
623*890232f2SAndroid Build Coastguard Worker   /// ```swift
624*890232f2SAndroid Build Coastguard Worker   /// let offset = builder.create(
625*890232f2SAndroid Build Coastguard Worker   ///   struct: NativeStr(num: 1),
626*890232f2SAndroid Build Coastguard Worker   ///   position: 10)
627*890232f2SAndroid Build Coastguard Worker   /// ```
628*890232f2SAndroid Build Coastguard Worker   ///
629*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
630*890232f2SAndroid Build Coastguard Worker   ///   - s: ``NativeStruct`` to be inserted into the ``ByteBuffer``
631*890232f2SAndroid Build Coastguard Worker   ///   - position: The  predefined position of the object
632*890232f2SAndroid Build Coastguard Worker   /// - Returns: ``Offset`` of written struct
633*890232f2SAndroid Build Coastguard Worker   @inline(__always)
634*890232f2SAndroid Build Coastguard Worker   @discardableResult
635*890232f2SAndroid Build Coastguard Worker   mutating public func create<T: NativeStruct>(
636*890232f2SAndroid Build Coastguard Worker     struct s: T, position: VOffset) -> Offset
637*890232f2SAndroid Build Coastguard Worker   {
638*890232f2SAndroid Build Coastguard Worker     let offset = create(struct: s)
639*890232f2SAndroid Build Coastguard Worker     _vtableStorage.add(loc: FieldLoc(
640*890232f2SAndroid Build Coastguard Worker       offset: _bb.size,
641*890232f2SAndroid Build Coastguard Worker       position: VOffset(position)))
642*890232f2SAndroid Build Coastguard Worker     return offset
643*890232f2SAndroid Build Coastguard Worker   }
644*890232f2SAndroid Build Coastguard Worker 
645*890232f2SAndroid Build Coastguard Worker   /// Writes a ``NativeStruct`` into the ``ByteBuffer``
646*890232f2SAndroid Build Coastguard Worker   ///
647*890232f2SAndroid Build Coastguard Worker   /// Adds a native struct that's build and padded according
648*890232f2SAndroid Build Coastguard Worker   /// to `FlatBuffers` standards, directly into the buffer without
649*890232f2SAndroid Build Coastguard Worker   /// a predefined position.
650*890232f2SAndroid Build Coastguard Worker   ///
651*890232f2SAndroid Build Coastguard Worker   /// ```swift
652*890232f2SAndroid Build Coastguard Worker   /// let offset = builder.create(
653*890232f2SAndroid Build Coastguard Worker   ///   struct: NativeStr(num: 1))
654*890232f2SAndroid Build Coastguard Worker   /// ```
655*890232f2SAndroid Build Coastguard Worker   ///
656*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
657*890232f2SAndroid Build Coastguard Worker   ///   - s: ``NativeStruct`` to be inserted into the ``ByteBuffer``
658*890232f2SAndroid Build Coastguard Worker   /// - Returns: ``Offset`` of written struct
659*890232f2SAndroid Build Coastguard Worker   @inline(__always)
660*890232f2SAndroid Build Coastguard Worker   @discardableResult
661*890232f2SAndroid Build Coastguard Worker   mutating public func create<T: NativeStruct>(
662*890232f2SAndroid Build Coastguard Worker     struct s: T) -> Offset
663*890232f2SAndroid Build Coastguard Worker   {
664*890232f2SAndroid Build Coastguard Worker     let size = MemoryLayout<T>.size
665*890232f2SAndroid Build Coastguard Worker     preAlign(len: size, alignment: MemoryLayout<T>.alignment)
666*890232f2SAndroid Build Coastguard Worker     _bb.push(struct: s, size: size)
667*890232f2SAndroid Build Coastguard Worker     return Offset(offset: _bb.size)
668*890232f2SAndroid Build Coastguard Worker   }
669*890232f2SAndroid Build Coastguard Worker 
670*890232f2SAndroid Build Coastguard Worker   // MARK: - Inserting Strings
671*890232f2SAndroid Build Coastguard Worker 
672*890232f2SAndroid Build Coastguard Worker   /// Insets a string into the buffer of type `UTF8`
673*890232f2SAndroid Build Coastguard Worker   ///
674*890232f2SAndroid Build Coastguard Worker   /// Adds a swift string into ``ByteBuffer`` by encoding it
675*890232f2SAndroid Build Coastguard Worker   /// using `UTF8`
676*890232f2SAndroid Build Coastguard Worker   ///
677*890232f2SAndroid Build Coastguard Worker   /// ```swift
678*890232f2SAndroid Build Coastguard Worker   /// let nameOffset = builder
679*890232f2SAndroid Build Coastguard Worker   ///   .create(string: "welcome")
680*890232f2SAndroid Build Coastguard Worker   /// ```
681*890232f2SAndroid Build Coastguard Worker   ///
682*890232f2SAndroid Build Coastguard Worker   /// - Parameter str: String to be serialized
683*890232f2SAndroid Build Coastguard Worker   /// - returns: ``Offset`` of inserted string
684*890232f2SAndroid Build Coastguard Worker   @inline(__always)
createnull685*890232f2SAndroid Build Coastguard Worker   mutating public func create(string str: String?) -> Offset {
686*890232f2SAndroid Build Coastguard Worker     guard let str = str else { return Offset() }
687*890232f2SAndroid Build Coastguard Worker     let len = str.utf8.count
688*890232f2SAndroid Build Coastguard Worker     notNested()
689*890232f2SAndroid Build Coastguard Worker     preAlign(len: len &+ 1, type: UOffset.self)
690*890232f2SAndroid Build Coastguard Worker     _bb.fill(padding: 1)
691*890232f2SAndroid Build Coastguard Worker     _bb.push(string: str, len: len)
692*890232f2SAndroid Build Coastguard Worker     push(element: UOffset(len))
693*890232f2SAndroid Build Coastguard Worker     return Offset(offset: _bb.size)
694*890232f2SAndroid Build Coastguard Worker   }
695*890232f2SAndroid Build Coastguard Worker 
696*890232f2SAndroid Build Coastguard Worker   /// Insets a shared string into the buffer of type `UTF8`
697*890232f2SAndroid Build Coastguard Worker   ///
698*890232f2SAndroid Build Coastguard Worker   /// Adds a swift string into ``ByteBuffer`` by encoding it
699*890232f2SAndroid Build Coastguard Worker   /// using `UTF8`. The function will check if the string,
700*890232f2SAndroid Build Coastguard Worker   /// is already written to the ``ByteBuffer``
701*890232f2SAndroid Build Coastguard Worker   ///
702*890232f2SAndroid Build Coastguard Worker   /// ```swift
703*890232f2SAndroid Build Coastguard Worker   /// let nameOffset = builder
704*890232f2SAndroid Build Coastguard Worker   ///   .createShared(string: "welcome")
705*890232f2SAndroid Build Coastguard Worker   ///
706*890232f2SAndroid Build Coastguard Worker   ///
707*890232f2SAndroid Build Coastguard Worker   /// let secondOffset = builder
708*890232f2SAndroid Build Coastguard Worker   ///   .createShared(string: "welcome")
709*890232f2SAndroid Build Coastguard Worker   ///
710*890232f2SAndroid Build Coastguard Worker   /// assert(nameOffset.o == secondOffset.o)
711*890232f2SAndroid Build Coastguard Worker   /// ```
712*890232f2SAndroid Build Coastguard Worker   ///
713*890232f2SAndroid Build Coastguard Worker   /// - Parameter str: String to be serialized
714*890232f2SAndroid Build Coastguard Worker   /// - returns: ``Offset`` of inserted string
715*890232f2SAndroid Build Coastguard Worker   @inline(__always)
createSharednull716*890232f2SAndroid Build Coastguard Worker   mutating public func createShared(string str: String?) -> Offset {
717*890232f2SAndroid Build Coastguard Worker     guard let str = str else { return Offset() }
718*890232f2SAndroid Build Coastguard Worker     if let offset = stringOffsetMap[str] {
719*890232f2SAndroid Build Coastguard Worker       return offset
720*890232f2SAndroid Build Coastguard Worker     }
721*890232f2SAndroid Build Coastguard Worker     let offset = create(string: str)
722*890232f2SAndroid Build Coastguard Worker     stringOffsetMap[str] = offset
723*890232f2SAndroid Build Coastguard Worker     return offset
724*890232f2SAndroid Build Coastguard Worker   }
725*890232f2SAndroid Build Coastguard Worker 
726*890232f2SAndroid Build Coastguard Worker   // MARK: - Inseting offsets
727*890232f2SAndroid Build Coastguard Worker 
728*890232f2SAndroid Build Coastguard Worker   /// Writes the ``Offset`` of an already written table
729*890232f2SAndroid Build Coastguard Worker   ///
730*890232f2SAndroid Build Coastguard Worker   /// Writes the ``Offset`` of a table if not empty into the
731*890232f2SAndroid Build Coastguard Worker   /// ``ByteBuffer``
732*890232f2SAndroid Build Coastguard Worker   ///
733*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
734*890232f2SAndroid Build Coastguard Worker   ///   - offset: ``Offset`` of another object to be written
735*890232f2SAndroid Build Coastguard Worker   ///   - position: The predefined position of the object
736*890232f2SAndroid Build Coastguard Worker   @inline(__always)
addnull737*890232f2SAndroid Build Coastguard Worker   mutating public func add(offset: Offset, at position: VOffset) {
738*890232f2SAndroid Build Coastguard Worker     if offset.isEmpty { return }
739*890232f2SAndroid Build Coastguard Worker     add(element: refer(to: offset.o), def: 0, at: position)
740*890232f2SAndroid Build Coastguard Worker   }
741*890232f2SAndroid Build Coastguard Worker 
742*890232f2SAndroid Build Coastguard Worker   /// Pushes a value of type ``Offset`` into the ``ByteBuffer``
743*890232f2SAndroid Build Coastguard Worker   /// - Parameter o: ``Offset``
744*890232f2SAndroid Build Coastguard Worker   /// - returns: Current position of the ``Offset``
745*890232f2SAndroid Build Coastguard Worker   @inline(__always)
746*890232f2SAndroid Build Coastguard Worker   @discardableResult
pushnull747*890232f2SAndroid Build Coastguard Worker   mutating public func push(element o: Offset) -> UOffset {
748*890232f2SAndroid Build Coastguard Worker     push(element: refer(to: o.o))
749*890232f2SAndroid Build Coastguard Worker   }
750*890232f2SAndroid Build Coastguard Worker 
751*890232f2SAndroid Build Coastguard Worker   // MARK: - Inserting Scalars to Buffer
752*890232f2SAndroid Build Coastguard Worker 
753*890232f2SAndroid Build Coastguard Worker   /// Writes a ``Scalar`` value into ``ByteBuffer``
754*890232f2SAndroid Build Coastguard Worker   ///
755*890232f2SAndroid Build Coastguard Worker   /// ``add(element:def:at:)`` takes in a default value, and current value
756*890232f2SAndroid Build Coastguard Worker   /// and the position within the `VTable`. The default value would not
757*890232f2SAndroid Build Coastguard Worker   /// be serialized if the value is the same as the current value or
758*890232f2SAndroid Build Coastguard Worker   /// `serializeDefaults` is equal to false.
759*890232f2SAndroid Build Coastguard Worker   ///
760*890232f2SAndroid Build Coastguard Worker   /// If serializing defaults is important ``init(initialSize:serializeDefaults:)``,
761*890232f2SAndroid Build Coastguard Worker   /// passing true for `serializeDefaults` would do the job.
762*890232f2SAndroid Build Coastguard Worker   ///
763*890232f2SAndroid Build Coastguard Worker   /// ```swift
764*890232f2SAndroid Build Coastguard Worker   /// // Adds 10 to the buffer
765*890232f2SAndroid Build Coastguard Worker   /// builder.add(element: Int(10), def: 1, position 12)
766*890232f2SAndroid Build Coastguard Worker   /// ```
767*890232f2SAndroid Build Coastguard Worker   ///
768*890232f2SAndroid Build Coastguard Worker   /// *NOTE: Never call this manually*
769*890232f2SAndroid Build Coastguard Worker   ///
770*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
771*890232f2SAndroid Build Coastguard Worker   ///   - element: Element to insert
772*890232f2SAndroid Build Coastguard Worker   ///   - def: Default value for that element
773*890232f2SAndroid Build Coastguard Worker   ///   - position: The predefined position of the element
774*890232f2SAndroid Build Coastguard Worker   @inline(__always)
775*890232f2SAndroid Build Coastguard Worker   mutating public func add<T: Scalar>(
776*890232f2SAndroid Build Coastguard Worker     element: T,
777*890232f2SAndroid Build Coastguard Worker     def: T,
778*890232f2SAndroid Build Coastguard Worker     at position: VOffset)
779*890232f2SAndroid Build Coastguard Worker   {
780*890232f2SAndroid Build Coastguard Worker     if element == def && !serializeDefaults { return }
781*890232f2SAndroid Build Coastguard Worker     track(offset: push(element: element), at: position)
782*890232f2SAndroid Build Coastguard Worker   }
783*890232f2SAndroid Build Coastguard Worker 
784*890232f2SAndroid Build Coastguard Worker   /// Writes a optional ``Scalar`` value into ``ByteBuffer``
785*890232f2SAndroid Build Coastguard Worker   ///
786*890232f2SAndroid Build Coastguard Worker   /// Takes an optional value to be written into the ``ByteBuffer``
787*890232f2SAndroid Build Coastguard Worker   ///
788*890232f2SAndroid Build Coastguard Worker   /// *NOTE: Never call this manually*
789*890232f2SAndroid Build Coastguard Worker   ///
790*890232f2SAndroid Build Coastguard Worker   /// - Parameters:
791*890232f2SAndroid Build Coastguard Worker   ///   - element: Optional element of type scalar
792*890232f2SAndroid Build Coastguard Worker   ///   - position: The predefined position of the element
793*890232f2SAndroid Build Coastguard Worker   @inline(__always)
add<T: Scalar>null794*890232f2SAndroid Build Coastguard Worker   mutating public func add<T: Scalar>(element: T?, at position: VOffset) {
795*890232f2SAndroid Build Coastguard Worker     guard let element = element else { return }
796*890232f2SAndroid Build Coastguard Worker     track(offset: push(element: element), at: position)
797*890232f2SAndroid Build Coastguard Worker   }
798*890232f2SAndroid Build Coastguard Worker 
799*890232f2SAndroid Build Coastguard Worker   /// Pushes a values of type ``Scalar`` into the ``ByteBuffer``
800*890232f2SAndroid Build Coastguard Worker   ///
801*890232f2SAndroid Build Coastguard Worker   /// *NOTE: Never call this manually*
802*890232f2SAndroid Build Coastguard Worker   ///
803*890232f2SAndroid Build Coastguard Worker   /// - Parameter element: Element to insert
804*890232f2SAndroid Build Coastguard Worker   /// - returns: Postion of the Element
805*890232f2SAndroid Build Coastguard Worker   @inline(__always)
806*890232f2SAndroid Build Coastguard Worker   @discardableResult
push<T: Scalar>null807*890232f2SAndroid Build Coastguard Worker   mutating public func push<T: Scalar>(element: T) -> UOffset {
808*890232f2SAndroid Build Coastguard Worker     let size = MemoryLayout<T>.size
809*890232f2SAndroid Build Coastguard Worker     preAlign(
810*890232f2SAndroid Build Coastguard Worker       len: size,
811*890232f2SAndroid Build Coastguard Worker       alignment: size)
812*890232f2SAndroid Build Coastguard Worker     _bb.push(value: element, len: size)
813*890232f2SAndroid Build Coastguard Worker     return _bb.size
814*890232f2SAndroid Build Coastguard Worker   }
815*890232f2SAndroid Build Coastguard Worker 
816*890232f2SAndroid Build Coastguard Worker }
817*890232f2SAndroid Build Coastguard Worker 
818*890232f2SAndroid Build Coastguard Worker extension FlatBufferBuilder: CustomDebugStringConvertible {
819*890232f2SAndroid Build Coastguard Worker 
820*890232f2SAndroid Build Coastguard Worker   public var debugDescription: String {
821*890232f2SAndroid Build Coastguard Worker     """
822*890232f2SAndroid Build Coastguard Worker     buffer debug:
823*890232f2SAndroid Build Coastguard Worker     \(_bb)
824*890232f2SAndroid Build Coastguard Worker     builder debug:
825*890232f2SAndroid Build Coastguard Worker     { finished: \(finished), serializeDefaults: \(serializeDefaults), isNested: \(isNested) }
826*890232f2SAndroid Build Coastguard Worker     """
827*890232f2SAndroid Build Coastguard Worker   }
828*890232f2SAndroid Build Coastguard Worker 
829*890232f2SAndroid Build Coastguard Worker   /// VTableStorage is a class to contain the VTable buffer that would be serialized into buffer
830*890232f2SAndroid Build Coastguard Worker   @usableFromInline
831*890232f2SAndroid Build Coastguard Worker   internal class VTableStorage {
832*890232f2SAndroid Build Coastguard Worker     /// Memory check since deallocating each time we want to clear would be expensive
833*890232f2SAndroid Build Coastguard Worker     /// and memory leaks would happen if we dont deallocate the first allocated memory.
834*890232f2SAndroid Build Coastguard Worker     /// memory is promised to be available before adding `FieldLoc`
835*890232f2SAndroid Build Coastguard Worker     private var memoryInUse = false
836*890232f2SAndroid Build Coastguard Worker     /// Size of FieldLoc in memory
837*890232f2SAndroid Build Coastguard Worker     let size = MemoryLayout<FieldLoc>.stride
838*890232f2SAndroid Build Coastguard Worker     /// Memeory buffer
839*890232f2SAndroid Build Coastguard Worker     var memory: UnsafeMutableRawBufferPointer!
840*890232f2SAndroid Build Coastguard Worker     /// Capacity of the current buffer
841*890232f2SAndroid Build Coastguard Worker     var capacity: Int = 0
842*890232f2SAndroid Build Coastguard Worker     /// Maximuim offset written to the class
843*890232f2SAndroid Build Coastguard Worker     var maxOffset: VOffset = 0
844*890232f2SAndroid Build Coastguard Worker     /// number of fields written into the buffer
845*890232f2SAndroid Build Coastguard Worker     var numOfFields: Int = 0
846*890232f2SAndroid Build Coastguard Worker     /// Last written Index
847*890232f2SAndroid Build Coastguard Worker     var writtenIndex: Int = 0
848*890232f2SAndroid Build Coastguard Worker 
849*890232f2SAndroid Build Coastguard Worker     /// Creates the memory to store the buffer in
850*890232f2SAndroid Build Coastguard Worker     @usableFromInline
851*890232f2SAndroid Build Coastguard Worker     @inline(__always)
852*890232f2SAndroid Build Coastguard Worker     init() {
853*890232f2SAndroid Build Coastguard Worker       memory = UnsafeMutableRawBufferPointer.allocate(
854*890232f2SAndroid Build Coastguard Worker         byteCount: 0,
855*890232f2SAndroid Build Coastguard Worker         alignment: 0)
856*890232f2SAndroid Build Coastguard Worker     }
857*890232f2SAndroid Build Coastguard Worker 
858*890232f2SAndroid Build Coastguard Worker     @inline(__always)
859*890232f2SAndroid Build Coastguard Worker     deinit {
860*890232f2SAndroid Build Coastguard Worker       memory.deallocate()
861*890232f2SAndroid Build Coastguard Worker     }
862*890232f2SAndroid Build Coastguard Worker 
863*890232f2SAndroid Build Coastguard Worker     /// Builds a buffer with byte count of fieldloc.size * count of field numbers
864*890232f2SAndroid Build Coastguard Worker     /// - Parameter count: number of fields to be written
865*890232f2SAndroid Build Coastguard Worker     @inline(__always)
startnull866*890232f2SAndroid Build Coastguard Worker     func start(count: Int) {
867*890232f2SAndroid Build Coastguard Worker       assert(count >= 0, "number of fields should NOT be negative")
868*890232f2SAndroid Build Coastguard Worker       let capacity = count &* size
869*890232f2SAndroid Build Coastguard Worker       ensure(space: capacity)
870*890232f2SAndroid Build Coastguard Worker     }
871*890232f2SAndroid Build Coastguard Worker 
872*890232f2SAndroid Build Coastguard Worker     /// Adds a FieldLoc into the buffer, which would track how many have been written,
873*890232f2SAndroid Build Coastguard Worker     /// and max offset
874*890232f2SAndroid Build Coastguard Worker     /// - Parameter loc: Location of encoded element
875*890232f2SAndroid Build Coastguard Worker     @inline(__always)
addnull876*890232f2SAndroid Build Coastguard Worker     func add(loc: FieldLoc) {
877*890232f2SAndroid Build Coastguard Worker       memory.baseAddress?.advanced(by: writtenIndex).storeBytes(
878*890232f2SAndroid Build Coastguard Worker         of: loc,
879*890232f2SAndroid Build Coastguard Worker         as: FieldLoc.self)
880*890232f2SAndroid Build Coastguard Worker       writtenIndex = writtenIndex &+ size
881*890232f2SAndroid Build Coastguard Worker       numOfFields = numOfFields &+ 1
882*890232f2SAndroid Build Coastguard Worker       maxOffset = max(loc.position, maxOffset)
883*890232f2SAndroid Build Coastguard Worker     }
884*890232f2SAndroid Build Coastguard Worker 
885*890232f2SAndroid Build Coastguard Worker     /// Clears the data stored related to the encoded buffer
886*890232f2SAndroid Build Coastguard Worker     @inline(__always)
clearnull887*890232f2SAndroid Build Coastguard Worker     func clear() {
888*890232f2SAndroid Build Coastguard Worker       maxOffset = 0
889*890232f2SAndroid Build Coastguard Worker       numOfFields = 0
890*890232f2SAndroid Build Coastguard Worker       writtenIndex = 0
891*890232f2SAndroid Build Coastguard Worker     }
892*890232f2SAndroid Build Coastguard Worker 
893*890232f2SAndroid Build Coastguard Worker     /// Ensure that the buffer has enough space instead of recreating the buffer each time.
894*890232f2SAndroid Build Coastguard Worker     /// - Parameter space: space required for the new vtable
895*890232f2SAndroid Build Coastguard Worker     @inline(__always)
ensurenull896*890232f2SAndroid Build Coastguard Worker     func ensure(space: Int) {
897*890232f2SAndroid Build Coastguard Worker       guard space &+ writtenIndex > capacity else { return }
898*890232f2SAndroid Build Coastguard Worker       memory.deallocate()
899*890232f2SAndroid Build Coastguard Worker       memory = UnsafeMutableRawBufferPointer.allocate(
900*890232f2SAndroid Build Coastguard Worker         byteCount: space,
901*890232f2SAndroid Build Coastguard Worker         alignment: size)
902*890232f2SAndroid Build Coastguard Worker       capacity = space
903*890232f2SAndroid Build Coastguard Worker     }
904*890232f2SAndroid Build Coastguard Worker 
905*890232f2SAndroid Build Coastguard Worker     /// Loads an object of type `FieldLoc` from buffer memory
906*890232f2SAndroid Build Coastguard Worker     /// - Parameter index: index of element
907*890232f2SAndroid Build Coastguard Worker     /// - Returns: a FieldLoc at index
908*890232f2SAndroid Build Coastguard Worker     @inline(__always)
loadnull909*890232f2SAndroid Build Coastguard Worker     func load(at index: Int) -> FieldLoc {
910*890232f2SAndroid Build Coastguard Worker       memory.load(fromByteOffset: index, as: FieldLoc.self)
911*890232f2SAndroid Build Coastguard Worker     }
912*890232f2SAndroid Build Coastguard Worker 
913*890232f2SAndroid Build Coastguard Worker   }
914*890232f2SAndroid Build Coastguard Worker 
915*890232f2SAndroid Build Coastguard Worker   internal struct FieldLoc {
916*890232f2SAndroid Build Coastguard Worker     var offset: UOffset
917*890232f2SAndroid Build Coastguard Worker     var position: VOffset
918*890232f2SAndroid Build Coastguard Worker   }
919*890232f2SAndroid Build Coastguard Worker 
920*890232f2SAndroid Build Coastguard Worker }
921