Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/flatbuffers/builder.py: 27%

331 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-03 07:57 +0000

1# Copyright 2014 Google Inc. All rights reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14 

15from . import number_types as N 

16from .number_types import (UOffsetTFlags, SOffsetTFlags, VOffsetTFlags) 

17 

18from . import encode 

19from . import packer 

20 

21from . import compat 

22from .compat import range_func 

23from .compat import memoryview_type 

24from .compat import import_numpy, NumpyRequiredForThisFeature 

25 

26import warnings 

27 

28np = import_numpy() 

29## @file 

30## @addtogroup flatbuffers_python_api 

31## @{ 

32 

33## @cond FLATBUFFERS_INTERNAL 

34class OffsetArithmeticError(RuntimeError): 

35 """ 

36 Error caused by an Offset arithmetic error. Probably caused by bad 

37 writing of fields. This is considered an unreachable situation in 

38 normal circumstances. 

39 """ 

40 pass 

41 

42 

43class IsNotNestedError(RuntimeError): 

44 """ 

45 Error caused by using a Builder to write Object data when not inside 

46 an Object. 

47 """ 

48 pass 

49 

50 

51class IsNestedError(RuntimeError): 

52 """ 

53 Error caused by using a Builder to begin an Object when an Object is 

54 already being built. 

55 """ 

56 pass 

57 

58 

59class StructIsNotInlineError(RuntimeError): 

60 """ 

61 Error caused by using a Builder to write a Struct at a location that 

62 is not the current Offset. 

63 """ 

64 pass 

65 

66 

67class BuilderSizeError(RuntimeError): 

68 """ 

69 Error caused by causing a Builder to exceed the hardcoded limit of 2 

70 gigabytes. 

71 """ 

72 pass 

73 

74class BuilderNotFinishedError(RuntimeError): 

75 """ 

76 Error caused by not calling `Finish` before calling `Output`. 

77 """ 

78 pass 

79 

80class EndVectorLengthMismatched(RuntimeError): 

81 """ 

82 The number of elements passed to EndVector does not match the number  

83 specified in StartVector. 

84 """ 

85 pass 

86 

87 

88# VtableMetadataFields is the count of metadata fields in each vtable. 

89VtableMetadataFields = 2 

90## @endcond 

91 

92class Builder(object): 

93 """ A Builder is used to construct one or more FlatBuffers. 

94 

95 Typically, Builder objects will be used from code generated by the `flatc` 

96 compiler. 

97 

98 A Builder constructs byte buffers in a last-first manner for simplicity and 

99 performance during reading. 

100 

101 Internally, a Builder is a state machine for creating FlatBuffer objects. 

102 

103 It holds the following internal state: 

104 - Bytes: an array of bytes. 

105 - current_vtable: a list of integers. 

106 - vtables: a hash of vtable entries. 

107 

108 Attributes: 

109 Bytes: The internal `bytearray` for the Builder. 

110 finished: A boolean determining if the Builder has been finalized. 

111 """ 

112 

113 ## @cond FLATBUFFERS_INTENRAL 

114 __slots__ = ("Bytes", "current_vtable", "head", "minalign", "objectEnd", 

115 "vtables", "nested", "forceDefaults", "finished", "vectorNumElems", 

116 "sharedStrings") 

117 

118 """Maximum buffer size constant, in bytes. 

119 

120 Builder will never allow it's buffer grow over this size. 

121 Currently equals 2Gb. 

122 """ 

123 MAX_BUFFER_SIZE = 2**31 

124 ## @endcond 

125 

126 def __init__(self, initialSize=1024): 

127 """Initializes a Builder of size `initial_size`. 

128 

129 The internal buffer is grown as needed. 

130 """ 

131 

132 if not (0 <= initialSize <= Builder.MAX_BUFFER_SIZE): 

133 msg = "flatbuffers: Cannot create Builder larger than 2 gigabytes." 

134 raise BuilderSizeError(msg) 

135 

136 self.Bytes = bytearray(initialSize) 

137 ## @cond FLATBUFFERS_INTERNAL 

138 self.current_vtable = None 

139 self.head = UOffsetTFlags.py_type(initialSize) 

140 self.minalign = 1 

141 self.objectEnd = None 

142 self.vtables = {} 

143 self.nested = False 

144 self.forceDefaults = False 

145 self.sharedStrings = {} 

