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