builder.go 24 KB

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