146 ## @endcond 

147 self.finished = False 

148 

149 def Output(self): 

150 """Return the portion of the buffer that has been used for writing data. 

151 

152 This is the typical way to access the FlatBuffer data inside the 

153 builder. If you try to access `Builder.Bytes` directly, you would need 

154 to manually index it with `Head()`, since the buffer is constructed 

155 backwards. 

156 

157 It raises BuilderNotFinishedError if the buffer has not been finished 

158 with `Finish`. 

159 """ 

160 

161 if not self.finished: 

162 raise BuilderNotFinishedError() 

163 

164 return self.Bytes[self.Head():] 

165 

166 ## @cond FLATBUFFERS_INTERNAL 

167 def StartObject(self, numfields): 

168 """StartObject initializes bookkeeping for writing a new object.""" 

169 

170 self.assertNotNested() 

171 

172 # use 32-bit offsets so that arithmetic doesn't overflow. 

173 self.current_vtable = [0 for _ in range_func(numfields)] 

174 self.objectEnd = self.Offset() 

175 self.nested = True 

176 

177 def WriteVtable(self): 

178 """ 

179 WriteVtable serializes the vtable for the current object, if needed. 

180 

181 Before writing out the vtable, this checks pre-existing vtables for 

182 equality to this one. If an equal vtable is found, point the object to 

183 the existing vtable and return. 

184 

185 Because vtable values are sensitive to alignment of object data, not 

186 all logically-equal vtables will be deduplicated. 

187 

188 A vtable has the following format: 

189 <VOffsetT: size of the vtable in bytes, including this value> 

190 <VOffsetT: size of the object in bytes, including the vtable offset> 

191 <VOffsetT: offset for a field> * N, where N is the number of fields 

192 in the schema for this type. Includes deprecated fields. 

193 Thus, a vtable is made of 2 + N elements, each VOffsetT bytes wide. 

194 

195 An object has the following format: 

196 <SOffsetT: offset to this object's vtable (may be negative)> 

197 <byte: data>+ 

198 """ 

199 

200 # Prepend a zero scalar to the object. Later in this function we'll 

201 # write an offset here that points to the object's vtable: 

202 self.PrependSOffsetTRelative(0) 

203 

204 objectOffset = self.Offset() 

205 

206 vtKey = [] 

207 trim = True 

208 for elem in reversed(self.current_vtable): 

209 if elem == 0: 

210 if trim: 

211 continue 

212 else: 

213 elem = objectOffset - elem 

214 trim = False 

215 

216 vtKey.append(elem) 

217 

218 vtKey = tuple(vtKey) 

219 vt2Offset = self.vtables.get(vtKey) 

220 if vt2Offset is None: 

221 # Did not find a vtable, so write this one to the buffer. 

222 

223 # Write out the current vtable in reverse , because 

224 # serialization occurs in last-first order: 

225 i = len(self.current_vtable) - 1 

226 trailing = 0 

227 trim = True 

228 while i >= 0: 

229 off = 0 

230 elem = self.current_vtable[i] 

231 i -= 1 

232 

233 if elem == 0: 

234 if trim: 

235 trailing += 1 

236 continue 

237 else: 

238 # Forward reference to field; 

239 # use 32bit number to ensure no overflow: 

240 off = objectOffset - elem 

241 trim = False 

242 

243 self.PrependVOffsetT(off) 

244 

245 # The two metadata fields are written last. 

246 

247 # First, store the object bytesize: 

248 objectSize = UOffsetTFlags.py_type(objectOffset - self.objectEnd) 

249 self.PrependVOffsetT(VOffsetTFlags.py_type(objectSize)) 

250 

251 # Second, store the vtable bytesize: 

252 vBytes = len(self.current_vtable) - trailing + VtableMetadataFields 

253 vBytes *= N.VOffsetTFlags.bytewidth 

254 self.PrependVOffsetT(VOffsetTFlags.py_type(vBytes)) 

255 

256 # Next, write the offset to the new vtable in the 

257 # already-allocated SOffsetT at the beginning of this object: 

258 objectStart = SOffsetTFlags.py_type(len(self.Bytes) - objectOffset) 

259 encode.Write(packer.soffset, self.Bytes, objectStart, 

260 SOffsetTFlags.py_type(self.Offset() - objectOffset)) 

261 

262 # Finally, store this vtable in memory for future 

