| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858 |
- # Copyright 2014 Google Inc. All rights reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import warnings
- from . import compat
- from . import encode
- from . import number_types as N
- from . import packer
- from .compat import memoryview_type
- from .compat import NumpyRequiredForThisFeature, import_numpy
- from .compat import range_func
- from .number_types import (SOffsetTFlags, UOffsetTFlags, VOffsetTFlags)
- np = import_numpy()
- ## @file
- ## @addtogroup flatbuffers_python_api
- ## @{
- ## @cond FLATBUFFERS_INTERNAL
- class OffsetArithmeticError(RuntimeError):
- """Error caused by an Offset arithmetic error.
- Probably caused by bad writing of fields. This is considered an unreachable
- situation in normal circumstances.
- """
- pass
- class IsNotNestedError(RuntimeError):
- """Error caused by using a Builder to write Object data when not inside
- an Object.
- """
- pass
- class IsNestedError(RuntimeError):
- """Error caused by using a Builder to begin an Object when an Object is
- already being built.
- """
- pass
- class StructIsNotInlineError(RuntimeError):
- """Error caused by using a Builder to write a Struct at a location that
- is not the current Offset.
- """
- pass
- class BuilderSizeError(RuntimeError):
- """Error caused by causing a Builder to exceed the hardcoded limit of 2
- gigabytes.
- """
- pass
- class BuilderNotFinishedError(RuntimeError):
- """Error caused by not calling `Finish` before calling `Output`."""
- pass
- class EndVectorLengthMismatched(RuntimeError):
- """The number of elements passed to EndVector does not match the number
- specified in StartVector.
- """
- pass
- # VtableMetadataFields is the count of metadata fields in each vtable.
- VtableMetadataFields = 2
- ## @endcond
- class Builder(object):
- """A Builder is used to construct one or more FlatBuffers.
- Typically, Builder objects will be used from code generated by the `flatc`
- compiler.
- A Builder constructs byte buffers in a last-first manner for simplicity and
- performance during reading.
- Internally, a Builder is a state machine for creating FlatBuffer objects.
- It holds the following internal state:
- - Bytes: an array of bytes.
- - current_vtable: a list of integers.
- - vtables: a hash of vtable entries.
- Attributes:
- Bytes: The internal `bytearray` for the Builder.
- finished: A boolean determining if the Builder has been finalized.
- """
- ## @cond FLATBUFFERS_INTENRAL
- __slots__ = (
- "Bytes",
- "current_vtable",
- "head",
- "minalign",
- "objectEnd",
- "vtables",
- "nested",
- "forceDefaults",
- "finished",
- "vectorNumElems",
- "sharedStrings",
- )
- """Maximum buffer size constant, in bytes.
- Builder will never allow it's buffer grow over this size.
- Currently equals 2Gb.
- """
- MAX_BUFFER_SIZE = 2**31
- ## @endcond
- def __init__(self, initialSize=1024):
- """Initializes a Builder of size `initial_size`.
- The internal buffer is grown as needed.
- """
- if not (0 <= initialSize <= Builder.MAX_BUFFER_SIZE):
- msg = "flatbuffers: Cannot create Builder larger than 2 gigabytes."
- raise BuilderSizeError(msg)
- self.Bytes = bytearray(initialSize)
- ## @cond FLATBUFFERS_INTERNAL
- self.current_vtable = None
- self.head = UOffsetTFlags.py_type(initialSize)
- self.minalign = 1
- self.objectEnd = None
- self.vtables = {}
- self.nested = False
- self.forceDefaults = False
- self.sharedStrings = None
- ## @endcond
- self.finished = False
- def Clear(self):
- ## @cond FLATBUFFERS_INTERNAL
- self.current_vtable = None
- self.head = len(self.Bytes)
- self.minalign = 1
- self.objectEnd = None
- self.vtables = {}
- self.nested = False
- self.forceDefaults = False
- self.sharedStrings = None
- self.vectorNumElems = None
- ## @endcond
- self.finished = False
- def Output(self):
- """Return the portion of the buffer that has been used for writing data.
- This is the typical way to access the FlatBuffer data inside the
- builder. If you try to access `Builder.Bytes` directly, you would need
- to manually index it with `Head()`, since the buffer is constructed
- backwards.
- It raises BuilderNotFinishedError if the buffer has not been finished
- with `Finish`.
- """
- if not self.finished:
- raise BuilderNotFinishedError()
- return self.Bytes[self.head :]
- ## @cond FLATBUFFERS_INTERNAL
- def StartObject(self, numfields):
- """StartObject initializes bookkeeping for writing a new object."""
- self.assertNotNested()
- # use 32-bit offsets so that arithmetic doesn't overflow.
- self.current_vtable = [0] * numfields
- self.objectEnd = self.Offset()
- self.nested = True
- def WriteVtable(self):
- """WriteVtable serializes the vtable for the current object, if needed.
- Before writing out the vtable, this checks pre-existing vtables for
- equality to this one. If an equal vtable is found, point the object to
- the existing vtable and return.
- Because vtable values are sensitive to alignment of object data, not
- all logically-equal vtables will be deduplicated.
- A vtable has the following format:
- <VOffsetT: size of the vtable in bytes, including this value>
- <VOffsetT: size of the object in bytes, including the vtable offset>
- <VOffsetT: offset for a field> * N, where N is the number of fields
- in the schema for this type. Includes deprecated fields.
- Thus, a vtable is made of 2 + N elements, each VOffsetT bytes wide.
- An object has the following format:
- <SOffsetT: offset to this object's vtable (may be negative)>
- <byte: data>+
- """
- # Prepend a zero scalar to the object. Later in this function we'll
- # write an offset here that points to the object's vtable:
- self.PrependSOffsetTRelative(0)
- objectOffset = self.Offset()
- vtKey = []
- trim = True
- for elem in reversed(self.current_vtable):
- if elem == 0:
- if trim:
- continue
- else:
- elem = objectOffset - elem
- trim = False
- vtKey.append(elem)
- objectSize = UOffsetTFlags.py_type(objectOffset - self.objectEnd)
- vtKey.append(objectSize)
- vtKey = tuple(vtKey)
- # calculate the size of the object
- vt2Offset = self.vtables.get(vtKey)
- if vt2Offset is None:
- # Did not find a vtable, so write this one to the buffer.
- # Write out the current vtable in reverse , because
- # serialization occurs in last-first order:
- i = len(self.current_vtable) - 1
- trailing = 0
- trim = True
- while i >= 0:
- off = 0
- elem = self.current_vtable[i]
- i -= 1
- if elem == 0:
- if trim:
- trailing += 1
- continue
- else:
- # Forward reference to field;
- # use 32bit number to ensure no overflow:
- off = objectOffset - elem
- trim = False
- self.PrependVOffsetT(off)
- # The two metadata fields are written last.
- # First, store the object bytesize:
- self.PrependVOffsetT(VOffsetTFlags.py_type(objectSize))
- # Second, store the vtable bytesize:
- vBytes = len(self.current_vtable) - trailing + VtableMetadataFields
- vBytes *= N.VOffsetTFlags.bytewidth
- self.PrependVOffsetT(VOffsetTFlags.py_type(vBytes))
- # Next, write the offset to the new vtable in the
- # already-allocated SOffsetT at the beginning of this object:
- objectStart = SOffsetTFlags.py_type(len(self.Bytes) - objectOffset)
- encode.Write(
- packer.soffset,
- self.Bytes,
- objectStart,
- SOffsetTFlags.py_type(self.Offset() - objectOffset),
- )
- # Finally, store this vtable in memory for future
- # deduplication:
- self.vtables[vtKey] = self.Offset()
- else:
- # Found a duplicate vtable.
- objectStart = SOffsetTFlags.py_type(len(self.Bytes) - objectOffset)
- self.head = UOffsetTFlags.py_type(objectStart)
- # Write the offset to the found vtable in the
- # already-allocated SOffsetT at the beginning of this object:
- encode.Write(
- packer.soffset,
- self.Bytes,
- self.Head(),
- SOffsetTFlags.py_type(vt2Offset - objectOffset),
- )
- self.current_vtable = None
- return objectOffset
- def EndObject(self):
- """EndObject writes data necessary to finish object construction."""
- self.assertNested()
- self.nested = False
- return self.WriteVtable()
- def GrowByteBuffer(self):
- """Doubles the size of the byteslice, and copies the old data towards
- the end of the new buffer (since we build the buffer backwards).
- """
- if len(self.Bytes) == Builder.MAX_BUFFER_SIZE:
- msg = "flatbuffers: cannot grow buffer beyond 2 gigabytes"
- raise BuilderSizeError(msg)
- newSize = min(len(self.Bytes) * 2, Builder.MAX_BUFFER_SIZE)
- if newSize == 0:
- newSize = 1
- bytes2 = bytearray(newSize)
- bytes2[newSize - len(self.Bytes) :] = self.Bytes
- self.Bytes = bytes2
- ## @endcond
- def Head(self):
- """Get the start of useful data in the underlying byte buffer.
- Note: unlike other functions, this value is interpreted as from the
- left.
- """
- ## @cond FLATBUFFERS_INTERNAL
- return self.head
- ## @endcond
- ## @cond FLATBUFFERS_INTERNAL
- def Offset(self):
- """Offset relative to the end of the buffer."""
- return len(self.Bytes) - self.head
- def Pad(self, n):
- """Pad places zeros at the current offset."""
- if n <= 0:
- return
- new_head = self.head - n
- self.Bytes[new_head : self.head] = b"\x00" * n
- self.head = new_head
- def Prep(self, size, additionalBytes):
- """Prep prepares to write an element of `size` after `additional_bytes`
- have been written, e.g. if you write a string, you need to align
- such the int length field is aligned to SizeInt32, and the string
- data follows it directly.
- If all you need to do is align, `additionalBytes` will be 0.
- """
- # Track the biggest thing we've ever aligned to.
- if size > self.minalign:
- self.minalign = size
- # Find the amount of alignment needed such that `size` is properly
- # aligned after `additionalBytes`:
- head = self.head
- buf_len = len(self.Bytes)
- alignSize = (~(buf_len - head + additionalBytes)) + 1
- alignSize &= size - 1
- # Reallocate the buffer if needed:
- needed = alignSize + size + additionalBytes
- while head < needed:
- oldBufSize = buf_len
- self.GrowByteBuffer()
- buf_len = len(self.Bytes)
- head += buf_len - oldBufSize
- self.head = head
- self.Pad(alignSize)
- def PrependSOffsetTRelative(self, off):
- """PrependSOffsetTRelative prepends an SOffsetT, relative to where it
- will be written.
- """
- # Ensure alignment is already done:
- self.Prep(N.SOffsetTFlags.bytewidth, 0)
- if not (off <= self.Offset()):
- msg = "flatbuffers: Offset arithmetic error."
- raise OffsetArithmeticError(msg)
- off2 = self.Offset() - off + N.SOffsetTFlags.bytewidth
- self.PlaceSOffsetT(off2)
- ## @endcond
- def PrependUOffsetTRelative(self, off):
- """Prepends an unsigned offset into vector data, relative to where it
- will be written.
- """
- # Ensure alignment is already done:
- self.Prep(N.UOffsetTFlags.bytewidth, 0)
- if not (off <= self.Offset()):
- msg = "flatbuffers: Offset arithmetic error."
- raise OffsetArithmeticError(msg)
- off2 = self.Offset() - off + N.UOffsetTFlags.bytewidth
- self.PlaceUOffsetT(off2)
- ## @cond FLATBUFFERS_INTERNAL
- def StartVector(self, elemSize, numElems, alignment):
- """StartVector initializes bookkeeping for writing a new vector.
- A vector has the following format:
- - <UOffsetT: number of elements in this vector>
- - <T: data>+, where T is the type of elements of this vector.
- """
- self.assertNotNested()
- self.nested = True
- self.vectorNumElems = numElems
- self.Prep(N.Uint32Flags.bytewidth, elemSize * numElems)
- self.Prep(alignment, elemSize * numElems) # In case alignment > int.
- return self.Offset()
- ## @endcond
- def EndVector(self, numElems=None):
- """EndVector writes data necessary to finish vector construction."""
- self.assertNested()
- ## @cond FLATBUFFERS_INTERNAL
- self.nested = False
- ## @endcond
- if numElems:
- warnings.warn("numElems is deprecated.", DeprecationWarning, stacklevel=2)
- if numElems != self.vectorNumElems:
- raise EndVectorLengthMismatched()
- # we already made space for this, so write without PrependUint32
- self.PlaceUOffsetT(self.vectorNumElems)
- self.vectorNumElems = None
- return self.Offset()
- def CreateSharedString(self, s, encoding="utf-8", errors="strict"):
- """CreateSharedString checks if the string is already written to the buffer
- before calling CreateString.
- """
- if not self.sharedStrings:
- self.sharedStrings = {}
- elif s in self.sharedStrings:
- return self.sharedStrings[s]
- off = self.CreateString(s, encoding, errors)
- self.sharedStrings[s] = off
- return off
- def CreateString(self, s, encoding="utf-8", errors="strict"):
- """CreateString writes a null-terminated byte string as a vector."""
- self.assertNotNested()
- ## @cond FLATBUFFERS_INTERNAL
- self.nested = True
- ## @endcond
- if isinstance(s, compat.string_types):
- x = s.encode(encoding, errors)
- elif isinstance(s, compat.binary_types):
- x = s
- else:
- raise TypeError("non-string passed to CreateString")
- payload_len = len(x)
- self.Prep(N.UOffsetTFlags.bytewidth, (payload_len + 1) * N.Uint8Flags.bytewidth)
- self.Place(0, N.Uint8Flags)
- new_head = self.head - payload_len
- self.head = new_head
- self.Bytes[new_head : new_head + payload_len] = x
- self.vectorNumElems = payload_len
- return self.EndVector()
- def CreateByteVector(self, x):
- """CreateString writes a byte vector."""
- self.assertNotNested()
- ## @cond FLATBUFFERS_INTERNAL
- self.nested = True
- ## @endcond
- if not isinstance(x, compat.binary_types):
- raise TypeError("non-byte vector passed to CreateByteVector")
- data_len = len(x)
- self.Prep(N.UOffsetTFlags.bytewidth, data_len * N.Uint8Flags.bytewidth)
- new_head = self.head - data_len
- self.head = new_head
- self.Bytes[new_head : new_head + data_len] = x
- self.vectorNumElems = data_len
- return self.EndVector()
- def CreateNumpyVector(self, x):
- """CreateNumpyVector writes a numpy array into the buffer."""
- if np is None:
- # Numpy is required for this feature
- raise NumpyRequiredForThisFeature("Numpy was not found.")
- if not isinstance(x, np.ndarray):
- raise TypeError("non-numpy-ndarray passed to CreateNumpyVector")
- if x.dtype.kind not in ["b", "i", "u", "f"]:
- raise TypeError("numpy-ndarray holds elements of unsupported datatype")
- if x.ndim > 1:
- raise TypeError("multidimensional-ndarray passed to CreateNumpyVector")
- self.StartVector(x.itemsize, x.size, x.dtype.alignment)
- # Ensure little endian byte ordering
- if x.dtype.str[0] == "<":
- x_lend = x
- else:
- x_lend = x.byteswap(inplace=False)
- # tobytes ensures c_contiguous ordering
- payload = x_lend.tobytes(order="C")
- # Calculate total length
- payload_len = len(payload)
- new_head = self.head - payload_len
- self.head = new_head
- self.Bytes[new_head : new_head + payload_len] = payload
- self.vectorNumElems = x.size
- return self.EndVector()
- ## @cond FLATBUFFERS_INTERNAL
- def assertNested(self):
- """Check that we are in the process of building an object."""
- if not self.nested:
- raise IsNotNestedError()
- def assertNotNested(self):
- """Check that no other objects are being built while making this object.
- If not, raise an exception.
- """
- if self.nested:
- raise IsNestedError()
- def assertStructIsInline(self, obj):
- """Structs are always stored inline, so need to be created right
- where they are used. You'll get this error if you created it
- elsewhere.
- """
- N.enforce_number(obj, N.UOffsetTFlags)
- if obj != self.Offset():
- msg = (
- "flatbuffers: Tried to write a Struct at an Offset that "
- "is different from the current Offset of the Builder."
- )
- raise StructIsNotInlineError(msg)
- def Slot(self, slotnum):
- """Slot sets the vtable key `voffset` to the current location in the
- buffer.
- """
- self.assertNested()
- self.current_vtable[slotnum] = self.Offset()
- ## @endcond
- def __Finish(self, rootTable, sizePrefix, file_identifier=None):
- """Finish finalizes a buffer, pointing to the given `rootTable`."""
- N.enforce_number(rootTable, N.UOffsetTFlags)
- prepSize = N.UOffsetTFlags.bytewidth
- if file_identifier is not None:
- prepSize += N.Int32Flags.bytewidth
- if sizePrefix:
- prepSize += N.Int32Flags.bytewidth
- self.Prep(self.minalign, prepSize)
- if file_identifier is not None:
- self.Prep(N.UOffsetTFlags.bytewidth, encode.FILE_IDENTIFIER_LENGTH)
- # Convert bytes object file_identifier to an array of 4 8-bit integers,
- # and use big-endian to enforce size compliance.
- # https://docs.python.org/2/library/struct.html#format-characters
- file_identifier = N.struct.unpack(">BBBB", file_identifier)
- for i in range(encode.FILE_IDENTIFIER_LENGTH - 1, -1, -1):
- # Place the bytes of the file_identifer in reverse order:
- self.Place(file_identifier[i], N.Uint8Flags)
- self.PrependUOffsetTRelative(rootTable)
- if sizePrefix:
- size = len(self.Bytes) - self.head
- N.enforce_number(size, N.Int32Flags)
- self.PrependInt32(size)
- self.finished = True
- return self.head
- def Finish(self, rootTable, file_identifier=None):
- """Finish finalizes a buffer, pointing to the given `rootTable`."""
- return self.__Finish(rootTable, False, file_identifier=file_identifier)
- def FinishSizePrefixed(self, rootTable, file_identifier=None):
- """Finish finalizes a buffer, pointing to the given `rootTable`,
- with the size prefixed.
- """
- return self.__Finish(rootTable, True, file_identifier=file_identifier)
- ## @cond FLATBUFFERS_INTERNAL
- def Prepend(self, flags, off):
- self.Prep(flags.bytewidth, 0)
- self.Place(off, flags)
- def PrependSlot(self, flags, o, x, d):
- if x is not None:
- N.enforce_number(x, flags)
- if d is not None:
- N.enforce_number(d, flags)
- if x != d or (self.forceDefaults and d is not None):
- self.Prepend(flags, x)
- self.Slot(o)
- def PrependBoolSlot(self, *args):
- self.PrependSlot(N.BoolFlags, *args)
- def PrependByteSlot(self, *args):
- self.PrependSlot(N.Uint8Flags, *args)
- def PrependUint8Slot(self, *args):
- self.PrependSlot(N.Uint8Flags, *args)
- def PrependUint16Slot(self, *args):
- self.PrependSlot(N.Uint16Flags, *args)
- def PrependUint32Slot(self, *args):
- self.PrependSlot(N.Uint32Flags, *args)
- def PrependUint64Slot(self, *args):
- self.PrependSlot(N.Uint64Flags, *args)
- def PrependInt8Slot(self, *args):
- self.PrependSlot(N.Int8Flags, *args)
- def PrependInt16Slot(self, *args):
- self.PrependSlot(N.Int16Flags, *args)
- def PrependInt32Slot(self, *args):
- self.PrependSlot(N.Int32Flags, *args)
- def PrependInt64Slot(self, *args):
- self.PrependSlot(N.Int64Flags, *args)
- def PrependFloat32Slot(self, *args):
- self.PrependSlot(N.Float32Flags, *args)
- def PrependFloat64Slot(self, *args):
- self.PrependSlot(N.Float64Flags, *args)
- def PrependUOffsetTRelativeSlot(self, o, x, d):
- """PrependUOffsetTRelativeSlot prepends an UOffsetT onto the object at
- vtable slot `o`. If value `x` equals default `d`, then the slot will
- be set to zero and no other data will be written.
- """
- if x != d or self.forceDefaults:
- self.PrependUOffsetTRelative(x)
- self.Slot(o)
- def PrependStructSlot(self, v, x, d):
- """PrependStructSlot prepends a struct onto the object at vtable slot `o`.
- Structs are stored inline, so nothing additional is being added. In
- generated code, `d` is always 0.
- """
- N.enforce_number(d, N.UOffsetTFlags)
- if x != d:
- self.assertStructIsInline(x)
- self.Slot(v)
- ## @endcond
- def PrependBool(self, x):
- """Prepend a `bool` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.BoolFlags, x)
- def PrependByte(self, x):
- """Prepend a `byte` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Uint8Flags, x)
- def PrependUint8(self, x):
- """Prepend an `uint8` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Uint8Flags, x)
- def PrependUint16(self, x):
- """Prepend an `uint16` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Uint16Flags, x)
- def PrependUint32(self, x):
- """Prepend an `uint32` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Uint32Flags, x)
- def PrependUint64(self, x):
- """Prepend an `uint64` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Uint64Flags, x)
- def PrependInt8(self, x):
- """Prepend an `int8` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Int8Flags, x)
- def PrependInt16(self, x):
- """Prepend an `int16` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Int16Flags, x)
- def PrependInt32(self, x):
- """Prepend an `int32` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Int32Flags, x)
- def PrependInt64(self, x):
- """Prepend an `int64` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Int64Flags, x)
- def PrependFloat32(self, x):
- """Prepend a `float32` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Float32Flags, x)
- def PrependFloat64(self, x):
- """Prepend a `float64` to the Builder buffer.
- Note: aligns and checks for space.
- """
- self.Prepend(N.Float64Flags, x)
- def ForceDefaults(self, forceDefaults):
- """In order to save space, fields that are set to their default value
- don't get serialized into the buffer. Forcing defaults provides a
- way to manually disable this optimization. When set to `True`, will
- always serialize default values.
- """
- self.forceDefaults = forceDefaults
- ##############################################################
- ## @cond FLATBUFFERS_INTERNAL
- def PrependVOffsetT(self, x):
- self.Prepend(N.VOffsetTFlags, x)
- def Place(self, x, flags):
- """Place prepends a value specified by `flags` to the Builder,
- without checking for available space.
- """
- N.enforce_number(x, flags)
- new_head = self.head - flags.bytewidth
- self.head = new_head
- encode.Write(flags.packer_type, self.Bytes, new_head, x)
- def PlaceVOffsetT(self, x):
- """PlaceVOffsetT prepends a VOffsetT to the Builder, without checking
- for space.
- """
- N.enforce_number(x, N.VOffsetTFlags)
- new_head = self.head - N.VOffsetTFlags.bytewidth
- self.head = new_head
- encode.Write(packer.voffset, self.Bytes, new_head, x)
- def PlaceSOffsetT(self, x):
- """PlaceSOffsetT prepends a SOffsetT to the Builder, without checking
- for space.
- """
- N.enforce_number(x, N.SOffsetTFlags)
- new_head = self.head - N.SOffsetTFlags.bytewidth
- self.head = new_head
- encode.Write(packer.soffset, self.Bytes, new_head, x)
- def PlaceUOffsetT(self, x):
- """PlaceUOffsetT prepends a UOffsetT to the Builder, without checking
- for space.
- """
- N.enforce_number(x, N.UOffsetTFlags)
- new_head = self.head - N.UOffsetTFlags.bytewidth
- self.head = new_head
- encode.Write(packer.uoffset, self.Bytes, new_head, x)
- ## @endcond
- ## @}
|