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