263 # deduplication: 

264 self.vtables[vtKey] = self.Offset() 

265 else: 

266 # Found a duplicate vtable. 

267 objectStart = SOffsetTFlags.py_type(len(self.Bytes) - objectOffset) 

268 self.head = UOffsetTFlags.py_type(objectStart) 

269 

270 # Write the offset to the found vtable in the 

271 # already-allocated SOffsetT at the beginning of this object: 

272 encode.Write(packer.soffset, self.Bytes, self.Head(), 

273 SOffsetTFlags.py_type(vt2Offset - objectOffset)) 

274 

275 self.current_vtable = None 

276 return objectOffset 

277 

278 def EndObject(self): 

279 """EndObject writes data necessary to finish object construction.""" 

280 self.assertNested() 

281 self.nested = False 

282 return self.WriteVtable() 

283 

284 def growByteBuffer(self): 

285 """Doubles the size of the byteslice, and copies the old data towards 

286 the end of the new buffer (since we build the buffer backwards).""" 

287 if len(self.Bytes) == Builder.MAX_BUFFER_SIZE: 

288 msg = "flatbuffers: cannot grow buffer beyond 2 gigabytes" 

289 raise BuilderSizeError(msg) 

290 

291 newSize = min(len(self.Bytes) * 2, Builder.MAX_BUFFER_SIZE) 

292 if newSize == 0: 

293 newSize = 1 

294 bytes2 = bytearray(newSize) 

295 bytes2[newSize-len(self.Bytes):] = self.Bytes 

296 self.Bytes = bytes2 

297 ## @endcond 

298 

299 def Head(self): 

300 """Get the start of useful data in the underlying byte buffer. 

301 

302 Note: unlike other functions, this value is interpreted as from the 

303 left. 

304 """ 

305 ## @cond FLATBUFFERS_INTERNAL 

306 return self.head 

307 ## @endcond 

308 

309 ## @cond FLATBUFFERS_INTERNAL 

310 def Offset(self): 

311 """Offset relative to the end of the buffer.""" 

312 return UOffsetTFlags.py_type(len(self.Bytes) - self.Head()) 

313 

314 def Pad(self, n): 

315 """Pad places zeros at the current offset.""" 

316 for i in range_func(n): 

317 self.Place(0, N.Uint8Flags) 

318 

319 def Prep(self, size, additionalBytes): 

320 """ 

321 Prep prepares to write an element of `size` after `additional_bytes` 

322 have been written, e.g. if you write a string, you need to align 

323 such the int length field is aligned to SizeInt32, and the string 

324 data follows it directly. 

325 If all you need to do is align, `additionalBytes` will be 0. 

326 """ 

327 

328 # Track the biggest thing we've ever aligned to. 

329 if size > self.minalign: 

330 self.minalign = size 

331 

332 # Find the amount of alignment needed such that `size` is properly 

333 # aligned after `additionalBytes`: 

334 alignSize = (~(len(self.Bytes) - self.Head() + additionalBytes)) + 1 

335 alignSize &= (size - 1) 

336 

337 # Reallocate the buffer if needed: 

338 while self.Head() < alignSize+size+additionalBytes: 

339 oldBufSize = len(self.Bytes) 

340 self.growByteBuffer() 

341 updated_head = self.head + len(self.Bytes) - oldBufSize 

342 self.head = UOffsetTFlags.py_type(updated_head) 

343 self.Pad(alignSize) 

344 

345 def PrependSOffsetTRelative(self, off): 

346 """ 

347 PrependSOffsetTRelative prepends an SOffsetT, relative to where it 

348 will be written. 

349 """ 

350 

351 # Ensure alignment is already done: 

352 self.Prep(N.SOffsetTFlags.bytewidth, 0) 

353 if not (off <= self.Offset()): 

354 msg = "flatbuffers: Offset arithmetic error." 

355 raise OffsetArithmeticError(msg) 

356 off2 = self.Offset() - off + N.SOffsetTFlags.bytewidth 

357 self.PlaceSOffsetT(off2) 

358 ## @endcond 

359 

360 def PrependUOffsetTRelative(self, off): 

361 """Prepends an unsigned offset into vector data, relative to where it 

362 will be written. 

363 """ 

364 

365 # Ensure alignment is already done: 

366 self.Prep(N.UOffsetTFlags.bytewidth, 0) 

