blob: cf21dd55d5c939cd51147883454c2e457a27f4bf [file] [log] [blame]
rw74d5f372014-07-11 16:12:35 -07001package flatbuffers
2
3// Builder is a state machine for creating FlatBuffer objects.
4// Use a Builder to construct object(s) starting from leaf nodes.
5//
6// A Builder constructs byte buffers in a last-first manner for simplicity and
7// performance.
8type Builder struct {
rw2dfff152015-11-11 17:08:16 -08009 // `Bytes` gives raw access to the buffer. Most users will want to use
10 // FinishedBytes() instead.
rw74d5f372014-07-11 16:12:35 -070011 Bytes []byte
12
rw2dfff152015-11-11 17:08:16 -080013 minalign int
14 vtable []UOffsetT
15 objectEnd UOffsetT
16 vtables []UOffsetT
17 head UOffsetT
18 nested bool
19 finished bool
rw74d5f372014-07-11 16:12:35 -070020}
21
22// NewBuilder initializes a Builder of size `initial_size`.
23// The internal buffer is grown as needed.
24func NewBuilder(initialSize int) *Builder {
25 if initialSize <= 0 {
26 initialSize = 0
27 }
28
29 b := &Builder{}
30 b.Bytes = make([]byte, initialSize)
31 b.head = UOffsetT(initialSize)
32 b.minalign = 1
33 b.vtables = make([]UOffsetT, 0, 16) // sensible default capacity
34
35 return b
36}
37
rwd756efb2015-04-02 19:33:00 -070038// Reset truncates the underlying Builder buffer, facilitating alloc-free
rw2dfff152015-11-11 17:08:16 -080039// reuse of a Builder. It also resets bookkeeping data.
rwd756efb2015-04-02 19:33:00 -070040func (b *Builder) Reset() {
rw3dd54422015-05-09 16:07:11 -070041 if b.Bytes != nil {
rwe5c21ec2015-05-09 16:32:26 -070042 b.Bytes = b.Bytes[:cap(b.Bytes)]
rw3dd54422015-05-09 16:07:11 -070043 }
44
45 if b.vtables != nil {
46 b.vtables = b.vtables[:0]
47 }
48
49 if b.vtable != nil {
50 b.vtable = b.vtable[:0]
51 }
rwe5c21ec2015-05-09 16:32:26 -070052
53 b.head = UOffsetT(len(b.Bytes))
54 b.minalign = 1
rw2dfff152015-11-11 17:08:16 -080055 b.nested = false
56 b.finished = false
57}
58
59// FinishedBytes returns a pointer to the written data in the byte buffer.
60// Panics if the builder is not in a finished state (which is caused by calling
61// `Finish()`).
62func (b *Builder) FinishedBytes() []byte {
63 b.assertFinished()
64 return b.Bytes[b.Head():]
rwd756efb2015-04-02 19:33:00 -070065}
66
rw74d5f372014-07-11 16:12:35 -070067// StartObject initializes bookkeeping for writing a new object.
68func (b *Builder) StartObject(numfields int) {
rw2dfff152015-11-11 17:08:16 -080069 b.assertNotNested()
70 b.nested = true
rw4d305f52015-06-24 11:53:44 -040071
rw74d5f372014-07-11 16:12:35 -070072 // use 32-bit offsets so that arithmetic doesn't overflow.
rw3dd54422015-05-09 16:07:11 -070073 if cap(b.vtable) < numfields || b.vtable == nil {
74 b.vtable = make([]UOffsetT, numfields)
75 } else {
76 b.vtable = b.vtable[:numfields]
rwe11da872015-05-09 16:10:03 -070077 for i := 0; i < len(b.vtable); i++ {
rw3dd54422015-05-09 16:07:11 -070078 b.vtable[i] = 0
79 }
80 }
81
rw74d5f372014-07-11 16:12:35 -070082 b.objectEnd = b.Offset()
83 b.minalign = 1
84}
85
86// WriteVtable serializes the vtable for the current object, if applicable.
87//
88// Before writing out the vtable, this checks pre-existing vtables for equality
89// to this one. If an equal vtable is found, point the object to the existing
90// vtable and return.
91//
92// Because vtable values are sensitive to alignment of object data, not all
93// logically-equal vtables will be deduplicated.
94//
95// A vtable has the following format:
96// <VOffsetT: size of the vtable in bytes, including this value>
97// <VOffsetT: size of the object in bytes, including the vtable offset>
98// <VOffsetT: offset for a field> * N, where N is the number of fields in
99// the schema for this type. Includes deprecated fields.
100// Thus, a vtable is made of 2 + N elements, each SizeVOffsetT bytes wide.
101//
102// An object has the following format:
103// <SOffsetT: offset to this object's vtable (may be negative)>
104// <byte: data>+
105func (b *Builder) WriteVtable() (n UOffsetT) {
106 // Prepend a zero scalar to the object. Later in this function we'll
107 // write an offset here that points to the object's vtable:
108 b.PrependSOffsetT(0)
109
110 objectOffset := b.Offset()
111 existingVtable := UOffsetT(0)
112
113 // Search backwards through existing vtables, because similar vtables
114 // are likely to have been recently appended. See
115 // BenchmarkVtableDeduplication for a case in which this heuristic
116 // saves about 30% of the time used in writing objects with duplicate
117 // tables.
118 for i := len(b.vtables) - 1; i >= 0; i-- {
119 // Find the other vtable, which is associated with `i`:
120 vt2Offset := b.vtables[i]
121 vt2Start := len(b.Bytes) - int(vt2Offset)
122 vt2Len := GetVOffsetT(b.Bytes[vt2Start:])
123
124 metadata := VtableMetadataFields * SizeVOffsetT
125 vt2End := vt2Start + int(vt2Len)
126 vt2 := b.Bytes[vt2Start+metadata : vt2End]
127
128 // Compare the other vtable to the one under consideration.
129 // If they are equal, store the offset and break:
130 if vtableEqual(b.vtable, objectOffset, vt2) {
131 existingVtable = vt2Offset
132 break
133 }
134 }
135
136 if existingVtable == 0 {
137 // Did not find a vtable, so write this one to the buffer.
138
139 // Write out the current vtable in reverse , because
140 // serialization occurs in last-first order:
141 for i := len(b.vtable) - 1; i >= 0; i-- {
142 var off UOffsetT
143 if b.vtable[i] != 0 {
144 // Forward reference to field;
rw2dfff152015-11-11 17:08:16 -0800145 // use 32bit number to assert no overflow:
rw74d5f372014-07-11 16:12:35 -0700146 off = objectOffset - b.vtable[i]
147 }
148
149 b.PrependVOffsetT(VOffsetT(off))
150 }
151
152 // The two metadata fields are written last.
153
154 // First, store the object bytesize:
155 objectSize := objectOffset - b.objectEnd
156 b.PrependVOffsetT(VOffsetT(objectSize))
157
158 // Second, store the vtable bytesize:
159 vBytes := (len(b.vtable) + VtableMetadataFields) * SizeVOffsetT
160 b.PrependVOffsetT(VOffsetT(vBytes))
161
162 // Next, write the offset to the new vtable in the
163 // already-allocated SOffsetT at the beginning of this object:
164 objectStart := SOffsetT(len(b.Bytes)) - SOffsetT(objectOffset)
165 WriteSOffsetT(b.Bytes[objectStart:],
166 SOffsetT(b.Offset())-SOffsetT(objectOffset))
167
168 // Finally, store this vtable in memory for future
169 // deduplication:
170 b.vtables = append(b.vtables, b.Offset())
171 } else {
172 // Found a duplicate vtable.
173
174 objectStart := SOffsetT(len(b.Bytes)) - SOffsetT(objectOffset)
175 b.head = UOffsetT(objectStart)
176
177 // Write the offset to the found vtable in the
178 // already-allocated SOffsetT at the beginning of this object:
179 WriteSOffsetT(b.Bytes[b.head:],
180 SOffsetT(existingVtable)-SOffsetT(objectOffset))
181 }
182
rw3dd54422015-05-09 16:07:11 -0700183 b.vtable = b.vtable[:0]
rw74d5f372014-07-11 16:12:35 -0700184 return objectOffset
185}
186
187// EndObject writes data necessary to finish object construction.
188func (b *Builder) EndObject() UOffsetT {
rw2dfff152015-11-11 17:08:16 -0800189 b.assertNested()
rw4d305f52015-06-24 11:53:44 -0400190 n := b.WriteVtable()
rw2dfff152015-11-11 17:08:16 -0800191 b.nested = false
rw4d305f52015-06-24 11:53:44 -0400192 return n
rw74d5f372014-07-11 16:12:35 -0700193}
194
195// Doubles the size of the byteslice, and copies the old data towards the
196// end of the new byteslice (since we build the buffer backwards).
197func (b *Builder) growByteBuffer() {
Luna118abc22014-10-29 11:55:21 +0100198 if (int64(len(b.Bytes)) & int64(0xC0000000)) != 0 {
rw74d5f372014-07-11 16:12:35 -0700199 panic("cannot grow buffer beyond 2 gigabytes")
200 }
rwd756efb2015-04-02 19:33:00 -0700201 newLen := len(b.Bytes) * 2
202 if newLen == 0 {
203 newLen = 1
rw74d5f372014-07-11 16:12:35 -0700204 }
rwd756efb2015-04-02 19:33:00 -0700205
206 if cap(b.Bytes) >= newLen {
207 b.Bytes = b.Bytes[:newLen]
208 } else {
209 extension := make([]byte, newLen-len(b.Bytes))
210 b.Bytes = append(b.Bytes, extension...)
211 }
212
213 middle := newLen / 2
214 copy(b.Bytes[middle:], b.Bytes[:middle])
rw74d5f372014-07-11 16:12:35 -0700215}
216
217// Head gives the start of useful data in the underlying byte buffer.
218// Note: unlike other functions, this value is interpreted as from the left.
219func (b *Builder) Head() UOffsetT {
220 return b.head
221}
222
223// Offset relative to the end of the buffer.
224func (b *Builder) Offset() UOffsetT {
225 return UOffsetT(len(b.Bytes)) - b.head
226}
227
228// Pad places zeros at the current offset.
229func (b *Builder) Pad(n int) {
230 for i := 0; i < n; i++ {
231 b.PlaceByte(0)
232 }
233}
234
235// Prep prepares to write an element of `size` after `additional_bytes`
236// have been written, e.g. if you write a string, you need to align such
237// the int length field is aligned to SizeInt32, and the string data follows it
238// directly.
239// If all you need to do is align, `additionalBytes` will be 0.
240func (b *Builder) Prep(size, additionalBytes int) {
241 // Track the biggest thing we've ever aligned to.
242 if size > b.minalign {
243 b.minalign = size
244 }
245 // Find the amount of alignment needed such that `size` is properly
246 // aligned after `additionalBytes`:
247 alignSize := (^(len(b.Bytes) - int(b.Head()) + additionalBytes)) + 1
248 alignSize &= (size - 1)
249
250 // Reallocate the buffer if needed:
Kyle Jonesc4a3e2f2015-03-31 12:16:36 -0700251 for int(b.head) <= alignSize+size+additionalBytes {
rw74d5f372014-07-11 16:12:35 -0700252 oldBufSize := len(b.Bytes)
253 b.growByteBuffer()
254 b.head += UOffsetT(len(b.Bytes) - oldBufSize)
255 }
256 b.Pad(alignSize)
257}
258
259// PrependSOffsetT prepends an SOffsetT, relative to where it will be written.
260func (b *Builder) PrependSOffsetT(off SOffsetT) {
261 b.Prep(SizeSOffsetT, 0) // Ensure alignment is already done.
262 if !(UOffsetT(off) <= b.Offset()) {
263 panic("unreachable: off <= b.Offset()")
264 }
265 off2 := SOffsetT(b.Offset()) - off + SOffsetT(SizeSOffsetT)
266 b.PlaceSOffsetT(off2)
267}
268
269// PrependUOffsetT prepends an UOffsetT, relative to where it will be written.
270func (b *Builder) PrependUOffsetT(off UOffsetT) {
271 b.Prep(SizeUOffsetT, 0) // Ensure alignment is already done.
272 if !(off <= b.Offset()) {
273 panic("unreachable: off <= b.Offset()")
274 }
275 off2 := b.Offset() - off + UOffsetT(SizeUOffsetT)
276 b.PlaceUOffsetT(off2)
277}
278
279// StartVector initializes bookkeeping for writing a new vector.
280//
281// A vector has the following format:
282// <UOffsetT: number of elements in this vector>
283// <T: data>+, where T is the type of elements of this vector.
rw417cb872014-09-03 23:26:06 -0700284func (b *Builder) StartVector(elemSize, numElems, alignment int) UOffsetT {
rw2dfff152015-11-11 17:08:16 -0800285 b.assertNotNested()
286 b.nested = true
rw74d5f372014-07-11 16:12:35 -0700287 b.Prep(SizeUint32, elemSize*numElems)
rw417cb872014-09-03 23:26:06 -0700288 b.Prep(alignment, elemSize*numElems) // Just in case alignment > int.
rw74d5f372014-07-11 16:12:35 -0700289 return b.Offset()
290}
291
292// EndVector writes data necessary to finish vector construction.
293func (b *Builder) EndVector(vectorNumElems int) UOffsetT {
rw2dfff152015-11-11 17:08:16 -0800294 b.assertNested()
295
rw74d5f372014-07-11 16:12:35 -0700296 // we already made space for this, so write without PrependUint32
297 b.PlaceUOffsetT(UOffsetT(vectorNumElems))
rw2dfff152015-11-11 17:08:16 -0800298
299 b.nested = false
rw74d5f372014-07-11 16:12:35 -0700300 return b.Offset()
301}
302
303// CreateString writes a null-terminated string as a vector.
304func (b *Builder) CreateString(s string) UOffsetT {
rw2dfff152015-11-11 17:08:16 -0800305 b.assertNotNested()
306 b.nested = true
rw4d305f52015-06-24 11:53:44 -0400307
rwc127cf72015-05-20 12:00:44 -0700308 b.Prep(int(SizeUOffsetT), (len(s)+1)*SizeByte)
309 b.PlaceByte(0)
310
311 l := UOffsetT(len(s))
312
313 b.head -= l
314 copy(b.Bytes[b.head:b.head+l], s)
315
316 return b.EndVector(len(s))
rwace7fa82015-04-02 18:22:13 -0700317}
318
rw3dd54422015-05-09 16:07:11 -0700319// CreateByteString writes a byte slice as a string (null-terminated).
rwace7fa82015-04-02 18:22:13 -0700320func (b *Builder) CreateByteString(s []byte) UOffsetT {
rw2dfff152015-11-11 17:08:16 -0800321 b.assertNotNested()
322 b.nested = true
rw4d305f52015-06-24 11:53:44 -0400323
rw74d5f372014-07-11 16:12:35 -0700324 b.Prep(int(SizeUOffsetT), (len(s)+1)*SizeByte)
325 b.PlaceByte(0)
326
rwace7fa82015-04-02 18:22:13 -0700327 l := UOffsetT(len(s))
rw74d5f372014-07-11 16:12:35 -0700328
329 b.head -= l
rwace7fa82015-04-02 18:22:13 -0700330 copy(b.Bytes[b.head:b.head+l], s)
rw74d5f372014-07-11 16:12:35 -0700331
rwace7fa82015-04-02 18:22:13 -0700332 return b.EndVector(len(s))
rw74d5f372014-07-11 16:12:35 -0700333}
334
Ben Harper6a012632015-03-08 21:39:01 +0200335// CreateByteVector writes a ubyte vector
336func (b *Builder) CreateByteVector(v []byte) UOffsetT {
rw2dfff152015-11-11 17:08:16 -0800337 b.assertNotNested()
338 b.nested = true
339
Ben Harper6a012632015-03-08 21:39:01 +0200340 b.Prep(int(SizeUOffsetT), len(v)*SizeByte)
341
342 l := UOffsetT(len(v))
343
344 b.head -= l
345 copy(b.Bytes[b.head:b.head+l], v)
346
347 return b.EndVector(len(v))
348}
349
rw2dfff152015-11-11 17:08:16 -0800350func (b *Builder) assertNested() {
351 // If you get this assert, you're in an object while trying to write
352 // data that belongs outside of an object.
353 // To fix this, write non-inline data (like vectors) before creating
354 // objects.
355 if !b.nested {
356 panic("Incorrect creation order: must be inside object.")
rw74d5f372014-07-11 16:12:35 -0700357 }
358}
359
rw2dfff152015-11-11 17:08:16 -0800360func (b *Builder) assertNotNested() {
361 // If you hit this, you're trying to construct a Table/Vector/String
362 // during the construction of its parent table (between the MyTableBuilder
363 // and builder.Finish()).
364 // Move the creation of these sub-objects to above the MyTableBuilder to
365 // not get this assert.
366 // Ignoring this assert may appear to work in simple cases, but the reason
367 // it is here is that storing objects in-line may cause vtable offsets
368 // to not fit anymore. It also leads to vtable duplication.
369 if b.nested {
370 panic("Incorrect creation order: object must not be nested.")
371 }
372}
373
374func (b *Builder) assertFinished() {
375 // If you get this assert, you're attempting to get access a buffer
376 // which hasn't been finished yet. Be sure to call builder.Finish()
377 // with your root table.
378 // If you really need to access an unfinished buffer, use the Bytes
379 // buffer directly.
380 if !b.finished {
381 panic("Incorrect use of FinishedBytes(): must call 'Finish' first.")
rw74d5f372014-07-11 16:12:35 -0700382 }
383}
384
385// PrependBoolSlot prepends a bool onto the object at vtable slot `o`.
386// If value `x` equals default `d`, then the slot will be set to zero and no
387// other data will be written.
388func (b *Builder) PrependBoolSlot(o int, x, d bool) {
389 val := byte(0)
390 if x {
391 val = 1
392 }
393 def := byte(0)
394 if d {
395 def = 1
396 }
397 b.PrependByteSlot(o, val, def)
398}
399
400// PrependByteSlot prepends a byte onto the object at vtable slot `o`.
401// If value `x` equals default `d`, then the slot will be set to zero and no
402// other data will be written.
403func (b *Builder) PrependByteSlot(o int, x, d byte) {
404 if x != d {
405 b.PrependByte(x)
406 b.Slot(o)
407 }
408}
409
410// PrependUint8Slot prepends a uint8 onto the object at vtable slot `o`.
411// If value `x` equals default `d`, then the slot will be set to zero and no
412// other data will be written.
413func (b *Builder) PrependUint8Slot(o int, x, d uint8) {
414 if x != d {
415 b.PrependUint8(x)
416 b.Slot(o)
417 }
418}
419
420// PrependUint16Slot prepends a uint16 onto the object at vtable slot `o`.
421// If value `x` equals default `d`, then the slot will be set to zero and no
422// other data will be written.
423func (b *Builder) PrependUint16Slot(o int, x, d uint16) {
424 if x != d {
425 b.PrependUint16(x)
426 b.Slot(o)
427 }
428}
429
430// PrependUint32Slot prepends a uint32 onto the object at vtable slot `o`.
431// If value `x` equals default `d`, then the slot will be set to zero and no
432// other data will be written.
433func (b *Builder) PrependUint32Slot(o int, x, d uint32) {
434 if x != d {
435 b.PrependUint32(x)
436 b.Slot(o)
437 }
438}
439
440// PrependUint64Slot prepends a uint64 onto the object at vtable slot `o`.
441// If value `x` equals default `d`, then the slot will be set to zero and no
442// other data will be written.
443func (b *Builder) PrependUint64Slot(o int, x, d uint64) {
444 if x != d {
445 b.PrependUint64(x)
446 b.Slot(o)
447 }
448}
449
450// PrependInt8Slot prepends a int8 onto the object at vtable slot `o`.
451// If value `x` equals default `d`, then the slot will be set to zero and no
452// other data will be written.
453func (b *Builder) PrependInt8Slot(o int, x, d int8) {
454 if x != d {
455 b.PrependInt8(x)
456 b.Slot(o)
457 }
458}
459
460// PrependInt16Slot prepends a int16 onto the object at vtable slot `o`.
461// If value `x` equals default `d`, then the slot will be set to zero and no
462// other data will be written.
463func (b *Builder) PrependInt16Slot(o int, x, d int16) {
464 if x != d {
465 b.PrependInt16(x)
466 b.Slot(o)
467 }
468}
469
470// PrependInt32Slot prepends a int32 onto the object at vtable slot `o`.
471// If value `x` equals default `d`, then the slot will be set to zero and no
472// other data will be written.
473func (b *Builder) PrependInt32Slot(o int, x, d int32) {
474 if x != d {
475 b.PrependInt32(x)
476 b.Slot(o)
477 }
478}
479
480// PrependInt64Slot prepends a int64 onto the object at vtable slot `o`.
481// If value `x` equals default `d`, then the slot will be set to zero and no
482// other data will be written.
483func (b *Builder) PrependInt64Slot(o int, x, d int64) {
484 if x != d {
485 b.PrependInt64(x)
486 b.Slot(o)
487 }
488}
489
490// PrependFloat32Slot prepends a float32 onto the object at vtable slot `o`.
491// If value `x` equals default `d`, then the slot will be set to zero and no
492// other data will be written.
493func (b *Builder) PrependFloat32Slot(o int, x, d float32) {
494 if x != d {
495 b.PrependFloat32(x)
496 b.Slot(o)
497 }
498}
499
500// PrependFloat64Slot prepends a float64 onto the object at vtable slot `o`.
501// If value `x` equals default `d`, then the slot will be set to zero and no
502// other data will be written.
503func (b *Builder) PrependFloat64Slot(o int, x, d float64) {
504 if x != d {
505 b.PrependFloat64(x)
506 b.Slot(o)
507 }
508}
509
510// PrependUOffsetTSlot prepends an UOffsetT onto the object at vtable slot `o`.
511// If value `x` equals default `d`, then the slot will be set to zero and no
512// other data will be written.
513func (b *Builder) PrependUOffsetTSlot(o int, x, d UOffsetT) {
514 if x != d {
515 b.PrependUOffsetT(x)
516 b.Slot(o)
517 }
518}
519
520// PrependStructSlot prepends a struct onto the object at vtable slot `o`.
521// Structs are stored inline, so nothing additional is being added.
522// In generated code, `d` is always 0.
523func (b *Builder) PrependStructSlot(voffset int, x, d UOffsetT) {
524 if x != d {
rw2dfff152015-11-11 17:08:16 -0800525 b.assertNested()
526 if x != b.Offset() {
527 panic("inline data write outside of object")
528 }
rw74d5f372014-07-11 16:12:35 -0700529 b.Slot(voffset)
530 }
531}
532
533// Slot sets the vtable key `voffset` to the current location in the buffer.
534func (b *Builder) Slot(slotnum int) {
535 b.vtable[slotnum] = UOffsetT(b.Offset())
536}
537
538// Finish finalizes a buffer, pointing to the given `rootTable`.
539func (b *Builder) Finish(rootTable UOffsetT) {
rw2dfff152015-11-11 17:08:16 -0800540 b.assertNotNested()
rw74d5f372014-07-11 16:12:35 -0700541 b.Prep(b.minalign, SizeUOffsetT)
542 b.PrependUOffsetT(rootTable)
rw2dfff152015-11-11 17:08:16 -0800543 b.finished = true
rw74d5f372014-07-11 16:12:35 -0700544}
545
546// vtableEqual compares an unwritten vtable to a written vtable.
547func vtableEqual(a []UOffsetT, objectStart UOffsetT, b []byte) bool {
548 if len(a)*SizeVOffsetT != len(b) {
549 return false
550 }
551
552 for i := 0; i < len(a); i++ {
553 x := GetVOffsetT(b[i*SizeVOffsetT : (i+1)*SizeVOffsetT])
554
555 // Skip vtable entries that indicate a default value.
556 if x == 0 && a[i] == 0 {
557 continue
558 }
559
560 y := SOffsetT(objectStart) - SOffsetT(a[i])
561 if SOffsetT(x) != y {
562 return false
563 }
564 }
565 return true
566}
567
568// PrependBool prepends a bool to the Builder buffer.
569// Aligns and checks for space.
570func (b *Builder) PrependBool(x bool) {
571 b.Prep(SizeBool, 0)
572 b.PlaceBool(x)
573}
574
575// PrependUint8 prepends a uint8 to the Builder buffer.
576// Aligns and checks for space.
577func (b *Builder) PrependUint8(x uint8) {
578 b.Prep(SizeUint8, 0)
579 b.PlaceUint8(x)
580}
581
582// PrependUint16 prepends a uint16 to the Builder buffer.
583// Aligns and checks for space.
584func (b *Builder) PrependUint16(x uint16) {
585 b.Prep(SizeUint16, 0)
586 b.PlaceUint16(x)
587}
588
589// PrependUint32 prepends a uint32 to the Builder buffer.
590// Aligns and checks for space.
591func (b *Builder) PrependUint32(x uint32) {
592 b.Prep(SizeUint32, 0)
593 b.PlaceUint32(x)
594}
595
596// PrependUint64 prepends a uint64 to the Builder buffer.
597// Aligns and checks for space.
598func (b *Builder) PrependUint64(x uint64) {
599 b.Prep(SizeUint64, 0)
600 b.PlaceUint64(x)
601}
602
603// PrependInt8 prepends a int8 to the Builder buffer.
604// Aligns and checks for space.
605func (b *Builder) PrependInt8(x int8) {
606 b.Prep(SizeInt8, 0)
607 b.PlaceInt8(x)
608}
609
610// PrependInt16 prepends a int16 to the Builder buffer.
611// Aligns and checks for space.
612func (b *Builder) PrependInt16(x int16) {
613 b.Prep(SizeInt16, 0)
614 b.PlaceInt16(x)
615}
616
617// PrependInt32 prepends a int32 to the Builder buffer.
618// Aligns and checks for space.
619func (b *Builder) PrependInt32(x int32) {
620 b.Prep(SizeInt32, 0)
621 b.PlaceInt32(x)
622}
623
624// PrependInt64 prepends a int64 to the Builder buffer.
625// Aligns and checks for space.
626func (b *Builder) PrependInt64(x int64) {
627 b.Prep(SizeInt64, 0)
628 b.PlaceInt64(x)
629}
630
631// PrependFloat32 prepends a float32 to the Builder buffer.
632// Aligns and checks for space.
633func (b *Builder) PrependFloat32(x float32) {
634 b.Prep(SizeFloat32, 0)
635 b.PlaceFloat32(x)
636}
637
638// PrependFloat64 prepends a float64 to the Builder buffer.
639// Aligns and checks for space.
640func (b *Builder) PrependFloat64(x float64) {
641 b.Prep(SizeFloat64, 0)
642 b.PlaceFloat64(x)
643}
644
645// PrependByte prepends a byte to the Builder buffer.
646// Aligns and checks for space.
647func (b *Builder) PrependByte(x byte) {
648 b.Prep(SizeByte, 0)
649 b.PlaceByte(x)
650}
651
652// PrependVOffsetT prepends a VOffsetT to the Builder buffer.
653// Aligns and checks for space.
654func (b *Builder) PrependVOffsetT(x VOffsetT) {
655 b.Prep(SizeVOffsetT, 0)
656 b.PlaceVOffsetT(x)
657}
658
659// PlaceBool prepends a bool to the Builder, without checking for space.
660func (b *Builder) PlaceBool(x bool) {
661 b.head -= UOffsetT(SizeBool)
662 WriteBool(b.Bytes[b.head:], x)
663}
664
665// PlaceUint8 prepends a uint8 to the Builder, without checking for space.
666func (b *Builder) PlaceUint8(x uint8) {
667 b.head -= UOffsetT(SizeUint8)
668 WriteUint8(b.Bytes[b.head:], x)
669}
670
671// PlaceUint16 prepends a uint16 to the Builder, without checking for space.
672func (b *Builder) PlaceUint16(x uint16) {
673 b.head -= UOffsetT(SizeUint16)
674 WriteUint16(b.Bytes[b.head:], x)
675}
676
677// PlaceUint32 prepends a uint32 to the Builder, without checking for space.
678func (b *Builder) PlaceUint32(x uint32) {
679 b.head -= UOffsetT(SizeUint32)
680 WriteUint32(b.Bytes[b.head:], x)
681}
682
683// PlaceUint64 prepends a uint64 to the Builder, without checking for space.
684func (b *Builder) PlaceUint64(x uint64) {
685 b.head -= UOffsetT(SizeUint64)
686 WriteUint64(b.Bytes[b.head:], x)
687}
688
689// PlaceInt8 prepends a int8 to the Builder, without checking for space.
690func (b *Builder) PlaceInt8(x int8) {
691 b.head -= UOffsetT(SizeInt8)
692 WriteInt8(b.Bytes[b.head:], x)
693}
694
695// PlaceInt16 prepends a int16 to the Builder, without checking for space.
696func (b *Builder) PlaceInt16(x int16) {
697 b.head -= UOffsetT(SizeInt16)
698 WriteInt16(b.Bytes[b.head:], x)
699}
700
701// PlaceInt32 prepends a int32 to the Builder, without checking for space.
702func (b *Builder) PlaceInt32(x int32) {
703 b.head -= UOffsetT(SizeInt32)
704 WriteInt32(b.Bytes[b.head:], x)
705}
706
707// PlaceInt64 prepends a int64 to the Builder, without checking for space.
708func (b *Builder) PlaceInt64(x int64) {
709 b.head -= UOffsetT(SizeInt64)
710 WriteInt64(b.Bytes[b.head:], x)
711}
712
713// PlaceFloat32 prepends a float32 to the Builder, without checking for space.
714func (b *Builder) PlaceFloat32(x float32) {
715 b.head -= UOffsetT(SizeFloat32)
716 WriteFloat32(b.Bytes[b.head:], x)
717}
718
719// PlaceFloat64 prepends a float64 to the Builder, without checking for space.
720func (b *Builder) PlaceFloat64(x float64) {
721 b.head -= UOffsetT(SizeFloat64)
722 WriteFloat64(b.Bytes[b.head:], x)
723}
724
725// PlaceByte prepends a byte to the Builder, without checking for space.
726func (b *Builder) PlaceByte(x byte) {
727 b.head -= UOffsetT(SizeByte)
728 WriteByte(b.Bytes[b.head:], x)
729}
730
731// PlaceVOffsetT prepends a VOffsetT to the Builder, without checking for space.
732func (b *Builder) PlaceVOffsetT(x VOffsetT) {
733 b.head -= UOffsetT(SizeVOffsetT)
734 WriteVOffsetT(b.Bytes[b.head:], x)
735}
736
737// PlaceSOffsetT prepends a SOffsetT to the Builder, without checking for space.
738func (b *Builder) PlaceSOffsetT(x SOffsetT) {
739 b.head -= UOffsetT(SizeSOffsetT)
740 WriteSOffsetT(b.Bytes[b.head:], x)
741}
742
743// PlaceUOffsetT prepends a UOffsetT to the Builder, without checking for space.
744func (b *Builder) PlaceUOffsetT(x UOffsetT) {
745 b.head -= UOffsetT(SizeUOffsetT)
746 WriteUOffsetT(b.Bytes[b.head:], x)
747}