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