367 if not (off <= self.Offset()): 

368 msg = "flatbuffers: Offset arithmetic error." 

369 raise OffsetArithmeticError(msg) 

370 off2 = self.Offset() - off + N.UOffsetTFlags.bytewidth 

371 self.PlaceUOffsetT(off2) 

372 

373 ## @cond FLATBUFFERS_INTERNAL 

374 def StartVector(self, elemSize, numElems, alignment): 

375 """ 

376 StartVector initializes bookkeeping for writing a new vector. 

377 

378 A vector has the following format: 

379 - <UOffsetT: number of elements in this vector> 

380 - <T: data>+, where T is the type of elements of this vector. 

381 """ 

382 

383 self.assertNotNested() 

384 self.nested = True 

385 self.vectorNumElems = numElems 

386 self.Prep(N.Uint32Flags.bytewidth, elemSize*numElems) 

387 self.Prep(alignment, elemSize*numElems) # In case alignment > int. 

388 return self.Offset() 

389 ## @endcond 

390 

391 def EndVector(self, numElems = None): 

392 """EndVector writes data necessary to finish vector construction.""" 

393 

394 self.assertNested() 

395 ## @cond FLATBUFFERS_INTERNAL 

396 self.nested = False 

397 ## @endcond 

398 

399 if numElems: 

400 warnings.warn("numElems is deprecated.", 

401 DeprecationWarning, stacklevel=2) 

402 if numElems != self.vectorNumElems: 

403 raise EndVectorLengthMismatched(); 

404 

405 # we already made space for this, so write without PrependUint32 

406 self.PlaceUOffsetT(self.vectorNumElems) 

407 self.vectorNumElems = None 

408 return self.Offset() 

409 

410 def CreateSharedString(self, s, encoding='utf-8', errors='strict'): 

411 """ 

412 CreateSharedString checks if the string is already written to the buffer 

413 before calling CreateString. 

414 """ 

415 

416 if s in self.sharedStrings: 

417 return self.sharedStrings[s] 

418 

419 off = self.CreateString(s, encoding, errors) 

420 self.sharedStrings[s] = off 

421 

422 return off 

423 

424 def CreateString(self, s, encoding='utf-8', errors='strict'): 

425 """CreateString writes a null-terminated byte string as a vector.""" 

426 

427 self.assertNotNested() 

428 ## @cond FLATBUFFERS_INTERNAL 

429 self.nested = True 

430 ## @endcond 

431 

432 if isinstance(s, compat.string_types): 

433 x = s.encode(encoding, errors) 

434 elif isinstance(s, compat.binary_types): 

435 x = s 

436 else: 

437 raise TypeError("non-string passed to CreateString") 

438 

439 self.Prep(N.UOffsetTFlags.bytewidth, (len(x)+1)*N.Uint8Flags.bytewidth) 

440 self.Place(0, N.Uint8Flags) 

441 

442 l = UOffsetTFlags.py_type(len(s)) 

443 ## @cond FLATBUFFERS_INTERNAL 

444 self.head = UOffsetTFlags.py_type(self.Head() - l) 

445 ## @endcond 

446 self.Bytes[self.Head():self.Head()+l] = x 

447 

448 self.vectorNumElems = len(x) 

449 return self.EndVector() 

450 

451 def CreateByteVector(self, x): 

452 """CreateString writes a byte vector.""" 

453 

454 self.assertNotNested() 

455 ## @cond FLATBUFFERS_INTERNAL 

456 self.nested = True 

457 ## @endcond 

458 

459 if not isinstance(x, compat.binary_types): 

460 raise TypeError("non-byte vector passed to CreateByteVector") 

461 

462 self.Prep(N.UOffsetTFlags.bytewidth, len(x)*N.Uint8Flags.bytewidth) 

463 

464 l = UOffsetTFlags.py_type(len(x)) 

465 ## @cond FLATBUFFERS_INTERNAL 

466 self.head = UOffsetTFlags.py_type(self.Head() - l) 

467 ## @endcond 

468 self.Bytes[self.Head():self.Head()+l] = x 

469 

470 self.vectorNumElems = len(x) 

471 return self.EndVector() 

472 

473 def CreateNumpyVector(self, x): 

474 """CreateNumpyVector writes a numpy array into the buffer.""" 

475 

476 if np is None: 

477 # Numpy is required for this feature 

