xref: /aosp_15_r20/external/flatbuffers/lobster/flatbuffers.lobster (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Worker// Copyright 2018 Google Inc. All rights reserved.
2*890232f2SAndroid Build Coastguard Worker//
3*890232f2SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*890232f2SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*890232f2SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*890232f2SAndroid Build Coastguard Worker//
7*890232f2SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*890232f2SAndroid Build Coastguard Worker//
9*890232f2SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*890232f2SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*890232f2SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*890232f2SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*890232f2SAndroid Build Coastguard Worker// limitations under the License.
14*890232f2SAndroid Build Coastguard Worker
15*890232f2SAndroid Build Coastguard Workerimport std
16*890232f2SAndroid Build Coastguard Worker
17*890232f2SAndroid Build Coastguard Workernamespace flatbuffers
18*890232f2SAndroid Build Coastguard Worker
19*890232f2SAndroid Build Coastguard Workerclass handle:
20*890232f2SAndroid Build Coastguard Worker    buf_:string
21*890232f2SAndroid Build Coastguard Worker    pos_:int
22*890232f2SAndroid Build Coastguard Worker
23*890232f2SAndroid Build Coastguard Worker// More strongly typed than a naked int, at no cost.
24*890232f2SAndroid Build Coastguard Workerstruct offset:
25*890232f2SAndroid Build Coastguard Worker    o:int
26*890232f2SAndroid Build Coastguard Worker
27*890232f2SAndroid Build Coastguard Workerenum sizeof:
28*890232f2SAndroid Build Coastguard Worker    sz_8 = 1
29*890232f2SAndroid Build Coastguard Worker    sz_16 = 2
30*890232f2SAndroid Build Coastguard Worker    sz_32 = 4
31*890232f2SAndroid Build Coastguard Worker    sz_64 = 8
32*890232f2SAndroid Build Coastguard Worker    sz_voffset = 2
33*890232f2SAndroid Build Coastguard Worker    sz_uoffset = 4
34*890232f2SAndroid Build Coastguard Worker    sz_soffset = 4
35*890232f2SAndroid Build Coastguard Worker    sz_metadata_fields = 2
36*890232f2SAndroid Build Coastguard Worker
37*890232f2SAndroid Build Coastguard Workerclass builder:
38*890232f2SAndroid Build Coastguard Worker    buf = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
39*890232f2SAndroid Build Coastguard Worker    current_vtable:[int] = []
40*890232f2SAndroid Build Coastguard Worker    head = 0
41*890232f2SAndroid Build Coastguard Worker    minalign = 1
42*890232f2SAndroid Build Coastguard Worker    object_end = 0
43*890232f2SAndroid Build Coastguard Worker    vtables:[int] = []
44*890232f2SAndroid Build Coastguard Worker    nested = false
45*890232f2SAndroid Build Coastguard Worker    finished = false
46*890232f2SAndroid Build Coastguard Worker
47*890232f2SAndroid Build Coastguard Worker    // Optionally call this right after creating the builder for a larger initial buffer.
48*890232f2SAndroid Build Coastguard Worker    def Initial(initial_size:int):
49*890232f2SAndroid Build Coastguard Worker        buf = "\x00".repeat_string(initial_size)
50*890232f2SAndroid Build Coastguard Worker
51*890232f2SAndroid Build Coastguard Worker    def Start():
52*890232f2SAndroid Build Coastguard Worker        // Get the start of useful data in the underlying byte buffer.
53*890232f2SAndroid Build Coastguard Worker        return buf.length - head
54*890232f2SAndroid Build Coastguard Worker
55*890232f2SAndroid Build Coastguard Worker    def Offset():
56*890232f2SAndroid Build Coastguard Worker        // Offset relative to the end of the buffer.
57*890232f2SAndroid Build Coastguard Worker        return offset { head }
58*890232f2SAndroid Build Coastguard Worker
59*890232f2SAndroid Build Coastguard Worker    // Returns a copy of the part of the buffer containing only the finished FlatBuffer
60*890232f2SAndroid Build Coastguard Worker    def SizedCopy():
61*890232f2SAndroid Build Coastguard Worker        assert finished
62*890232f2SAndroid Build Coastguard Worker        return buf.substring(Start(), -1)
63*890232f2SAndroid Build Coastguard Worker
64*890232f2SAndroid Build Coastguard Worker    def StartNesting():
65*890232f2SAndroid Build Coastguard Worker        assert not nested
66*890232f2SAndroid Build Coastguard Worker        nested = true
67*890232f2SAndroid Build Coastguard Worker
68*890232f2SAndroid Build Coastguard Worker    def EndNesting():
69*890232f2SAndroid Build Coastguard Worker        assert nested
70*890232f2SAndroid Build Coastguard Worker        nested = false
71*890232f2SAndroid Build Coastguard Worker
72*890232f2SAndroid Build Coastguard Worker    def StartObject(numfields):
73*890232f2SAndroid Build Coastguard Worker        StartNesting()
74*890232f2SAndroid Build Coastguard Worker        current_vtable = map(numfields): 0
75*890232f2SAndroid Build Coastguard Worker        object_end = head
76*890232f2SAndroid Build Coastguard Worker        minalign = 1
77*890232f2SAndroid Build Coastguard Worker
78*890232f2SAndroid Build Coastguard Worker    def EndObject():
79*890232f2SAndroid Build Coastguard Worker        EndNesting()
80*890232f2SAndroid Build Coastguard Worker        // Prepend a zero scalar to the object. Later in this function we'll
81*890232f2SAndroid Build Coastguard Worker        // write an offset here that points to the object's vtable:
82*890232f2SAndroid Build Coastguard Worker        PrependInt32(0)
83*890232f2SAndroid Build Coastguard Worker        let object_offset = head
84*890232f2SAndroid Build Coastguard Worker        // Write out new vtable speculatively.
85*890232f2SAndroid Build Coastguard Worker        let vtable_size = (current_vtable.length + sz_metadata_fields) * sz_voffset
86*890232f2SAndroid Build Coastguard Worker        while current_vtable.length:
87*890232f2SAndroid Build Coastguard Worker            let o = current_vtable.pop()
88*890232f2SAndroid Build Coastguard Worker            PrependVOffsetT(if o: object_offset - o else: 0)
89*890232f2SAndroid Build Coastguard Worker        // The two metadata fields are written last.
90*890232f2SAndroid Build Coastguard Worker        // First, store the object bytesize:
91*890232f2SAndroid Build Coastguard Worker        PrependVOffsetT(object_offset - object_end)
92*890232f2SAndroid Build Coastguard Worker        // Second, store the vtable bytesize:
93*890232f2SAndroid Build Coastguard Worker        PrependVOffsetT(vtable_size)
94*890232f2SAndroid Build Coastguard Worker        // Search backwards through existing vtables, because similar vtables
95*890232f2SAndroid Build Coastguard Worker        // are likely to have been recently appended. See
96*890232f2SAndroid Build Coastguard Worker        // BenchmarkVtableDeduplication for a case in which this heuristic
97*890232f2SAndroid Build Coastguard Worker        // saves about 30% of the time used in writing objects with duplicate
98*890232f2SAndroid Build Coastguard Worker        // tables.
99*890232f2SAndroid Build Coastguard Worker        def find_existing_table():
100*890232f2SAndroid Build Coastguard Worker            reverse(vtables) vt2_offset:
101*890232f2SAndroid Build Coastguard Worker                // Find the other vtable:
102*890232f2SAndroid Build Coastguard Worker                let vt2_start = buf.length - vt2_offset
103*890232f2SAndroid Build Coastguard Worker                let vt2_len = buf.read_int16_le(vt2_start)
104*890232f2SAndroid Build Coastguard Worker                // Compare the other vtable to the one under consideration.
105*890232f2SAndroid Build Coastguard Worker                // If they are equal, return the offset:
106*890232f2SAndroid Build Coastguard Worker                if vtable_size == vt2_len and
107*890232f2SAndroid Build Coastguard Worker                    not compare_substring(buf, Start(), buf, vt2_start, vtable_size):
108*890232f2SAndroid Build Coastguard Worker                        return vt2_offset
109*890232f2SAndroid Build Coastguard Worker            return 0
110*890232f2SAndroid Build Coastguard Worker        let existing_vtable = find_existing_table()
111*890232f2SAndroid Build Coastguard Worker        if existing_vtable:
112*890232f2SAndroid Build Coastguard Worker            // Found a duplicate vtable, remove the one we wrote.
113*890232f2SAndroid Build Coastguard Worker            head = object_offset
114*890232f2SAndroid Build Coastguard Worker            // Write the offset to the found vtable in the
115*890232f2SAndroid Build Coastguard Worker            // already-allocated offset at the beginning of this object:
116*890232f2SAndroid Build Coastguard Worker            buf.write_int32_le(Start(), existing_vtable - object_offset)
117*890232f2SAndroid Build Coastguard Worker        else:
118*890232f2SAndroid Build Coastguard Worker            // Did not find a vtable, so keep the one we wrote.
119*890232f2SAndroid Build Coastguard Worker            // Next, write the offset to the new vtable in the
120*890232f2SAndroid Build Coastguard Worker            // already-allocated offset at the beginning of this object:
121*890232f2SAndroid Build Coastguard Worker            buf.write_int32_le(buf.length - object_offset, head - object_offset)
122*890232f2SAndroid Build Coastguard Worker            // Finally, store this vtable in memory for future
123*890232f2SAndroid Build Coastguard Worker            // deduplication:
124*890232f2SAndroid Build Coastguard Worker            vtables.push(head)
125*890232f2SAndroid Build Coastguard Worker        return offset { object_offset }
126*890232f2SAndroid Build Coastguard Worker
127*890232f2SAndroid Build Coastguard Worker    def Pad(n):
128*890232f2SAndroid Build Coastguard Worker        for(n):
129*890232f2SAndroid Build Coastguard Worker            buf, head = buf.write_int8_le_back(head, 0)
130*890232f2SAndroid Build Coastguard Worker
131*890232f2SAndroid Build Coastguard Worker    def Prep(size, additional_bytes):
132*890232f2SAndroid Build Coastguard Worker        // Track the biggest thing we've ever aligned to.
133*890232f2SAndroid Build Coastguard Worker        if size > minalign:
134*890232f2SAndroid Build Coastguard Worker            minalign = size
135*890232f2SAndroid Build Coastguard Worker        // Find the amount of alignment needed such that `size` is properly
136*890232f2SAndroid Build Coastguard Worker        // aligned after `additionalBytes`:
137*890232f2SAndroid Build Coastguard Worker        let align_size = ((~(head + additional_bytes)) + 1) & (size - 1)
138*890232f2SAndroid Build Coastguard Worker        Pad(align_size)
139*890232f2SAndroid Build Coastguard Worker
140*890232f2SAndroid Build Coastguard Worker    def PrependUOffsetTRelative(off:offset):
141*890232f2SAndroid Build Coastguard Worker        // Prepends an unsigned offset into vector data, relative to where it will be written.
142*890232f2SAndroid Build Coastguard Worker        Prep(sz_uoffset, 0)
143*890232f2SAndroid Build Coastguard Worker        assert off.o <= head
144*890232f2SAndroid Build Coastguard Worker        PlaceUOffsetT(head - off.o + sz_uoffset)
145*890232f2SAndroid Build Coastguard Worker
146*890232f2SAndroid Build Coastguard Worker    def StartVector(elem_size, num_elems, alignment):
147*890232f2SAndroid Build Coastguard Worker        // Initializes bookkeeping for writing a new vector.
148*890232f2SAndroid Build Coastguard Worker        StartNesting()
149*890232f2SAndroid Build Coastguard Worker        Prep(sz_32, elem_size * num_elems)
150*890232f2SAndroid Build Coastguard Worker        Prep(alignment, elem_size * num_elems)  // In case alignment > int.
151*890232f2SAndroid Build Coastguard Worker        return Offset()
152*890232f2SAndroid Build Coastguard Worker
153*890232f2SAndroid Build Coastguard Worker    def EndVector(vector_num_elems):
154*890232f2SAndroid Build Coastguard Worker        EndNesting()
155*890232f2SAndroid Build Coastguard Worker        // we already made space for this, so write without PrependUint32
156*890232f2SAndroid Build Coastguard Worker        PlaceUOffsetT(vector_num_elems)
157*890232f2SAndroid Build Coastguard Worker        return Offset()
158*890232f2SAndroid Build Coastguard Worker
159*890232f2SAndroid Build Coastguard Worker    def CreateString(s:string):
160*890232f2SAndroid Build Coastguard Worker        // writes a null-terminated byte string.
161*890232f2SAndroid Build Coastguard Worker        StartNesting()
162*890232f2SAndroid Build Coastguard Worker        Prep(sz_32, s.length + 1)
163*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_substring_back(head, s, true)
164*890232f2SAndroid Build Coastguard Worker        return EndVector(s.length)
165*890232f2SAndroid Build Coastguard Worker
166*890232f2SAndroid Build Coastguard Worker    def CreateByteVector(s:string):
167*890232f2SAndroid Build Coastguard Worker        // writes a non-null-terminated byte string.
168*890232f2SAndroid Build Coastguard Worker        StartNesting()
169*890232f2SAndroid Build Coastguard Worker        Prep(sz_32, s.length)
170*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_substring_back(head, s, false)
171*890232f2SAndroid Build Coastguard Worker        return EndVector(s.length)
172*890232f2SAndroid Build Coastguard Worker
173*890232f2SAndroid Build Coastguard Worker    def Slot(slotnum):
174*890232f2SAndroid Build Coastguard Worker        assert nested
175*890232f2SAndroid Build Coastguard Worker        while current_vtable.length <= slotnum: current_vtable.push(0)
176*890232f2SAndroid Build Coastguard Worker        current_vtable[slotnum] = head
177*890232f2SAndroid Build Coastguard Worker
178*890232f2SAndroid Build Coastguard Worker    def __Finish(root_table:offset, size_prefix:int, file_identifier:string?):
179*890232f2SAndroid Build Coastguard Worker        // Finish finalizes a buffer, pointing to the given root_table
180*890232f2SAndroid Build Coastguard Worker        assert not finished
181*890232f2SAndroid Build Coastguard Worker        assert not nested
182*890232f2SAndroid Build Coastguard Worker        var prep_size = sz_32
183*890232f2SAndroid Build Coastguard Worker        if file_identifier:
184*890232f2SAndroid Build Coastguard Worker            prep_size += sz_32
185*890232f2SAndroid Build Coastguard Worker        if size_prefix:
186*890232f2SAndroid Build Coastguard Worker            prep_size += sz_32
187*890232f2SAndroid Build Coastguard Worker        Prep(minalign, prep_size)
188*890232f2SAndroid Build Coastguard Worker        if file_identifier:
189*890232f2SAndroid Build Coastguard Worker            assert file_identifier.length == 4
190*890232f2SAndroid Build Coastguard Worker            buf, head = buf.write_substring_back(head, file_identifier, false)
191*890232f2SAndroid Build Coastguard Worker        PrependUOffsetTRelative(root_table)
192*890232f2SAndroid Build Coastguard Worker        if size_prefix:
193*890232f2SAndroid Build Coastguard Worker            PrependInt32(head)
194*890232f2SAndroid Build Coastguard Worker        finished = true
195*890232f2SAndroid Build Coastguard Worker        return Start()
196*890232f2SAndroid Build Coastguard Worker
197*890232f2SAndroid Build Coastguard Worker    def Finish(root_table:offset, file_identifier:string? = nil):
198*890232f2SAndroid Build Coastguard Worker        return __Finish(root_table, false, file_identifier)
199*890232f2SAndroid Build Coastguard Worker
200*890232f2SAndroid Build Coastguard Worker    def FinishSizePrefixed(root_table:offset, file_identifier:string? = nil):
201*890232f2SAndroid Build Coastguard Worker        return __Finish(root_table, true, file_identifier)
202*890232f2SAndroid Build Coastguard Worker
203*890232f2SAndroid Build Coastguard Worker    def PrependBool(x):
204*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int8_le_back(head, x)
205*890232f2SAndroid Build Coastguard Worker
206*890232f2SAndroid Build Coastguard Worker    def PrependByte(x):
207*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int8_le_back(head, x)
208*890232f2SAndroid Build Coastguard Worker
209*890232f2SAndroid Build Coastguard Worker    def PrependUint8(x):
210*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int8_le_back(head, x)
211*890232f2SAndroid Build Coastguard Worker
212*890232f2SAndroid Build Coastguard Worker    def PrependUint16(x):
213*890232f2SAndroid Build Coastguard Worker        Prep(sz_16, 0)
214*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int16_le_back(head, x)
215*890232f2SAndroid Build Coastguard Worker
216*890232f2SAndroid Build Coastguard Worker    def PrependUint32(x):
217*890232f2SAndroid Build Coastguard Worker        Prep(sz_32, 0)
218*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int32_le_back(head, x)
219*890232f2SAndroid Build Coastguard Worker
220*890232f2SAndroid Build Coastguard Worker    def PrependUint64(x):
221*890232f2SAndroid Build Coastguard Worker        Prep(sz_64, 0)
222*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int64_le_back(head, x)
223*890232f2SAndroid Build Coastguard Worker
224*890232f2SAndroid Build Coastguard Worker    def PrependInt8(x):
225*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int8_le_back(head, x)
226*890232f2SAndroid Build Coastguard Worker
227*890232f2SAndroid Build Coastguard Worker    def PrependInt16(x):
228*890232f2SAndroid Build Coastguard Worker        Prep(sz_16, 0)
229*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int16_le_back(head, x)
230*890232f2SAndroid Build Coastguard Worker
231*890232f2SAndroid Build Coastguard Worker    def PrependInt32(x):
232*890232f2SAndroid Build Coastguard Worker        Prep(sz_32, 0)
233*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int32_le_back(head, x)
234*890232f2SAndroid Build Coastguard Worker
235*890232f2SAndroid Build Coastguard Worker    def PrependInt64(x):
236*890232f2SAndroid Build Coastguard Worker        Prep(sz_64, 0)
237*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int64_le_back(head, x)
238*890232f2SAndroid Build Coastguard Worker
239*890232f2SAndroid Build Coastguard Worker    def PrependFloat32(x):
240*890232f2SAndroid Build Coastguard Worker        Prep(sz_32, 0)
241*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_float32_le_back(head, x)
242*890232f2SAndroid Build Coastguard Worker
243*890232f2SAndroid Build Coastguard Worker    def PrependFloat64(x):
244*890232f2SAndroid Build Coastguard Worker        Prep(sz_64, 0)
245*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_float64_le_back(head, x)
246*890232f2SAndroid Build Coastguard Worker
247*890232f2SAndroid Build Coastguard Worker    def PrependVOffsetT(x):
248*890232f2SAndroid Build Coastguard Worker        Prep(sz_voffset, 0)
249*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int16_le_back(head, x)
250*890232f2SAndroid Build Coastguard Worker
251*890232f2SAndroid Build Coastguard Worker    def PlaceVOffsetT(x):
252*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int16_le_back(head, x)
253*890232f2SAndroid Build Coastguard Worker
254*890232f2SAndroid Build Coastguard Worker    def PlaceSOffsetT(x):
255*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int32_le_back(head, x)
256*890232f2SAndroid Build Coastguard Worker
257*890232f2SAndroid Build Coastguard Worker    def PlaceUOffsetT(x):
258*890232f2SAndroid Build Coastguard Worker        buf, head = buf.write_int32_le_back(head, x)
259*890232f2SAndroid Build Coastguard Worker
260*890232f2SAndroid Build Coastguard Worker    def PrependSlot(o:int, x, d, f):
261*890232f2SAndroid Build Coastguard Worker        if x != d:
262*890232f2SAndroid Build Coastguard Worker            f(x)
263*890232f2SAndroid Build Coastguard Worker            Slot(o)
264*890232f2SAndroid Build Coastguard Worker
265*890232f2SAndroid Build Coastguard Worker    def PrependSlot(o:int, x, f):
266*890232f2SAndroid Build Coastguard Worker        f(x)
267*890232f2SAndroid Build Coastguard Worker        Slot(o)
268*890232f2SAndroid Build Coastguard Worker
269*890232f2SAndroid Build Coastguard Worker    def PrependBoolSlot(o, x, d): PrependSlot(o, x, d): PrependBool(_)
270*890232f2SAndroid Build Coastguard Worker    def PrependByteSlot(o, x, d): PrependSlot(o, x, d): PrependByte(_)
271*890232f2SAndroid Build Coastguard Worker    def PrependUint8Slot(o, x, d): PrependSlot(o, x, d): PrependUint8(_)
272*890232f2SAndroid Build Coastguard Worker    def PrependUint16Slot(o, x, d): PrependSlot(o, x, d): PrependUint16(_)
273*890232f2SAndroid Build Coastguard Worker    def PrependUint32Slot(o, x, d): PrependSlot(o, x, d): PrependUint32(_)
274*890232f2SAndroid Build Coastguard Worker    def PrependUint64Slot(o, x, d): PrependSlot(o, x, d): PrependUint64(_)
275*890232f2SAndroid Build Coastguard Worker    def PrependInt8Slot(o, x, d): PrependSlot(o, x, d): PrependInt8(_)
276*890232f2SAndroid Build Coastguard Worker    def PrependInt16Slot(o, x, d): PrependSlot(o, x, d): PrependInt16(_)
277*890232f2SAndroid Build Coastguard Worker    def PrependInt32Slot(o, x, d): PrependSlot(o, x, d): PrependInt32(_)
278*890232f2SAndroid Build Coastguard Worker    def PrependInt64Slot(o, x, d): PrependSlot(o, x, d): PrependInt64(_)
279*890232f2SAndroid Build Coastguard Worker    def PrependFloat32Slot(o, x, d): PrependSlot(o, x, d): PrependFloat32(_)
280*890232f2SAndroid Build Coastguard Worker    def PrependFloat64Slot(o, x, d): PrependSlot(o, x, d): PrependFloat64(_)
281*890232f2SAndroid Build Coastguard Worker
282*890232f2SAndroid Build Coastguard Worker    def PrependBoolSlot(o, x): PrependSlot(o, x): PrependBool(_)
283*890232f2SAndroid Build Coastguard Worker    def PrependByteSlot(o, x): PrependSlot(o, x): PrependByte(_)
284*890232f2SAndroid Build Coastguard Worker    def PrependUint8Slot(o, x): PrependSlot(o, x): PrependUint8(_)
285*890232f2SAndroid Build Coastguard Worker    def PrependUint16Slot(o, x): PrependSlot(o, x): PrependUint16(_)
286*890232f2SAndroid Build Coastguard Worker    def PrependUint32Slot(o, x): PrependSlot(o, x): PrependUint32(_)
287*890232f2SAndroid Build Coastguard Worker    def PrependUint64Slot(o, x): PrependSlot(o, x): PrependUint64(_)
288*890232f2SAndroid Build Coastguard Worker    def PrependInt8Slot(o, x): PrependSlot(o, x): PrependInt8(_)
289*890232f2SAndroid Build Coastguard Worker    def PrependInt16Slot(o, x): PrependSlot(o, x): PrependInt16(_)
290*890232f2SAndroid Build Coastguard Worker    def PrependInt32Slot(o, x): PrependSlot(o, x): PrependInt32(_)
291*890232f2SAndroid Build Coastguard Worker    def PrependInt64Slot(o, x): PrependSlot(o, x): PrependInt64(_)
292*890232f2SAndroid Build Coastguard Worker    def PrependFloat32Slot(o, x): PrependSlot(o, x): PrependFloat32(_)
293*890232f2SAndroid Build Coastguard Worker    def PrependFloat64Slot(o, x): PrependSlot(o, x): PrependFloat64(_)
294*890232f2SAndroid Build Coastguard Worker
295*890232f2SAndroid Build Coastguard Worker    def PrependUOffsetTRelativeSlot(o:int, x:offset):
296*890232f2SAndroid Build Coastguard Worker        if x.o:
297*890232f2SAndroid Build Coastguard Worker            PrependUOffsetTRelative(x)
298*890232f2SAndroid Build Coastguard Worker            Slot(o)
299*890232f2SAndroid Build Coastguard Worker
300*890232f2SAndroid Build Coastguard Worker    def PrependStructSlot(v:int, x:offset):
301*890232f2SAndroid Build Coastguard Worker        if x.o:
302*890232f2SAndroid Build Coastguard Worker            // Structs are always stored inline, so need to be created right
303*890232f2SAndroid Build Coastguard Worker            // where they are used. You'll get this error if you created it
304*890232f2SAndroid Build Coastguard Worker            // elsewhere.
305*890232f2SAndroid Build Coastguard Worker            assert x.o == head
306*890232f2SAndroid Build Coastguard Worker            Slot(v)
307*890232f2SAndroid Build Coastguard Worker
308*890232f2SAndroid Build Coastguard Workerdef has_identifier(buf:string, file_identifier:string):
309*890232f2SAndroid Build Coastguard Worker    assert file_identifier.length == 4
310*890232f2SAndroid Build Coastguard Worker    return buf.length >= 8 and buf.substring(4, 4) == file_identifier
311*890232f2SAndroid Build Coastguard Worker
312*890232f2SAndroid Build Coastguard Worker
313