1 package flatbuffers
2
3 import "sort"
4
5
6
7
8
9
10 type Builder struct {
11
12
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
30
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)
41 return b
42 }
43
44
45
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
72
73
74 func (b *Builder) FinishedBytes() []byte {
75 b.assertFinished()
76 return b.Bytes[b.Head():]
77 }
78
79
80 func (b *Builder) StartObject(numfields int) {
81 b.assertNotNested()
82 b.nested = true
83
84
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 func (b *Builder) WriteVtable() (n UOffsetT) {
117
118
119 b.PrependSOffsetT(0)
120
121 objectOffset := b.Offset()
122 existingVtable := UOffsetT(0)
123
124
125 i := len(b.vtable) - 1
126 for ; i >= 0 && b.vtable[i] == 0; i-- {
127 }
128 b.vtable = b.vtable[:i+1]
129
130
131
132
133
134
135 for i := len(b.vtables) - 1; i >= 0; i-- {
136
137 vt2Offset := b.vtables[i]
138 vt2Start := len(b.Bytes) - int(vt2Offset)
139 vt2Len := GetVOffsetT(b.Bytes[vt2Start:])
140
141 metadata := VtableMetadataFields * SizeVOffsetT
142 vt2End := vt2Start + int(vt2Len)
143 vt2 := b.Bytes[vt2Start+metadata : vt2End]
144
145
146
147 if vtableEqual(b.vtable, objectOffset, vt2) {
148 existingVtable = vt2Offset
149 break
150 }
151 }
152
153 if existingVtable == 0 {
154
155
156
157
158 for i := len(b.vtable) - 1; i >= 0; i-- {
159 var off UOffsetT
160 if b.vtable[i] != 0 {
161
162
163 off = objectOffset - b.vtable[i]
164 }
165
166 b.PrependVOffsetT(VOffsetT(off))
167 }
168
169
170
171
172 objectSize := objectOffset - b.objectEnd
173 b.PrependVOffsetT(VOffsetT(objectSize))
174
175
176 vBytes := (len(b.vtable) + VtableMetadataFields) * SizeVOffsetT
177 b.PrependVOffsetT(VOffsetT(vBytes))
178
179
180
181 objectStart := SOffsetT(len(b.Bytes)) - SOffsetT(objectOffset)
182 WriteSOffsetT(b.Bytes[objectStart:],
183 SOffsetT(b.Offset())-SOffsetT(objectOffset))
184
185
186
187 b.vtables = append(b.vtables, b.Offset())
188 } else {
189
190
191 objectStart := SOffsetT(len(b.Bytes)) - SOffsetT(objectOffset)
192 b.head = UOffsetT(objectStart)
193
194
195
196 WriteSOffsetT(b.Bytes[b.head:],
197 SOffsetT(existingVtable)-SOffsetT(objectOffset))
198 }
199
200 b.vtable = b.vtable[:0]
201 return objectOffset
202 }
203
204
205 func (b *Builder) EndObject() UOffsetT {
206 b.assertNested()
207 n := b.WriteVtable()
208 b.nested = false
209 return n
210 }
211
212
213
214 func (b *Builder) growByteBuffer() {
215 if (int64(len(b.Bytes)) & int64(0xC0000000)) != 0 {
216 panic("cannot grow buffer beyond 2 gigabytes")
217 }
218 newLen := len(b.Bytes) * 2
219 if newLen == 0 {
220 newLen = 1
221 }
222
223 if cap(b.Bytes) >= newLen {
224 b.Bytes = b.Bytes[:newLen]
225 } else {
226 extension := make([]byte, newLen-len(b.Bytes))
227 b.Bytes = append(b.Bytes, extension...)
228 }
229
230 middle := newLen / 2
231 copy(b.Bytes[middle:], b.Bytes[:middle])
232 }
233
234
235
236 func (b *Builder) Head() UOffsetT {
237 return b.head
238 }
239
240
241 func (b *Builder) Offset() UOffsetT {
242 return UOffsetT(len(b.Bytes)) - b.head
243 }
244
245
246 func (b *Builder) Pad(n int) {
247 for i := 0; i < n; i++ {
248 b.PlaceByte(0)
249 }
250 }
251
252
253
254
255
256
257 func (b *Builder) Prep(size, additionalBytes int) {
258
259 if size > b.minalign {
260 b.minalign = size
261 }
262
263
264 alignSize := (^(len(b.Bytes) - int(b.Head()) + additionalBytes)) + 1
265 alignSize &= (size - 1)
266
267
268 for int(b.head) <= alignSize+size+additionalBytes {
269 oldBufSize := len(b.Bytes)
270 b.growByteBuffer()
271 b.head += UOffsetT(len(b.Bytes) - oldBufSize)
272 }
273 b.Pad(alignSize)
274 }
275
276
277 func (b *Builder) PrependSOffsetT(off SOffsetT) {
278 b.Prep(SizeSOffsetT, 0)
279 if !(UOffsetT(off) <= b.Offset()) {
280 panic("unreachable: off <= b.Offset()")
281 }
282 off2 := SOffsetT(b.Offset()) - off + SOffsetT(SizeSOffsetT)
283 b.PlaceSOffsetT(off2)
284 }
285
286
287 func (b *Builder) PrependUOffsetT(off UOffsetT) {
288 b.Prep(SizeUOffsetT, 0)
289 if !(off <= b.Offset()) {
290 panic("unreachable: off <= b.Offset()")
291 }
292 off2 := b.Offset() - off + UOffsetT(SizeUOffsetT)
293 b.PlaceUOffsetT(off2)
294 }
295
296
297
298
299
300
301 func (b *Builder) StartVector(elemSize, numElems, alignment int) UOffsetT {
302 b.assertNotNested()
303 b.nested = true
304 b.Prep(SizeUint32, elemSize*numElems)
305 b.Prep(alignment, elemSize*numElems)
306 return b.Offset()
307 }
308
309
310 func (b *Builder) EndVector(vectorNumElems int) UOffsetT {
311 b.assertNested()
312
313
314 b.PlaceUOffsetT(UOffsetT(vectorNumElems))
315
316 b.nested = false
317 return b.Offset()
318 }
319
320
321 func (b *Builder) CreateVectorOfTables(offsets []UOffsetT) UOffsetT {
322 b.assertNotNested()
323 b.StartVector(4, len(offsets), 4)
324 for i := len(offsets) - 1; i >= 0; i-- {
325 b.PrependUOffsetT(offsets[i])
326 }
327 return b.EndVector(len(offsets))
328 }
329
330 type KeyCompare func(o1, o2 UOffsetT, buf []byte) bool
331
332 func (b *Builder) CreateVectorOfSortedTables(offsets []UOffsetT, keyCompare KeyCompare) UOffsetT {
333 sort.Slice(offsets, func(i, j int) bool {
334 return keyCompare(offsets[i], offsets[j], b.Bytes)
335 })
336 return b.CreateVectorOfTables(offsets)
337 }
338
339
340
341 func (b *Builder) CreateSharedString(s string) UOffsetT {
342 if b.sharedStrings == nil {
343 b.sharedStrings = make(map[string]UOffsetT)
344 }
345 if v, ok := b.sharedStrings[s]; ok {
346 return v
347 }
348 off := b.CreateString(s)
349 b.sharedStrings[s] = off
350 return off
351 }
352
353
354 func (b *Builder) CreateString(s string) UOffsetT {
355 b.assertNotNested()
356 b.nested = true
357
358 b.Prep(int(SizeUOffsetT), (len(s)+1)*SizeByte)
359 b.PlaceByte(0)
360
361 l := UOffsetT(len(s))
362
363 b.head -= l
364 copy(b.Bytes[b.head:b.head+l], s)
365
366 return b.EndVector(len(s))
367 }
368
369
370 func (b *Builder) CreateByteString(s []byte) UOffsetT {
371 b.assertNotNested()
372 b.nested = true
373
374 b.Prep(int(SizeUOffsetT), (len(s)+1)*SizeByte)
375 b.PlaceByte(0)
376
377 l := UOffsetT(len(s))
378
379 b.head -= l
380 copy(b.Bytes[b.head:b.head+l], s)
381
382 return b.EndVector(len(s))
383 }
384
385
386 func (b *Builder) CreateByteVector(v []byte) UOffsetT {
387 b.assertNotNested()
388 b.nested = true
389
390 b.Prep(int(SizeUOffsetT), len(v)*SizeByte)
391
392 l := UOffsetT(len(v))
393
394 b.head -= l
395 copy(b.Bytes[b.head:b.head+l], v)
396
397 return b.EndVector(len(v))
398 }
399
400 func (b *Builder) assertNested() {
401
402
403
404
405 if !b.nested {
406 panic("Incorrect creation order: must be inside object.")
407 }
408 }
409
410 func (b *Builder) assertNotNested() {
411
412
413
414
415
416
417
418
419 if b.nested {
420 panic("Incorrect creation order: object must not be nested.")
421 }
422 }
423
424 func (b *Builder) assertFinished() {
425
426
427
428
429
430 if !b.finished {
431 panic("Incorrect use of FinishedBytes(): must call 'Finish' first.")
432 }
433 }
434
435
436
437
438 func (b *Builder) PrependBoolSlot(o int, x, d bool) {
439 val := byte(0)
440 if x {
441 val = 1
442 }
443 def := byte(0)
444 if d {
445 def = 1
446 }
447 b.PrependByteSlot(o, val, def)
448 }
449
450
451
452
453 func (b *Builder) PrependByteSlot(o int, x, d byte) {
454 if x != d {
455 b.PrependByte(x)
456 b.Slot(o)
457 }
458 }
459
460
461
462
463 func (b *Builder) PrependUint8Slot(o int, x, d uint8) {
464 if x != d {
465 b.PrependUint8(x)
466 b.Slot(o)
467 }
468 }
469
470
471
472
473 func (b *Builder) PrependUint16Slot(o int, x, d uint16) {
474 if x != d {
475 b.PrependUint16(x)
476 b.Slot(o)
477 }
478 }
479
480
481
482
483 func (b *Builder) PrependUint32Slot(o int, x, d uint32) {
484 if x != d {
485 b.PrependUint32(x)
486 b.Slot(o)
487 }
488 }
489
490
491
492
493 func (b *Builder) PrependUint64Slot(o int, x, d uint64) {
494 if x != d {
495 b.PrependUint64(x)
496 b.Slot(o)
497 }
498 }
499
500
501
502
503 func (b *Builder) PrependInt8Slot(o int, x, d int8) {
504 if x != d {
505 b.PrependInt8(x)
506 b.Slot(o)
507 }
508 }
509
510
511
512
513 func (b *Builder) PrependInt16Slot(o int, x, d int16) {
514 if x != d {
515 b.PrependInt16(x)
516 b.Slot(o)
517 }
518 }
519
520
521
522
523 func (b *Builder) PrependInt32Slot(o int, x, d int32) {
524 if x != d {
525 b.PrependInt32(x)
526 b.Slot(o)
527 }
528 }
529
530
531
532
533 func (b *Builder) PrependInt64Slot(o int, x, d int64) {
534 if x != d {
535 b.PrependInt64(x)
536 b.Slot(o)
537 }
538 }
539
540
541
542
543 func (b *Builder) PrependFloat32Slot(o int, x, d float32) {
544 if x != d {
545 b.PrependFloat32(x)
546 b.Slot(o)
547 }
548 }
549
550
551
552
553 func (b *Builder) PrependFloat64Slot(o int, x, d float64) {
554 if x != d {
555 b.PrependFloat64(x)
556 b.Slot(o)
557 }
558 }
559
560
561
562
563 func (b *Builder) PrependUOffsetTSlot(o int, x, d UOffsetT) {
564 if x != d {
565 b.PrependUOffsetT(x)
566 b.Slot(o)
567 }
568 }
569
570
571
572
573 func (b *Builder) PrependStructSlot(voffset int, x, d UOffsetT) {
574 if x != d {
575 b.assertNested()
576 if x != b.Offset() {
577 panic("inline data write outside of object")
578 }
579 b.Slot(voffset)
580 }
581 }
582
583
584 func (b *Builder) Slot(slotnum int) {
585 b.vtable[slotnum] = UOffsetT(b.Offset())
586 }
587
588
589
590 func (b *Builder) FinishWithFileIdentifier(rootTable UOffsetT, fid []byte) {
591 if fid == nil || len(fid) != fileIdentifierLength {
592 panic("incorrect file identifier length")
593 }
594
595
596 b.Prep(b.minalign, SizeInt32+fileIdentifierLength)
597 for i := fileIdentifierLength - 1; i >= 0; i-- {
598
599 b.PlaceByte(fid[i])
600 }
601
602 b.Finish(rootTable)
603 }
604
605
606
607
608 func (b *Builder) FinishSizePrefixed(rootTable UOffsetT) {
609 b.finish(rootTable, true)
610 }
611
612
613
614
615 func (b *Builder) FinishSizePrefixedWithFileIdentifier(rootTable UOffsetT, fid []byte) {
616 if fid == nil || len(fid) != fileIdentifierLength {
617 panic("incorrect file identifier length")
618 }
619
620
621 b.Prep(b.minalign, SizeInt32+fileIdentifierLength+sizePrefixLength)
622 for i := fileIdentifierLength - 1; i >= 0; i-- {
623
624 b.PlaceByte(fid[i])
625 }
626
627 b.finish(rootTable, true)
628 }
629
630
631 func (b *Builder) Finish(rootTable UOffsetT) {
632 b.finish(rootTable, false)
633 }
634
635
636
637 func (b *Builder) finish(rootTable UOffsetT, sizePrefix bool) {
638 b.assertNotNested()
639
640 if sizePrefix {
641 b.Prep(b.minalign, SizeUOffsetT+sizePrefixLength)
642 } else {
643 b.Prep(b.minalign, SizeUOffsetT)
644 }
645
646 b.PrependUOffsetT(rootTable)
647
648 if sizePrefix {
649 b.PlaceUint32(uint32(b.Offset()))
650 }
651
652 b.finished = true
653 }
654
655
656 func vtableEqual(a []UOffsetT, objectStart UOffsetT, b []byte) bool {
657 if len(a)*SizeVOffsetT != len(b) {
658 return false
659 }
660
661 for i := 0; i < len(a); i++ {
662 x := GetVOffsetT(b[i*SizeVOffsetT : (i+1)*SizeVOffsetT])
663
664
665 if x == 0 && a[i] == 0 {
666 continue
667 }
668
669 y := SOffsetT(objectStart) - SOffsetT(a[i])
670 if SOffsetT(x) != y {
671 return false
672 }
673 }
674 return true
675 }
676
677
678
679 func (b *Builder) PrependBool(x bool) {
680 b.Prep(SizeBool, 0)
681 b.PlaceBool(x)
682 }
683
684
685
686 func (b *Builder) PrependUint8(x uint8) {
687 b.Prep(SizeUint8, 0)
688 b.PlaceUint8(x)
689 }
690
691
692
693 func (b *Builder) PrependUint16(x uint16) {
694 b.Prep(SizeUint16, 0)
695 b.PlaceUint16(x)
696 }
697
698
699
700 func (b *Builder) PrependUint32(x uint32) {
701 b.Prep(SizeUint32, 0)
702 b.PlaceUint32(x)
703 }
704
705
706
707 func (b *Builder) PrependUint64(x uint64) {
708 b.Prep(SizeUint64, 0)
709 b.PlaceUint64(x)
710 }
711
712
713
714 func (b *Builder) PrependInt8(x int8) {
715 b.Prep(SizeInt8, 0)
716 b.PlaceInt8(x)
717 }
718
719
720
721 func (b *Builder) PrependInt16(x int16) {
722 b.Prep(SizeInt16, 0)
723 b.PlaceInt16(x)
724 }
725
726
727
728 func (b *Builder) PrependInt32(x int32) {
729 b.Prep(SizeInt32, 0)
730 b.PlaceInt32(x)
731 }
732
733
734
735 func (b *Builder) PrependInt64(x int64) {
736 b.Prep(SizeInt64, 0)
737 b.PlaceInt64(x)
738 }
739
740
741
742 func (b *Builder) PrependFloat32(x float32) {
743 b.Prep(SizeFloat32, 0)
744 b.PlaceFloat32(x)
745 }
746
747
748
749 func (b *Builder) PrependFloat64(x float64) {
750 b.Prep(SizeFloat64, 0)
751 b.PlaceFloat64(x)
752 }
753
754
755
756 func (b *Builder) PrependByte(x byte) {
757 b.Prep(SizeByte, 0)
758 b.PlaceByte(x)
759 }
760
761
762
763 func (b *Builder) PrependVOffsetT(x VOffsetT) {
764 b.Prep(SizeVOffsetT, 0)
765 b.PlaceVOffsetT(x)
766 }
767
768
769 func (b *Builder) PlaceBool(x bool) {
770 b.head -= UOffsetT(SizeBool)
771 WriteBool(b.Bytes[b.head:], x)
772 }
773
774
775 func (b *Builder) PlaceUint8(x uint8) {
776 b.head -= UOffsetT(SizeUint8)
777 WriteUint8(b.Bytes[b.head:], x)
778 }
779
780
781 func (b *Builder) PlaceUint16(x uint16) {
782 b.head -= UOffsetT(SizeUint16)
783 WriteUint16(b.Bytes[b.head:], x)
784 }
785
786
787 func (b *Builder) PlaceUint32(x uint32) {
788 b.head -= UOffsetT(SizeUint32)
789 WriteUint32(b.Bytes[b.head:], x)
790 }
791
792
793 func (b *Builder) PlaceUint64(x uint64) {
794 b.head -= UOffsetT(SizeUint64)
795 WriteUint64(b.Bytes[b.head:], x)
796 }
797
798
799 func (b *Builder) PlaceInt8(x int8) {
800 b.head -= UOffsetT(SizeInt8)
801 WriteInt8(b.Bytes[b.head:], x)
802 }
803
804
805 func (b *Builder) PlaceInt16(x int16) {
806 b.head -= UOffsetT(SizeInt16)
807 WriteInt16(b.Bytes[b.head:], x)
808 }
809
810
811 func (b *Builder) PlaceInt32(x int32) {
812 b.head -= UOffsetT(SizeInt32)
813 WriteInt32(b.Bytes[b.head:], x)
814 }
815
816
817 func (b *Builder) PlaceInt64(x int64) {
818 b.head -= UOffsetT(SizeInt64)
819 WriteInt64(b.Bytes[b.head:], x)
820 }
821
822
823 func (b *Builder) PlaceFloat32(x float32) {
824 b.head -= UOffsetT(SizeFloat32)
825 WriteFloat32(b.Bytes[b.head:], x)
826 }
827
828
829 func (b *Builder) PlaceFloat64(x float64) {
830 b.head -= UOffsetT(SizeFloat64)
831 WriteFloat64(b.Bytes[b.head:], x)
832 }
833
834
835 func (b *Builder) PlaceByte(x byte) {
836 b.head -= UOffsetT(SizeByte)
837 WriteByte(b.Bytes[b.head:], x)
838 }
839
840
841 func (b *Builder) PlaceVOffsetT(x VOffsetT) {
842 b.head -= UOffsetT(SizeVOffsetT)
843 WriteVOffsetT(b.Bytes[b.head:], x)
844 }
845
846
847 func (b *Builder) PlaceSOffsetT(x SOffsetT) {
848 b.head -= UOffsetT(SizeSOffsetT)
849 WriteSOffsetT(b.Bytes[b.head:], x)
850 }
851
852
853 func (b *Builder) PlaceUOffsetT(x UOffsetT) {
854 b.head -= UOffsetT(SizeUOffsetT)
855 WriteUOffsetT(b.Bytes[b.head:], x)
856 }
857
View as plain text