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