478 raise NumpyRequiredForThisFeature("Numpy was not found.") 

479 

480 if not isinstance(x, np.ndarray): 

481 raise TypeError("non-numpy-ndarray passed to CreateNumpyVector") 

482 

483 if x.dtype.kind not in ['b', 'i', 'u', 'f']: 

484 raise TypeError("numpy-ndarray holds elements of unsupported datatype") 

485 

486 if x.ndim > 1: 

487 raise TypeError("multidimensional-ndarray passed to CreateNumpyVector") 

488 

489 self.StartVector(x.itemsize, x.size, x.dtype.alignment) 

490 

491 # Ensure little endian byte ordering 

492 if x.dtype.str[0] == "<": 

493 x_lend = x 

494 else: 

495 x_lend = x.byteswap(inplace=False) 

496 

497 # Calculate total length 

498 l = UOffsetTFlags.py_type(x_lend.itemsize * x_lend.size) 

499 ## @cond FLATBUFFERS_INTERNAL 

500 self.head = UOffsetTFlags.py_type(self.Head() - l) 

501 ## @endcond 

502 

503 # tobytes ensures c_contiguous ordering 

504 self.Bytes[self.Head():self.Head()+l] = x_lend.tobytes(order='C') 

505 

506 self.vectorNumElems = x.size 

507 return self.EndVector() 

508 

509 ## @cond FLATBUFFERS_INTERNAL 

510 def assertNested(self): 

511 """ 

512 Check that we are in the process of building an object. 

513 """ 

514 

515 if not self.nested: 

516 raise IsNotNestedError() 

517 

518 def assertNotNested(self): 

519 """ 

520 Check that no other objects are being built while making this 

521 object. If not, raise an exception. 

522 """ 

523 

524 if self.nested: 

525 raise IsNestedError() 

526 

527 def assertStructIsInline(self, obj): 

528 """ 

529 Structs are always stored inline, so need to be created right 

530 where they are used. You'll get this error if you created it 

531 elsewhere. 

532 """ 

533 

534 N.enforce_number(obj, N.UOffsetTFlags) 

535 if obj != self.Offset(): 

536 msg = ("flatbuffers: Tried to write a Struct at an Offset that " 

537 "is different from the current Offset of the Builder.") 

538 raise StructIsNotInlineError(msg) 

539 

540 def Slot(self, slotnum): 

541 """ 

542 Slot sets the vtable key `voffset` to the current location in the 

543 buffer. 

544 

545 """ 

546 self.assertNested() 

547 self.current_vtable[slotnum] = self.Offset() 

548 ## @endcond 

549 

550 def __Finish(self, rootTable, sizePrefix, file_identifier=None): 

551 """Finish finalizes a buffer, pointing to the given `rootTable`.""" 

552 N.enforce_number(rootTable, N.UOffsetTFlags) 

553 

554 prepSize = N.UOffsetTFlags.bytewidth 

555 if file_identifier is not None: 

556 prepSize += N.Int32Flags.bytewidth 

557 if sizePrefix: 

558 prepSize += N.Int32Flags.bytewidth 

559 self.Prep(self.minalign, prepSize) 

560 

561 if file_identifier is not None: 

562 self.Prep(N.UOffsetTFlags.bytewidth, encode.FILE_IDENTIFIER_LENGTH) 

563 

564 # Convert bytes object file_identifier to an array of 4 8-bit integers, 

565 # and use big-endian to enforce size compliance. 

566 # https://docs.python.org/2/library/struct.html#format-characters 

567 file_identifier = N.struct.unpack(">BBBB", file_identifier) 

568 for i in range(encode.FILE_IDENTIFIER_LENGTH-1, -1, -1): 

569 # Place the bytes of the file_identifer in reverse order: 

570 self.Place(file_identifier[i], N.Uint8Flags) 

571 

572 self.PrependUOffsetTRelative(rootTable) 

573 if sizePrefix: 

574 size = len(self.Bytes) - self.Head() 

575 N.enforce_number(size, N.Int32Flags) 

576 self.PrependInt32(size) 

577 self.finished = True 

578 return self.Head() 

579 

580 def Finish(self, rootTable, file_identifier=None): 

581 """Finish finalizes a buffer, pointing to the given `rootTable`.""" 

582 return self.__Finish(rootTable, False, file_identifier=file_identifier) 

583 

