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