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