584 def FinishSizePrefixed(self, rootTable, file_identifier=None): 

585 """ 

586 Finish finalizes a buffer, pointing to the given `rootTable`, 

587 with the size prefixed. 

588 """ 

589 return self.__Finish(rootTable, True, file_identifier=file_identifier) 

590 

591 ## @cond FLATBUFFERS_INTERNAL 

592 def Prepend(self, flags, off): 

593 self.Prep(flags.bytewidth, 0) 

594 self.Place(off, flags) 

595 

596 def PrependSlot(self, flags, o, x, d): 

597 if x is not None: 

598 N.enforce_number(x, flags) 

599 if d is not None: 

600 N.enforce_number(d, flags) 

601 if x != d or (self.forceDefaults and d is not None): 

602 self.Prepend(flags, x) 

603 self.Slot(o) 

604 

605 def PrependBoolSlot(self, *args): self.PrependSlot(N.BoolFlags, *args) 

606 

607 def PrependByteSlot(self, *args): self.PrependSlot(N.Uint8Flags, *args) 

608 

609 def PrependUint8Slot(self, *args): self.PrependSlot(N.Uint8Flags, *args) 

610 

611 def PrependUint16Slot(self, *args): self.PrependSlot(N.Uint16Flags, *args) 

612 

613 def PrependUint32Slot(self, *args): self.PrependSlot(N.Uint32Flags, *args) 

614 

615 def PrependUint64Slot(self, *args): self.PrependSlot(N.Uint64Flags, *args) 

616 

617 def PrependInt8Slot(self, *args): self.PrependSlot(N.Int8Flags, *args) 

618 

619 def PrependInt16Slot(self, *args): self.PrependSlot(N.Int16Flags, *args) 

620 

621 def PrependInt32Slot(self, *args): self.PrependSlot(N.Int32Flags, *args) 

622 

623 def PrependInt64Slot(self, *args): self.PrependSlot(N.Int64Flags, *args) 

624 

625 def PrependFloat32Slot(self, *args): self.PrependSlot(N.Float32Flags, 

626 *args) 

627 

628 def PrependFloat64Slot(self, *args): self.PrependSlot(N.Float64Flags, 

629 *args) 

630 

631 def PrependUOffsetTRelativeSlot(self, o, x, d): 

632 """ 

633 PrependUOffsetTRelativeSlot prepends an UOffsetT onto the object at 

634 vtable slot `o`. If value `x` equals default `d`, then the slot will 

635 be set to zero and no other data will be written. 

636 """ 

637 

638 if x != d or self.forceDefaults: 

639 self.PrependUOffsetTRelative(x) 

640 self.Slot(o) 

641 

642 def PrependStructSlot(self, v, x, d): 

643 """ 

644 PrependStructSlot prepends a struct onto the object at vtable slot `o`. 

645 Structs are stored inline, so nothing additional is being added. 

646 In generated code, `d` is always 0. 

647 """ 

648 

649 N.enforce_number(d, N.UOffsetTFlags) 

650 if x != d: 

651 self.assertStructIsInline(x) 

652 self.Slot(v) 

653 

654 ## @endcond 

655 

656 def PrependBool(self, x): 

657 """Prepend a `bool` to the Builder buffer. 

658 

659 Note: aligns and checks for space. 

660 """ 

661 self.Prepend(N.BoolFlags, x) 

662 

663 def PrependByte(self, x): 

664 """Prepend a `byte` to the Builder buffer. 

665 

666 Note: aligns and checks for space. 

667 """ 

668 self.Prepend(N.Uint8Flags, x) 

669 

670 def PrependUint8(self, x): 

671 """Prepend an `uint8` to the Builder buffer. 

672 

673 Note: aligns and checks for space. 

674 """ 

675 self.Prepend(N.Uint8Flags, x) 

676 

677 def PrependUint16(self, x): 

678 """Prepend an `uint16` to the Builder buffer. 

679 

680 Note: aligns and checks for space. 

681 """ 

682 self.Prepend(N.Uint16Flags, x) 

683 

684 def PrependUint32(self, x): 

685 """Prepend an `uint32` to the Builder buffer. 

686 

687 Note: aligns and checks for space. 

688 """ 

689 self.Prepend(N.Uint32Flags, x) 

690 

691 def PrependUint64(self, x): 

692 """Prepend an `uint64` to the Builder buffer. 

693 

694 Note: aligns and checks for space. 

695 """ 

