blob: d99b590bb2a5c7b3c277c53ede8e0810cd07a3f1 [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -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 {
9 // `Bytes` gives raw access to the buffer. Most users will want to use
10 // FinishedBytes() instead.
11 Bytes []byte
12
13 minalign int
14 vtable []UOffsetT
15 objectEnd UOffsetT
16 vtables []UOffsetT
17 head UOffsetT
18 nested bool
19 finished bool
Austin Schuh272c6132020-11-14 16:37:52 -080020
21 sharedStrings map[string]UOffsetT
Austin Schuhe89fa2d2019-08-14 20:24:23 -070022}
23
24const fileIdentifierLength = 4
Austin Schuh272c6132020-11-14 16:37:52 -080025const sizePrefixLength = 4
Austin Schuhe89fa2d2019-08-14 20:24:23 -070026
27// NewBuilder initializes a Builder of size `initial_size`.
28// The internal buffer is grown as needed.
29func NewBuilder(initialSize int) *Builder {
30 if initialSize <= 0 {
31 initialSize = 0
32 }
33
34 b := &Builder{}
35 b.Bytes = make([]byte, initialSize)
36 b.head = UOffsetT(initialSize)
37 b.minalign = 1
38 b.vtables = make([]UOffsetT, 0, 16) // sensible default capacity
Austin Schuhe89fa2d2019-08-14 20:24:23 -070039 return b
40}
41
42// Reset truncates the underlying Builder buffer, facilitating alloc-free
43// reuse of a Builder. It also resets bookkeeping data.
44func (b *Builder) Reset() {
45 if b.Bytes != nil {
46 b.Bytes = b.Bytes[:cap(b.Bytes)]
47 }
48
49 if b.vtables != nil {
50 b.vtables = b.vtables[:0]
51 }
52
53 if b.vtable != nil {
54 b.vtable = b.vtable[:0]
55 }
56
Austin Schuh272c6132020-11-14 16:37:52 -080057 if b.sharedStrings != nil {
58 for key := range b.sharedStrings {
59 delete(b.sharedStrings, key)
60 }
61 }
62
Austin Schuhe89fa2d2019-08-14 20:24:23 -070063 b.head = UOffsetT(len(b.Bytes))
64 b.minalign = 1
65 b.nested = false
66 b.finished = false
67}
68
69// FinishedBytes returns a pointer to the written data in the byte buffer.
70// Panics if the builder is not in a finished state (which is caused by calling
71// `Finish()`).
72func (b *Builder) FinishedBytes() []byte {
73 b.assertFinished()
74 return b.Bytes[b.Head():]
75}
76
77// StartObject initializes bookkeeping for writing a new object.
78func (b *Builder) StartObject(numfields int) {
79 b.assertNotNested()
80 b.nested = true
81
82 // use 32-bit offsets so that arithmetic doesn't overflow.
83 if cap(b.vtable) < numfields || b.vtable == nil {
84 b.vtable = make([]UOffsetT, numfields)
85 } else {
86 b.vtable = b.vtable[:numfields]
87 for i := 0; i < len(b.vtable); i++ {
88 b.vtable[i] = 0
89 }
90 }
91
92 b.objectEnd = b.Offset()
93}
94
95// WriteVtable serializes the vtable for the current object, if applicable.
96//
97// Before writing out the vtable, this checks pre-existing vtables for equality
98// to this one. If an equal vtable is found, point the object to the existing
99// vtable and return.
100//
101// Because vtable values are sensitive to alignment of object data, not all
102// logically-equal vtables will be deduplicated.
103//
104// A vtable has the following format:
105// <VOffsetT: size of the vtable in bytes, including this value>
106// <VOffsetT: size of the object in bytes, including the vtable offset>
107// <VOffsetT: offset for a field> * N, where N is the number of fields in
108// the schema for this type. Includes deprecated fields.
109// Thus, a vtable is made of 2 + N elements, each SizeVOffsetT bytes wide.
110//
111// An object has the following format:
112// <SOffsetT: offset to this object's vtable (may be negative)>
113// <byte: data>+
114func (b *Builder) WriteVtable() (n UOffsetT) {
115 // Prepend a zero scalar to the object. Later in this function we'll
116 // write an offset here that points to the object's vtable:
117 b.PrependSOffsetT(0)
118
119 objectOffset := b.Offset()
120 existingVtable := UOffsetT(0)
121
122 // Trim vtable of trailing zeroes.
123 i := len(b.vtable) - 1
124 for ; i >= 0 && b.vtable[i] == 0; i-- {
125 }
126 b.vtable = b.vtable[:i+1]
127
128 // Search backwards through existing vtables, because similar vtables
129 // are likely to have been recently appended. See
130 // BenchmarkVtableDeduplication for a case in which this heuristic
131 // saves about 30% of the time used in writing objects with duplicate
132 // tables.
133 for i := len(b.vtables) - 1; i >= 0; i-- {
134 // Find the other vtable, which is associated with `i`:
135 vt2Offset := b.vtables[i]
136 vt2Start := len(b.Bytes) - int(vt2Offset)
137 vt2Len := GetVOffsetT(b.Bytes[vt2Start:])
138
139 metadata := VtableMetadataFields * SizeVOffsetT
140 vt2End := vt2Start + int(vt2Len)
141 vt2 := b.Bytes[vt2Start+metadata : vt2End]
142
143 // Compare the other vtable to the one under consideration.
144 // If they are equal, store the offset and break:
145 if vtableEqual(b.vtable, objectOffset, vt2) {
146 existingVtable = vt2Offset
147 break
148 }
149 }
150
151 if existingVtable == 0 {
152 // Did not find a vtable, so write this one to the buffer.
153
154 // Write out the current vtable in reverse , because
155 // serialization occurs in last-first order:
156 for i := len(b.vtable) - 1; i >= 0; i-- {
157 var off UOffsetT
158 if b.vtable[i] != 0 {
159 // Forward reference to field;
160 // use 32bit number to assert no overflow:
161 off = objectOffset - b.vtable[i]
162 }
163
164 b.PrependVOffsetT(VOffsetT(off))
165 }
166
167 // The two metadata fields are written last.
168
169 // First, store the object bytesize:
170 objectSize := objectOffset - b.objectEnd
171 b.PrependVOffsetT(VOffsetT(objectSize))
172
173 // Second, store the vtable bytesize:
174 vBytes := (len(b.vtable) + VtableMetadataFields) * SizeVOffsetT
175 b.PrependVOffsetT(VOffsetT(vBytes))
176
177 // Next, write the offset to the new vtable in the
178 // already-allocated SOffsetT at the beginning of this object:
179 objectStart := SOffsetT(len(b.Bytes)) - SOffsetT(objectOffset)
180 WriteSOffsetT(b.Bytes[objectStart:],
181 SOffsetT(b.Offset())-SOffsetT(objectOffset))
182
183 // Finally, store this vtable in memory for future
184 // deduplication:
185 b.vtables = append(b.vtables, b.Offset())
186 } else {
187 // Found a duplicate vtable.
188
189 objectStart := SOffsetT(len(b.Bytes)) - SOffsetT(objectOffset)
190 b.head = UOffsetT(objectStart)
191
192 // Write the offset to the found vtable in the
193 // already-allocated SOffsetT at the beginning of this object:
194 WriteSOffsetT(b.Bytes[b.head:],
195 SOffsetT(existingVtable)-SOffsetT(objectOffset))
196 }
197
198 b.vtable = b.vtable[:0]
199 return objectOffset
200}
201
202// EndObject writes data necessary to finish object construction.
203func (b *Builder) EndObject() UOffsetT {
204 b.assertNested()
205 n := b.WriteVtable()
206 b.nested = false
207 return n
208}
209
210// Doubles the size of the byteslice, and copies the old data towards the
211// end of the new byteslice (since we build the buffer backwards).
212func (b *Builder) growByteBuffer() {
213 if (int64(len(b.Bytes)) & int64(0xC0000000)) != 0 {
214 panic("cannot grow buffer beyond 2 gigabytes")
215 }
216 newLen := len(b.Bytes) * 2
217 if newLen == 0 {
218 newLen = 1
219 }
220
221 if cap(b.Bytes) >= newLen {
222 b.Bytes = b.Bytes[:newLen]
223 } else {
224 extension := make([]byte, newLen-len(b.Bytes))
225 b.Bytes = append(b.Bytes, extension...)
226 }
227
228 middle := newLen / 2
229 copy(b.Bytes[middle:], b.Bytes[:middle])
230}
231
232// Head gives the start of useful data in the underlying byte buffer.
233// Note: unlike other functions, this value is interpreted as from the left.
234func (b *Builder) Head() UOffsetT {
235 return b.head
236}
237
238// Offset relative to the end of the buffer.
239func (b *Builder) Offset() UOffsetT {
240 return UOffsetT(len(b.Bytes)) - b.head
241}
242
243// Pad places zeros at the current offset.
244func (b *Builder) Pad(n int) {
245 for i := 0; i < n; i++ {
246 b.PlaceByte(0)
247 }
248}
249
250// Prep prepares to write an element of `size` after `additional_bytes`
251// have been written, e.g. if you write a string, you need to align such
252// the int length field is aligned to SizeInt32, and the string data follows it
253// directly.
254// If all you need to do is align, `additionalBytes` will be 0.
255func (b *Builder) Prep(size, additionalBytes int) {
256 // Track the biggest thing we've ever aligned to.
257 if size > b.minalign {
258 b.minalign = size
259 }
260 // Find the amount of alignment needed such that `size` is properly
261 // aligned after `additionalBytes`:
262 alignSize := (^(len(b.Bytes) - int(b.Head()) + additionalBytes)) + 1
263 alignSize &= (size - 1)
264
265 // Reallocate the buffer if needed:
266 for int(b.head) <= alignSize+size+additionalBytes {
267 oldBufSize := len(b.Bytes)
268 b.growByteBuffer()
269 b.head += UOffsetT(len(b.Bytes) - oldBufSize)
270 }
271 b.Pad(alignSize)
272}
273
274// PrependSOffsetT prepends an SOffsetT, relative to where it will be written.
275func (b *Builder) PrependSOffsetT(off SOffsetT) {
276 b.Prep(SizeSOffsetT, 0) // Ensure alignment is already done.
277 if !(UOffsetT(off) <= b.Offset()) {
278 panic("unreachable: off <= b.Offset()")
279 }
280 off2 := SOffsetT(b.Offset()) - off + SOffsetT(SizeSOffsetT)
281 b.PlaceSOffsetT(off2)
282}
283
284// PrependUOffsetT prepends an UOffsetT, relative to where it will be written.
285func (b *Builder) PrependUOffsetT(off UOffsetT) {
286 b.Prep(SizeUOffsetT, 0) // Ensure alignment is already done.
287 if !(off <= b.Offset()) {
288 panic("unreachable: off <= b.Offset()")
289 }
290 off2 := b.Offset() - off + UOffsetT(SizeUOffsetT)
291 b.PlaceUOffsetT(off2)
292}
293
294// StartVector initializes bookkeeping for writing a new vector.
295//
296// A vector has the following format:
297// <UOffsetT: number of elements in this vector>
298// <T: data>+, where T is the type of elements of this vector.
299func (b *Builder) StartVector(elemSize, numElems, alignment int) UOffsetT {
300 b.assertNotNested()
301 b.nested = true
302 b.Prep(SizeUint32, elemSize*numElems)
303 b.Prep(alignment, elemSize*numElems) // Just in case alignment > int.
304 return b.Offset()
305}
306
307// EndVector writes data necessary to finish vector construction.
308func (b *Builder) EndVector(vectorNumElems int) UOffsetT {
309 b.assertNested()
310
311 // we already made space for this, so write without PrependUint32
312 b.PlaceUOffsetT(UOffsetT(vectorNumElems))
313
314 b.nested = false
315 return b.Offset()
316}
317
Austin Schuh272c6132020-11-14 16:37:52 -0800318// CreateSharedString Checks if the string is already written
319// to the buffer before calling CreateString
320func (b *Builder) CreateSharedString(s string) UOffsetT {
321 if b.sharedStrings == nil {
322 b.sharedStrings = make(map[string]UOffsetT)
323 }
324 if v, ok := b.sharedStrings[s]; ok {
325 return v
326 }
327 off := b.CreateString(s)
328 b.sharedStrings[s] = off
329 return off
330}
331
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700332// CreateString writes a null-terminated string as a vector.
333func (b *Builder) CreateString(s string) UOffsetT {
334 b.assertNotNested()
335 b.nested = true
336
337 b.Prep(int(SizeUOffsetT), (len(s)+1)*SizeByte)
338 b.PlaceByte(0)
339
340 l := UOffsetT(len(s))
341
342 b.head -= l
343 copy(b.Bytes[b.head:b.head+l], s)
344
345 return b.EndVector(len(s))
346}
347
348// CreateByteString writes a byte slice as a string (null-terminated).
349func (b *Builder) CreateByteString(s []byte) UOffsetT {
350 b.assertNotNested()
351 b.nested = true
352
353 b.Prep(int(SizeUOffsetT), (len(s)+1)*SizeByte)
354 b.PlaceByte(0)
355
356 l := UOffsetT(len(s))
357
358 b.head -= l
359 copy(b.Bytes[b.head:b.head+l], s)
360
361 return b.EndVector(len(s))
362}
363
364// CreateByteVector writes a ubyte vector
365func (b *Builder) CreateByteVector(v []byte) UOffsetT {
366 b.assertNotNested()
367 b.nested = true
368
369 b.Prep(int(SizeUOffsetT), len(v)*SizeByte)
370
371 l := UOffsetT(len(v))
372
373 b.head -= l
374 copy(b.Bytes[b.head:b.head+l], v)
375
376 return b.EndVector(len(v))
377}
378
379func (b *Builder) assertNested() {
380 // If you get this assert, you're in an object while trying to write
381 // data that belongs outside of an object.
382 // To fix this, write non-inline data (like vectors) before creating
383 // objects.
384 if !b.nested {
385 panic("Incorrect creation order: must be inside object.")
386 }
387}
388
389func (b *Builder) assertNotNested() {
390 // If you hit this, you're trying to construct a Table/Vector/String
391 // during the construction of its parent table (between the MyTableBuilder
392 // and builder.Finish()).
393 // Move the creation of these sub-objects to above the MyTableBuilder to
394 // not get this assert.
395 // Ignoring this assert may appear to work in simple cases, but the reason
396 // it is here is that storing objects in-line may cause vtable offsets
397 // to not fit anymore. It also leads to vtable duplication.
398 if b.nested {
399 panic("Incorrect creation order: object must not be nested.")
400 }
401}
402
403func (b *Builder) assertFinished() {
404 // If you get this assert, you're attempting to get access a buffer
405 // which hasn't been finished yet. Be sure to call builder.Finish()
406 // with your root table.
407 // If you really need to access an unfinished buffer, use the Bytes
408 // buffer directly.
409 if !b.finished {
410 panic("Incorrect use of FinishedBytes(): must call 'Finish' first.")
411 }
412}
413
414// PrependBoolSlot prepends a bool onto the object at vtable slot `o`.
415// If value `x` equals default `d`, then the slot will be set to zero and no
416// other data will be written.
417func (b *Builder) PrependBoolSlot(o int, x, d bool) {
418 val := byte(0)
419 if x {
420 val = 1
421 }
422 def := byte(0)
423 if d {
424 def = 1
425 }
426 b.PrependByteSlot(o, val, def)
427}
428
429// PrependByteSlot prepends a byte onto the object at vtable slot `o`.
430// If value `x` equals default `d`, then the slot will be set to zero and no
431// other data will be written.
432func (b *Builder) PrependByteSlot(o int, x, d byte) {
433 if x != d {
434 b.PrependByte(x)
435 b.Slot(o)
436 }
437}
438
439// PrependUint8Slot prepends a uint8 onto the object at vtable slot `o`.
440// If value `x` equals default `d`, then the slot will be set to zero and no
441// other data will be written.
442func (b *Builder) PrependUint8Slot(o int, x, d uint8) {
443 if x != d {
444 b.PrependUint8(x)
445 b.Slot(o)
446 }
447}
448
449// PrependUint16Slot prepends a uint16 onto the object at vtable slot `o`.
450// If value `x` equals default `d`, then the slot will be set to zero and no
451// other data will be written.
452func (b *Builder) PrependUint16Slot(o int, x, d uint16) {
453 if x != d {
454 b.PrependUint16(x)
455 b.Slot(o)
456 }
457}
458
459// PrependUint32Slot prepends a uint32 onto the object at vtable slot `o`.
460// If value `x` equals default `d`, then the slot will be set to zero and no
461// other data will be written.
462func (b *Builder) PrependUint32Slot(o int, x, d uint32) {
463 if x != d {
464 b.PrependUint32(x)
465 b.Slot(o)
466 }
467}
468
469// PrependUint64Slot prepends a uint64 onto the object at vtable slot `o`.
470// If value `x` equals default `d`, then the slot will be set to zero and no
471// other data will be written.
472func (b *Builder) PrependUint64Slot(o int, x, d uint64) {
473 if x != d {
474 b.PrependUint64(x)
475 b.Slot(o)
476 }
477}
478
479// PrependInt8Slot prepends a int8 onto the object at vtable slot `o`.
480// If value `x` equals default `d`, then the slot will be set to zero and no
481// other data will be written.
482func (b *Builder) PrependInt8Slot(o int, x, d int8) {
483 if x != d {
484 b.PrependInt8(x)
485 b.Slot(o)
486 }
487}
488
489// PrependInt16Slot prepends a int16 onto the object at vtable slot `o`.
490// If value `x` equals default `d`, then the slot will be set to zero and no
491// other data will be written.
492func (b *Builder) PrependInt16Slot(o int, x, d int16) {
493 if x != d {
494 b.PrependInt16(x)
495 b.Slot(o)
496 }
497}
498
499// PrependInt32Slot prepends a int32 onto the object at vtable slot `o`.
500// If value `x` equals default `d`, then the slot will be set to zero and no
501// other data will be written.
502func (b *Builder) PrependInt32Slot(o int, x, d int32) {
503 if x != d {
504 b.PrependInt32(x)
505 b.Slot(o)
506 }
507}
508
509// PrependInt64Slot prepends a int64 onto the object at vtable slot `o`.
510// If value `x` equals default `d`, then the slot will be set to zero and no
511// other data will be written.
512func (b *Builder) PrependInt64Slot(o int, x, d int64) {
513 if x != d {
514 b.PrependInt64(x)
515 b.Slot(o)
516 }
517}
518
519// PrependFloat32Slot prepends a float32 onto the object at vtable slot `o`.
520// If value `x` equals default `d`, then the slot will be set to zero and no
521// other data will be written.
522func (b *Builder) PrependFloat32Slot(o int, x, d float32) {
523 if x != d {
524 b.PrependFloat32(x)
525 b.Slot(o)
526 }
527}
528
529// PrependFloat64Slot prepends a float64 onto the object at vtable slot `o`.
530// If value `x` equals default `d`, then the slot will be set to zero and no
531// other data will be written.
532func (b *Builder) PrependFloat64Slot(o int, x, d float64) {
533 if x != d {
534 b.PrependFloat64(x)
535 b.Slot(o)
536 }
537}
538
539// PrependUOffsetTSlot prepends an UOffsetT onto the object at vtable slot `o`.
540// If value `x` equals default `d`, then the slot will be set to zero and no
541// other data will be written.
542func (b *Builder) PrependUOffsetTSlot(o int, x, d UOffsetT) {
543 if x != d {
544 b.PrependUOffsetT(x)
545 b.Slot(o)
546 }
547}
548
549// PrependStructSlot prepends a struct onto the object at vtable slot `o`.
550// Structs are stored inline, so nothing additional is being added.
551// In generated code, `d` is always 0.
552func (b *Builder) PrependStructSlot(voffset int, x, d UOffsetT) {
553 if x != d {
554 b.assertNested()
555 if x != b.Offset() {
556 panic("inline data write outside of object")
557 }
558 b.Slot(voffset)
559 }
560}
561
562// Slot sets the vtable key `voffset` to the current location in the buffer.
563func (b *Builder) Slot(slotnum int) {
564 b.vtable[slotnum] = UOffsetT(b.Offset())
565}
566
567// FinishWithFileIdentifier finalizes a buffer, pointing to the given `rootTable`.
568// as well as applys a file identifier
569func (b *Builder) FinishWithFileIdentifier(rootTable UOffsetT, fid []byte) {
570 if fid == nil || len(fid) != fileIdentifierLength {
571 panic("incorrect file identifier length")
572 }
573 // In order to add a file identifier to the flatbuffer message, we need
574 // to prepare an alignment and file identifier length
575 b.Prep(b.minalign, SizeInt32+fileIdentifierLength)
576 for i := fileIdentifierLength - 1; i >= 0; i-- {
577 // place the file identifier
578 b.PlaceByte(fid[i])
579 }
580 // finish
581 b.Finish(rootTable)
582}
583
Austin Schuh272c6132020-11-14 16:37:52 -0800584// FinishSizePrefixed finalizes a buffer, pointing to the given `rootTable`.
585// The buffer is prefixed with the size of the buffer, excluding the size
586// of the prefix itself.
587func (b *Builder) FinishSizePrefixed(rootTable UOffsetT) {
588 b.finish(rootTable, true)
589}
590
591// FinishSizePrefixedWithFileIdentifier finalizes a buffer, pointing to the given `rootTable`
592// and applies a file identifier. The buffer is prefixed with the size of the buffer,
593// excluding the size of the prefix itself.
594func (b *Builder) FinishSizePrefixedWithFileIdentifier(rootTable UOffsetT, fid []byte) {
595 if fid == nil || len(fid) != fileIdentifierLength {
596 panic("incorrect file identifier length")
597 }
598 // In order to add a file identifier and size prefix to the flatbuffer message,
599 // we need to prepare an alignment, a size prefix length, and file identifier length
600 b.Prep(b.minalign, SizeInt32+fileIdentifierLength+sizePrefixLength)
601 for i := fileIdentifierLength - 1; i >= 0; i-- {
602 // place the file identifier
603 b.PlaceByte(fid[i])
604 }
605 // finish
606 b.finish(rootTable, true)
607}
608
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700609// Finish finalizes a buffer, pointing to the given `rootTable`.
610func (b *Builder) Finish(rootTable UOffsetT) {
Austin Schuh272c6132020-11-14 16:37:52 -0800611 b.finish(rootTable, false)
612}
613
614// finish finalizes a buffer, pointing to the given `rootTable`
615// with an optional size prefix.
616func (b *Builder) finish(rootTable UOffsetT, sizePrefix bool) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700617 b.assertNotNested()
Austin Schuh272c6132020-11-14 16:37:52 -0800618
619 if sizePrefix {
620 b.Prep(b.minalign, SizeUOffsetT+sizePrefixLength)
621 } else {
622 b.Prep(b.minalign, SizeUOffsetT)
623 }
624
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700625 b.PrependUOffsetT(rootTable)
Austin Schuh272c6132020-11-14 16:37:52 -0800626
627 if sizePrefix {
628 b.PlaceUint32(uint32(b.Offset()))
629 }
630
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700631 b.finished = true
632}
633
634// vtableEqual compares an unwritten vtable to a written vtable.
635func vtableEqual(a []UOffsetT, objectStart UOffsetT, b []byte) bool {
636 if len(a)*SizeVOffsetT != len(b) {
637 return false
638 }
639
640 for i := 0; i < len(a); i++ {
641 x := GetVOffsetT(b[i*SizeVOffsetT : (i+1)*SizeVOffsetT])
642
643 // Skip vtable entries that indicate a default value.
644 if x == 0 && a[i] == 0 {
645 continue
646 }
647
648 y := SOffsetT(objectStart) - SOffsetT(a[i])
649 if SOffsetT(x) != y {
650 return false
651 }
652 }
653 return true
654}
655
656// PrependBool prepends a bool to the Builder buffer.
657// Aligns and checks for space.
658func (b *Builder) PrependBool(x bool) {
659 b.Prep(SizeBool, 0)
660 b.PlaceBool(x)
661}
662
663// PrependUint8 prepends a uint8 to the Builder buffer.
664// Aligns and checks for space.
665func (b *Builder) PrependUint8(x uint8) {
666 b.Prep(SizeUint8, 0)
667 b.PlaceUint8(x)
668}
669
670// PrependUint16 prepends a uint16 to the Builder buffer.
671// Aligns and checks for space.
672func (b *Builder) PrependUint16(x uint16) {
673 b.Prep(SizeUint16, 0)
674 b.PlaceUint16(x)
675}
676
677// PrependUint32 prepends a uint32 to the Builder buffer.
678// Aligns and checks for space.
679func (b *Builder) PrependUint32(x uint32) {
680 b.Prep(SizeUint32, 0)
681 b.PlaceUint32(x)
682}
683
684// PrependUint64 prepends a uint64 to the Builder buffer.
685// Aligns and checks for space.
686func (b *Builder) PrependUint64(x uint64) {
687 b.Prep(SizeUint64, 0)
688 b.PlaceUint64(x)
689}
690
691// PrependInt8 prepends a int8 to the Builder buffer.
692// Aligns and checks for space.
693func (b *Builder) PrependInt8(x int8) {
694 b.Prep(SizeInt8, 0)
695 b.PlaceInt8(x)
696}
697
698// PrependInt16 prepends a int16 to the Builder buffer.
699// Aligns and checks for space.
700func (b *Builder) PrependInt16(x int16) {
701 b.Prep(SizeInt16, 0)
702 b.PlaceInt16(x)
703}
704
705// PrependInt32 prepends a int32 to the Builder buffer.
706// Aligns and checks for space.
707func (b *Builder) PrependInt32(x int32) {
708 b.Prep(SizeInt32, 0)
709 b.PlaceInt32(x)
710}
711
712// PrependInt64 prepends a int64 to the Builder buffer.
713// Aligns and checks for space.
714func (b *Builder) PrependInt64(x int64) {
715 b.Prep(SizeInt64, 0)
716 b.PlaceInt64(x)
717}
718
719// PrependFloat32 prepends a float32 to the Builder buffer.
720// Aligns and checks for space.
721func (b *Builder) PrependFloat32(x float32) {
722 b.Prep(SizeFloat32, 0)
723 b.PlaceFloat32(x)
724}
725
726// PrependFloat64 prepends a float64 to the Builder buffer.
727// Aligns and checks for space.
728func (b *Builder) PrependFloat64(x float64) {
729 b.Prep(SizeFloat64, 0)
730 b.PlaceFloat64(x)
731}
732
733// PrependByte prepends a byte to the Builder buffer.
734// Aligns and checks for space.
735func (b *Builder) PrependByte(x byte) {
736 b.Prep(SizeByte, 0)
737 b.PlaceByte(x)
738}
739
740// PrependVOffsetT prepends a VOffsetT to the Builder buffer.
741// Aligns and checks for space.
742func (b *Builder) PrependVOffsetT(x VOffsetT) {
743 b.Prep(SizeVOffsetT, 0)
744 b.PlaceVOffsetT(x)
745}
746
747// PlaceBool prepends a bool to the Builder, without checking for space.
748func (b *Builder) PlaceBool(x bool) {
749 b.head -= UOffsetT(SizeBool)
750 WriteBool(b.Bytes[b.head:], x)
751}
752
753// PlaceUint8 prepends a uint8 to the Builder, without checking for space.
754func (b *Builder) PlaceUint8(x uint8) {
755 b.head -= UOffsetT(SizeUint8)
756 WriteUint8(b.Bytes[b.head:], x)
757}
758
759// PlaceUint16 prepends a uint16 to the Builder, without checking for space.
760func (b *Builder) PlaceUint16(x uint16) {
761 b.head -= UOffsetT(SizeUint16)
762 WriteUint16(b.Bytes[b.head:], x)
763}
764
765// PlaceUint32 prepends a uint32 to the Builder, without checking for space.
766func (b *Builder) PlaceUint32(x uint32) {
767 b.head -= UOffsetT(SizeUint32)
768 WriteUint32(b.Bytes[b.head:], x)
769}
770
771// PlaceUint64 prepends a uint64 to the Builder, without checking for space.
772func (b *Builder) PlaceUint64(x uint64) {
773 b.head -= UOffsetT(SizeUint64)
774 WriteUint64(b.Bytes[b.head:], x)
775}
776
777// PlaceInt8 prepends a int8 to the Builder, without checking for space.
778func (b *Builder) PlaceInt8(x int8) {
779 b.head -= UOffsetT(SizeInt8)
780 WriteInt8(b.Bytes[b.head:], x)
781}
782
783// PlaceInt16 prepends a int16 to the Builder, without checking for space.
784func (b *Builder) PlaceInt16(x int16) {
785 b.head -= UOffsetT(SizeInt16)
786 WriteInt16(b.Bytes[b.head:], x)
787}
788
789// PlaceInt32 prepends a int32 to the Builder, without checking for space.
790func (b *Builder) PlaceInt32(x int32) {
791 b.head -= UOffsetT(SizeInt32)
792 WriteInt32(b.Bytes[b.head:], x)
793}
794
795// PlaceInt64 prepends a int64 to the Builder, without checking for space.
796func (b *Builder) PlaceInt64(x int64) {
797 b.head -= UOffsetT(SizeInt64)
798 WriteInt64(b.Bytes[b.head:], x)
799}
800
801// PlaceFloat32 prepends a float32 to the Builder, without checking for space.
802func (b *Builder) PlaceFloat32(x float32) {
803 b.head -= UOffsetT(SizeFloat32)
804 WriteFloat32(b.Bytes[b.head:], x)
805}
806
807// PlaceFloat64 prepends a float64 to the Builder, without checking for space.
808func (b *Builder) PlaceFloat64(x float64) {
809 b.head -= UOffsetT(SizeFloat64)
810 WriteFloat64(b.Bytes[b.head:], x)
811}
812
813// PlaceByte prepends a byte to the Builder, without checking for space.
814func (b *Builder) PlaceByte(x byte) {
815 b.head -= UOffsetT(SizeByte)
816 WriteByte(b.Bytes[b.head:], x)
817}
818
819// PlaceVOffsetT prepends a VOffsetT to the Builder, without checking for space.
820func (b *Builder) PlaceVOffsetT(x VOffsetT) {
821 b.head -= UOffsetT(SizeVOffsetT)
822 WriteVOffsetT(b.Bytes[b.head:], x)
823}
824
825// PlaceSOffsetT prepends a SOffsetT to the Builder, without checking for space.
826func (b *Builder) PlaceSOffsetT(x SOffsetT) {
827 b.head -= UOffsetT(SizeSOffsetT)
828 WriteSOffsetT(b.Bytes[b.head:], x)
829}
830
831// PlaceUOffsetT prepends a UOffsetT to the Builder, without checking for space.
832func (b *Builder) PlaceUOffsetT(x UOffsetT) {
833 b.head -= UOffsetT(SizeUOffsetT)
834 WriteUOffsetT(b.Bytes[b.head:], x)
835}