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