696 self.Prepend(N.Uint64Flags, x) 

697 

698 def PrependInt8(self, x): 

699 """Prepend an `int8` to the Builder buffer. 

700 

701 Note: aligns and checks for space. 

702 """ 

703 self.Prepend(N.Int8Flags, x) 

704 

705 def PrependInt16(self, x): 

706 """Prepend an `int16` to the Builder buffer. 

707 

708 Note: aligns and checks for space. 

709 """ 

710 self.Prepend(N.Int16Flags, x) 

711 

712 def PrependInt32(self, x): 

713 """Prepend an `int32` to the Builder buffer. 

714 

715 Note: aligns and checks for space. 

716 """ 

717 self.Prepend(N.Int32Flags, x) 

718 

719 def PrependInt64(self, x): 

720 """Prepend an `int64` to the Builder buffer. 

721 

722 Note: aligns and checks for space. 

723 """ 

724 self.Prepend(N.Int64Flags, x) 

725 

726 def PrependFloat32(self, x): 

727 """Prepend a `float32` to the Builder buffer. 

728 

729 Note: aligns and checks for space. 

730 """ 

731 self.Prepend(N.Float32Flags, x) 

732 

733 def PrependFloat64(self, x): 

734 """Prepend a `float64` to the Builder buffer. 

735 

736 Note: aligns and checks for space. 

737 """ 

738 self.Prepend(N.Float64Flags, x) 

739 

740 def ForceDefaults(self, forceDefaults): 

741 """ 

742 In order to save space, fields that are set to their default value 

743 don't get serialized into the buffer. Forcing defaults provides a 

744 way to manually disable this optimization. When set to `True`, will 

745 always serialize default values. 

746 """ 

747 self.forceDefaults = forceDefaults 

748 

749############################################################## 

750 

751 ## @cond FLATBUFFERS_INTERNAL 

752 def PrependVOffsetT(self, x): self.Prepend(N.VOffsetTFlags, x) 

753 

754 def Place(self, x, flags): 

755 """ 

756 Place prepends a value specified by `flags` to the Builder, 

757 without checking for available space. 

758 """ 

759 

760 N.enforce_number(x, flags) 

761 self.head = self.head - flags.bytewidth 

762 encode.Write(flags.packer_type, self.Bytes, self.Head(), x) 

763 

764 def PlaceVOffsetT(self, x): 

765 """PlaceVOffsetT prepends a VOffsetT to the Builder, without checking 

766 for space. 

767 """ 

768 N.enforce_number(x, N.VOffsetTFlags) 

769 self.head = self.head - N.VOffsetTFlags.bytewidth 

770 encode.Write(packer.voffset, self.Bytes, self.Head(), x) 

771 

772 def PlaceSOffsetT(self, x): 

773 """PlaceSOffsetT prepends a SOffsetT to the Builder, without checking 

774 for space. 

775 """ 

776 N.enforce_number(x, N.SOffsetTFlags) 

777 self.head = self.head - N.SOffsetTFlags.bytewidth 

778 encode.Write(packer.soffset, self.Bytes, self.Head(), x) 

779 

780 def PlaceUOffsetT(self, x): 

781 """PlaceUOffsetT prepends a UOffsetT to the Builder, without checking 

782 for space. 

783 """ 

784 N.enforce_number(x, N.UOffsetTFlags) 

785 self.head = self.head - N.UOffsetTFlags.bytewidth 

786 encode.Write(packer.uoffset, self.Bytes, self.Head(), x) 

787 ## @endcond 

788 

789## @cond FLATBUFFERS_INTERNAL 

790def vtableEqual(a, objectStart, b): 

791 """vtableEqual compares an unwritten vtable to a written vtable.""" 

792 

793 N.enforce_number(objectStart, N.UOffsetTFlags) 

794 

795 if len(a) * N.VOffsetTFlags.bytewidth != len(b): 

796 return False 

797 

798 for i, elem in enumerate(a): 

799 x = encode.Get(packer.voffset, b, i * N.VOffsetTFlags.bytewidth) 

800 

801 # Skip vtable entries that indicate a default value. 

802 if x == 0 and elem == 0: 

803 pass 

804 else: 

805 y = objectStart - elem 

806 if x != y: 

807 return False 

808 return True 

809## @endcond 

810## @}