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