Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
builder.py859 linesDownload Raw Back to flatbuffers
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 at6#7#     http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# 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 and13# limitations under the License.14 15import warnings16 17from . import compat18from . import encode19from . import number_types as N20from . import packer21from .compat import memoryview_type22from .compat import NumpyRequiredForThisFeature, import_numpy23from .compat import range_func24from .number_types import (SOffsetTFlags, UOffsetTFlags, VOffsetTFlags)25 26np = import_numpy()27## @file28## @addtogroup flatbuffers_python_api29## @{30 31 32## @cond FLATBUFFERS_INTERNAL33class OffsetArithmeticError(RuntimeError):34  """Error caused by an Offset arithmetic error.35 36  Probably caused by bad writing of fields. This is considered an unreachable37  situation in normal circumstances.38  """39 40  pass41 42 43class IsNotNestedError(RuntimeError):44  """Error caused by using a Builder to write Object data when not inside45 46  an Object.47  """48 49  pass50 51 52class IsNestedError(RuntimeError):53  """Error caused by using a Builder to begin an Object when an Object is54 55  already being built.56  """57 58  pass59 60 61class StructIsNotInlineError(RuntimeError):62  """Error caused by using a Builder to write a Struct at a location that63 64  is not the current Offset.65  """66 67  pass68 69 70class BuilderSizeError(RuntimeError):71  """Error caused by causing a Builder to exceed the hardcoded limit of 272 73  gigabytes.74  """75 76  pass77 78 79class BuilderNotFinishedError(RuntimeError):80  """Error caused by not calling `Finish` before calling `Output`."""81 82  pass83 84 85class EndVectorLengthMismatched(RuntimeError):86  """The number of elements passed to EndVector does not match the number87 88  specified in StartVector.89  """90 91  pass92 93 94# VtableMetadataFields is the count of metadata fields in each vtable.95VtableMetadataFields = 296## @endcond97 98 99class Builder(object):100  """A Builder is used to construct one or more FlatBuffers.101 102  Typically, Builder objects will be used from code generated by the `flatc`103  compiler.104 105  A Builder constructs byte buffers in a last-first manner for simplicity and106  performance during reading.107 108  Internally, a Builder is a state machine for creating FlatBuffer objects.109 110  It holds the following internal state:111      - Bytes: an array of bytes.112      - current_vtable: a list of integers.113      - vtables: a hash of vtable entries.114 115  Attributes:116    Bytes: The internal `bytearray` for the Builder.117    finished: A boolean determining if the Builder has been finalized.118  """119 120  ## @cond FLATBUFFERS_INTENRAL121  __slots__ = (122      "Bytes",123      "current_vtable",124      "head",125      "minalign",126      "objectEnd",127      "vtables",128      "nested",129      "forceDefaults",130      "finished",131      "vectorNumElems",132      "sharedStrings",133  )134 135  """Maximum buffer size constant, in bytes.136 137    Builder will never allow it's buffer grow over this size.138    Currently equals 2Gb.139    """140  MAX_BUFFER_SIZE = 2**31141  ## @endcond142 143  def __init__(self, initialSize=1024):144    """Initializes a Builder of size `initial_size`.145 146    The internal buffer is grown as needed.147    """148 149    if not (0 <= initialSize <= Builder.MAX_BUFFER_SIZE):150      msg = "flatbuffers: Cannot create Builder larger than 2 gigabytes."151      raise BuilderSizeError(msg)152 153    self.Bytes = bytearray(initialSize)154    ## @cond FLATBUFFERS_INTERNAL155    self.current_vtable = None156    self.head = UOffsetTFlags.py_type(initialSize)157    self.minalign = 1158    self.objectEnd = None159    self.vtables = {}160    self.nested = False161    self.forceDefaults = False162    self.sharedStrings = None163    ## @endcond164    self.finished = False165 166  def Clear(self):167    ## @cond FLATBUFFERS_INTERNAL168    self.current_vtable = None169    self.head = len(self.Bytes)170    self.minalign = 1171    self.objectEnd = None172    self.vtables = {}173    self.nested = False174    self.forceDefaults = False175    self.sharedStrings = None176    self.vectorNumElems = None177    ## @endcond178    self.finished = False179 180  def Output(self):181    """Return the portion of the buffer that has been used for writing data.182 183    This is the typical way to access the FlatBuffer data inside the184    builder. If you try to access `Builder.Bytes` directly, you would need185    to manually index it with `Head()`, since the buffer is constructed186    backwards.187 188    It raises BuilderNotFinishedError if the buffer has not been finished189    with `Finish`.190    """191 192    if not self.finished:193      raise BuilderNotFinishedError()194 195    return self.Bytes[self.head :]196 197  ## @cond FLATBUFFERS_INTERNAL198  def StartObject(self, numfields):199    """StartObject initializes bookkeeping for writing a new object."""200 201    self.assertNotNested()202 203    # use 32-bit offsets so that arithmetic doesn't overflow.204    self.current_vtable = [0] * numfields205    self.objectEnd = self.Offset()206    self.nested = True207 208  def WriteVtable(self):209    """WriteVtable serializes the vtable for the current object, if needed.210 211    Before writing out the vtable, this checks pre-existing vtables for212    equality to this one. If an equal vtable is found, point the object to213    the existing vtable and return.214 215    Because vtable values are sensitive to alignment of object data, not216    all logically-equal vtables will be deduplicated.217 218    A vtable has the following format:219      <VOffsetT: size of the vtable in bytes, including this value>220      <VOffsetT: size of the object in bytes, including the vtable offset>221      <VOffsetT: offset for a field> * N, where N is the number of fields222                 in the schema for this type. Includes deprecated fields.223    Thus, a vtable is made of 2 + N elements, each VOffsetT bytes wide.224 225    An object has the following format:226      <SOffsetT: offset to this object's vtable (may be negative)>227      <byte: data>+228    """229 230    # Prepend a zero scalar to the object. Later in this function we'll231    # write an offset here that points to the object's vtable:232    self.PrependSOffsetTRelative(0)233 234    objectOffset = self.Offset()235 236    vtKey = []237    trim = True238    for elem in reversed(self.current_vtable):239      if elem == 0:240        if trim:241          continue242      else:243        elem = objectOffset - elem244        trim = False245 246      vtKey.append(elem)247 248    objectSize = UOffsetTFlags.py_type(objectOffset - self.objectEnd)249    vtKey.append(objectSize)250    vtKey = tuple(vtKey)251    # calculate the size of the object252    vt2Offset = self.vtables.get(vtKey)253    if vt2Offset is None:254      # Did not find a vtable, so write this one to the buffer.255 256      # Write out the current vtable in reverse , because257      # serialization occurs in last-first order:258      i = len(self.current_vtable) - 1259      trailing = 0260      trim = True261      while i >= 0:262        off = 0263        elem = self.current_vtable[i]264        i -= 1265 266        if elem == 0:267          if trim:268            trailing += 1269            continue270        else:271          # Forward reference to field;272          # use 32bit number to ensure no overflow:273          off = objectOffset - elem274          trim = False275 276        self.PrependVOffsetT(off)277 278      # The two metadata fields are written last.279 280      # First, store the object bytesize:281      self.PrependVOffsetT(VOffsetTFlags.py_type(objectSize))282 283      # Second, store the vtable bytesize:284      vBytes = len(self.current_vtable) - trailing + VtableMetadataFields285      vBytes *= N.VOffsetTFlags.bytewidth286      self.PrependVOffsetT(VOffsetTFlags.py_type(vBytes))287 288      # Next, write the offset to the new vtable in the289      # already-allocated SOffsetT at the beginning of this object:290      objectStart = SOffsetTFlags.py_type(len(self.Bytes) - objectOffset)291      encode.Write(292          packer.soffset,293          self.Bytes,294          objectStart,295          SOffsetTFlags.py_type(self.Offset() - objectOffset),296      )297 298      # Finally, store this vtable in memory for future299      # deduplication:300      self.vtables[vtKey] = self.Offset()301    else:302      # Found a duplicate vtable.303      objectStart = SOffsetTFlags.py_type(len(self.Bytes) - objectOffset)304      self.head = UOffsetTFlags.py_type(objectStart)305 306      # Write the offset to the found vtable in the307      # already-allocated SOffsetT at the beginning of this object:308      encode.Write(309          packer.soffset,310          self.Bytes,311          self.Head(),312          SOffsetTFlags.py_type(vt2Offset - objectOffset),313      )314 315    self.current_vtable = None316    return objectOffset317 318  def EndObject(self):319    """EndObject writes data necessary to finish object construction."""320    self.assertNested()321    self.nested = False322    return self.WriteVtable()323 324  def GrowByteBuffer(self):325    """Doubles the size of the byteslice, and copies the old data towards326 327    the end of the new buffer (since we build the buffer backwards).328    """329    if len(self.Bytes) == Builder.MAX_BUFFER_SIZE:330      msg = "flatbuffers: cannot grow buffer beyond 2 gigabytes"331      raise BuilderSizeError(msg)332 333    newSize = min(len(self.Bytes) * 2, Builder.MAX_BUFFER_SIZE)334    if newSize == 0:335      newSize = 1336    bytes2 = bytearray(newSize)337    bytes2[newSize - len(self.Bytes) :] = self.Bytes338    self.Bytes = bytes2339 340  ## @endcond341 342  def Head(self):343    """Get the start of useful data in the underlying byte buffer.344 345    Note: unlike other functions, this value is interpreted as from the346    left.347    """348    ## @cond FLATBUFFERS_INTERNAL349    return self.head350    ## @endcond351 352  ## @cond FLATBUFFERS_INTERNAL353  def Offset(self):354    """Offset relative to the end of the buffer."""355    return len(self.Bytes) - self.head356 357  def Pad(self, n):358    """Pad places zeros at the current offset."""359    if n <= 0:360      return361    new_head = self.head - n362    self.Bytes[new_head : self.head] = b"\x00" * n363    self.head = new_head364 365  def Prep(self, size, additionalBytes):366    """Prep prepares to write an element of `size` after `additional_bytes`367 368    have been written, e.g. if you write a string, you need to align369    such the int length field is aligned to SizeInt32, and the string370    data follows it directly.371    If all you need to do is align, `additionalBytes` will be 0.372    """373 374    # Track the biggest thing we've ever aligned to.375    if size > self.minalign:376      self.minalign = size377 378    # Find the amount of alignment needed such that `size` is properly379    # aligned after `additionalBytes`:380    head = self.head381    buf_len = len(self.Bytes)382    alignSize = (~(buf_len - head + additionalBytes)) + 1383    alignSize &= size - 1384 385    # Reallocate the buffer if needed:386    needed = alignSize + size + additionalBytes387    while head < needed:388      oldBufSize = buf_len389      self.GrowByteBuffer()390      buf_len = len(self.Bytes)391      head += buf_len - oldBufSize392    self.head = head393    self.Pad(alignSize)394 395  def PrependSOffsetTRelative(self, off):396    """PrependSOffsetTRelative prepends an SOffsetT, relative to where it397 398    will be written.399    """400 401    # Ensure alignment is already done:402    self.Prep(N.SOffsetTFlags.bytewidth, 0)403    if not (off <= self.Offset()):404      msg = "flatbuffers: Offset arithmetic error."405      raise OffsetArithmeticError(msg)406    off2 = self.Offset() - off + N.SOffsetTFlags.bytewidth407    self.PlaceSOffsetT(off2)408 409  ## @endcond410 411  def PrependUOffsetTRelative(self, off):412    """Prepends an unsigned offset into vector data, relative to where it413 414    will be written.415    """416 417    # Ensure alignment is already done:418    self.Prep(N.UOffsetTFlags.bytewidth, 0)419    if not (off <= self.Offset()):420      msg = "flatbuffers: Offset arithmetic error."421      raise OffsetArithmeticError(msg)422    off2 = self.Offset() - off + N.UOffsetTFlags.bytewidth423    self.PlaceUOffsetT(off2)424 425  ## @cond FLATBUFFERS_INTERNAL426  def StartVector(self, elemSize, numElems, alignment):427    """StartVector initializes bookkeeping for writing a new vector.428 429    A vector has the following format:430      - <UOffsetT: number of elements in this vector>431      - <T: data>+, where T is the type of elements of this vector.432    """433 434    self.assertNotNested()435    self.nested = True436    self.vectorNumElems = numElems437    self.Prep(N.Uint32Flags.bytewidth, elemSize * numElems)438    self.Prep(alignment, elemSize * numElems)  # In case alignment > int.439    return self.Offset()440 441  ## @endcond442 443  def EndVector(self, numElems=None):444    """EndVector writes data necessary to finish vector construction."""445 446    self.assertNested()447    ## @cond FLATBUFFERS_INTERNAL448    self.nested = False449    ## @endcond450 451    if numElems:452      warnings.warn("numElems is deprecated.", DeprecationWarning, stacklevel=2)453      if numElems != self.vectorNumElems:454        raise EndVectorLengthMismatched()455 456    # we already made space for this, so write without PrependUint32457    self.PlaceUOffsetT(self.vectorNumElems)458    self.vectorNumElems = None459    return self.Offset()460 461  def CreateSharedString(self, s, encoding="utf-8", errors="strict"):462    """CreateSharedString checks if the string is already written to the buffer463 464    before calling CreateString.465    """466 467    if not self.sharedStrings:468      self.sharedStrings = {}469    elif s in self.sharedStrings:470      return self.sharedStrings[s]471 472    off = self.CreateString(s, encoding, errors)473    self.sharedStrings[s] = off474 475    return off476 477  def CreateString(self, s, encoding="utf-8", errors="strict"):478    """CreateString writes a null-terminated byte string as a vector."""479 480    self.assertNotNested()481    ## @cond FLATBUFFERS_INTERNAL482    self.nested = True483    ## @endcond484 485    if isinstance(s, compat.string_types):486      x = s.encode(encoding, errors)487    elif isinstance(s, compat.binary_types):488      x = s489    else:490      raise TypeError("non-string passed to CreateString")491 492    payload_len = len(x)493    self.Prep(N.UOffsetTFlags.bytewidth, (payload_len + 1) * N.Uint8Flags.bytewidth)494    self.Place(0, N.Uint8Flags)495 496    new_head = self.head - payload_len497    self.head = new_head498    self.Bytes[new_head : new_head + payload_len] = x499 500    self.vectorNumElems = payload_len501    return self.EndVector()502 503  def CreateByteVector(self, x):504    """CreateString writes a byte vector."""505 506    self.assertNotNested()507    ## @cond FLATBUFFERS_INTERNAL508    self.nested = True509    ## @endcond510 511    if not isinstance(x, compat.binary_types):512      raise TypeError("non-byte vector passed to CreateByteVector")513 514    data_len = len(x)515    self.Prep(N.UOffsetTFlags.bytewidth, data_len * N.Uint8Flags.bytewidth)516    new_head = self.head - data_len517    self.head = new_head518    self.Bytes[new_head : new_head + data_len] = x519 520    self.vectorNumElems = data_len521    return self.EndVector()522 523  def CreateNumpyVector(self, x):524    """CreateNumpyVector writes a numpy array into the buffer."""525 526    if np is None:527      # Numpy is required for this feature528      raise NumpyRequiredForThisFeature("Numpy was not found.")529 530    if not isinstance(x, np.ndarray):531      raise TypeError("non-numpy-ndarray passed to CreateNumpyVector")532 533    if x.dtype.kind not in ["b", "i", "u", "f"]:534      raise TypeError("numpy-ndarray holds elements of unsupported datatype")535 536    if x.ndim > 1:537      raise TypeError("multidimensional-ndarray passed to CreateNumpyVector")538 539    self.StartVector(x.itemsize, x.size, x.dtype.alignment)540 541    # Ensure little endian byte ordering542    if x.dtype.str[0] == "<":543      x_lend = x544    else:545      x_lend = x.byteswap(inplace=False)546 547    # tobytes ensures c_contiguous ordering548    payload = x_lend.tobytes(order="C")549 550    # Calculate total length551    payload_len = len(payload)552    new_head = self.head - payload_len553    self.head = new_head554    self.Bytes[new_head : new_head + payload_len] = payload555 556    self.vectorNumElems = x.size557    return self.EndVector()558 559  ## @cond FLATBUFFERS_INTERNAL560  def assertNested(self):561    """Check that we are in the process of building an object."""562 563    if not self.nested:564      raise IsNotNestedError()565 566  def assertNotNested(self):567    """Check that no other objects are being built while making this object.568 569    If not, raise an exception.570    """571 572    if self.nested:573      raise IsNestedError()574 575  def assertStructIsInline(self, obj):576    """Structs are always stored inline, so need to be created right577 578    where they are used. You'll get this error if you created it579    elsewhere.580    """581 582    N.enforce_number(obj, N.UOffsetTFlags)583    if obj != self.Offset():584      msg = (585          "flatbuffers: Tried to write a Struct at an Offset that "586          "is different from the current Offset of the Builder."587      )588      raise StructIsNotInlineError(msg)589 590  def Slot(self, slotnum):591    """Slot sets the vtable key `voffset` to the current location in the592 593    buffer.594    """595    self.assertNested()596    self.current_vtable[slotnum] = self.Offset()597 598  ## @endcond599 600  def __Finish(self, rootTable, sizePrefix, file_identifier=None):601    """Finish finalizes a buffer, pointing to the given `rootTable`."""602    N.enforce_number(rootTable, N.UOffsetTFlags)603 604    prepSize = N.UOffsetTFlags.bytewidth605    if file_identifier is not None:606      prepSize += N.Int32Flags.bytewidth607    if sizePrefix:608      prepSize += N.Int32Flags.bytewidth609    self.Prep(self.minalign, prepSize)610 611    if file_identifier is not None:612      self.Prep(N.UOffsetTFlags.bytewidth, encode.FILE_IDENTIFIER_LENGTH)613 614      # Convert bytes object file_identifier to an array of 4 8-bit integers,615      # and use big-endian to enforce size compliance.616      # https://docs.python.org/2/library/struct.html#format-characters617      file_identifier = N.struct.unpack(">BBBB", file_identifier)618      for i in range(encode.FILE_IDENTIFIER_LENGTH - 1, -1, -1):619        # Place the bytes of the file_identifer in reverse order:620        self.Place(file_identifier[i], N.Uint8Flags)621 622    self.PrependUOffsetTRelative(rootTable)623    if sizePrefix:624      size = len(self.Bytes) - self.head625      N.enforce_number(size, N.Int32Flags)626      self.PrependInt32(size)627    self.finished = True628    return self.head629 630  def Finish(self, rootTable, file_identifier=None):631    """Finish finalizes a buffer, pointing to the given `rootTable`."""632    return self.__Finish(rootTable, False, file_identifier=file_identifier)633 634  def FinishSizePrefixed(self, rootTable, file_identifier=None):635    """Finish finalizes a buffer, pointing to the given `rootTable`,636 637    with the size prefixed.638    """639    return self.__Finish(rootTable, True, file_identifier=file_identifier)640 641  ## @cond FLATBUFFERS_INTERNAL642  def Prepend(self, flags, off):643    self.Prep(flags.bytewidth, 0)644    self.Place(off, flags)645 646  def PrependSlot(self, flags, o, x, d):647    if x is not None:648      N.enforce_number(x, flags)649    if d is not None:650      N.enforce_number(d, flags)651    if x != d or (self.forceDefaults and d is not None):652      self.Prepend(flags, x)653      self.Slot(o)654 655  def PrependBoolSlot(self, *args):656    self.PrependSlot(N.BoolFlags, *args)657 658  def PrependByteSlot(self, *args):659    self.PrependSlot(N.Uint8Flags, *args)660 661  def PrependUint8Slot(self, *args):662    self.PrependSlot(N.Uint8Flags, *args)663 664  def PrependUint16Slot(self, *args):665    self.PrependSlot(N.Uint16Flags, *args)666 667  def PrependUint32Slot(self, *args):668    self.PrependSlot(N.Uint32Flags, *args)669 670  def PrependUint64Slot(self, *args):671    self.PrependSlot(N.Uint64Flags, *args)672 673  def PrependInt8Slot(self, *args):674    self.PrependSlot(N.Int8Flags, *args)675 676  def PrependInt16Slot(self, *args):677    self.PrependSlot(N.Int16Flags, *args)678 679  def PrependInt32Slot(self, *args):680    self.PrependSlot(N.Int32Flags, *args)681 682  def PrependInt64Slot(self, *args):683    self.PrependSlot(N.Int64Flags, *args)684 685  def PrependFloat32Slot(self, *args):686    self.PrependSlot(N.Float32Flags, *args)687 688  def PrependFloat64Slot(self, *args):689    self.PrependSlot(N.Float64Flags, *args)690 691  def PrependUOffsetTRelativeSlot(self, o, x, d):692    """PrependUOffsetTRelativeSlot prepends an UOffsetT onto the object at693 694    vtable slot `o`. If value `x` equals default `d`, then the slot will695    be set to zero and no other data will be written.696    """697 698    if x != d or self.forceDefaults:699      self.PrependUOffsetTRelative(x)700      self.Slot(o)701 702  def PrependStructSlot(self, v, x, d):703    """PrependStructSlot prepends a struct onto the object at vtable slot `o`.704 705    Structs are stored inline, so nothing additional is being added. In706    generated code, `d` is always 0.707    """708 709    N.enforce_number(d, N.UOffsetTFlags)710    if x != d:711      self.assertStructIsInline(x)712      self.Slot(v)713 714  ## @endcond715 716  def PrependBool(self, x):717    """Prepend a `bool` to the Builder buffer.718 719    Note: aligns and checks for space.720    """721    self.Prepend(N.BoolFlags, x)722 723  def PrependByte(self, x):724    """Prepend a `byte` to the Builder buffer.725 726    Note: aligns and checks for space.727    """728    self.Prepend(N.Uint8Flags, x)729 730  def PrependUint8(self, x):731    """Prepend an `uint8` to the Builder buffer.732 733    Note: aligns and checks for space.734    """735    self.Prepend(N.Uint8Flags, x)736 737  def PrependUint16(self, x):738    """Prepend an `uint16` to the Builder buffer.739 740    Note: aligns and checks for space.741    """742    self.Prepend(N.Uint16Flags, x)743 744  def PrependUint32(self, x):745    """Prepend an `uint32` to the Builder buffer.746 747    Note: aligns and checks for space.748    """749    self.Prepend(N.Uint32Flags, x)750 751  def PrependUint64(self, x):752    """Prepend an `uint64` to the Builder buffer.753 754    Note: aligns and checks for space.755    """756    self.Prepend(N.Uint64Flags, x)757 758  def PrependInt8(self, x):759    """Prepend an `int8` to the Builder buffer.760 761    Note: aligns and checks for space.762    """763    self.Prepend(N.Int8Flags, x)764 765  def PrependInt16(self, x):766    """Prepend an `int16` to the Builder buffer.767 768    Note: aligns and checks for space.769    """770    self.Prepend(N.Int16Flags, x)771 772  def PrependInt32(self, x):773    """Prepend an `int32` to the Builder buffer.774 775    Note: aligns and checks for space.776    """777    self.Prepend(N.Int32Flags, x)778 779  def PrependInt64(self, x):780    """Prepend an `int64` to the Builder buffer.781 782    Note: aligns and checks for space.783    """784    self.Prepend(N.Int64Flags, x)785 786  def PrependFloat32(self, x):787    """Prepend a `float32` to the Builder buffer.788 789    Note: aligns and checks for space.790    """791    self.Prepend(N.Float32Flags, x)792 793  def PrependFloat64(self, x):794    """Prepend a `float64` to the Builder buffer.795 796    Note: aligns and checks for space.797    """798    self.Prepend(N.Float64Flags, x)799 800  def ForceDefaults(self, forceDefaults):801    """In order to save space, fields that are set to their default value802 803    don't get serialized into the buffer. Forcing defaults provides a804    way to manually disable this optimization. When set to `True`, will805    always serialize default values.806    """807    self.forceDefaults = forceDefaults808 809  ##############################################################810 811  ## @cond FLATBUFFERS_INTERNAL812  def PrependVOffsetT(self, x):813    self.Prepend(N.VOffsetTFlags, x)814 815  def Place(self, x, flags):816    """Place prepends a value specified by `flags` to the Builder,817 818    without checking for available space.819    """820 821    N.enforce_number(x, flags)822    new_head = self.head - flags.bytewidth823    self.head = new_head824    encode.Write(flags.packer_type, self.Bytes, new_head, x)825 826  def PlaceVOffsetT(self, x):827    """PlaceVOffsetT prepends a VOffsetT to the Builder, without checking828 829    for space.830    """831    N.enforce_number(x, N.VOffsetTFlags)832    new_head = self.head - N.VOffsetTFlags.bytewidth833    self.head = new_head834    encode.Write(packer.voffset, self.Bytes, new_head, x)835 836  def PlaceSOffsetT(self, x):837    """PlaceSOffsetT prepends a SOffsetT to the Builder, without checking838 839    for space.840    """841    N.enforce_number(x, N.SOffsetTFlags)842    new_head = self.head - N.SOffsetTFlags.bytewidth843    self.head = new_head844    encode.Write(packer.soffset, self.Bytes, new_head, x)845 846  def PlaceUOffsetT(self, x):847    """PlaceUOffsetT prepends a UOffsetT to the Builder, without checking848 849    for space.850    """851    N.enforce_number(x, N.UOffsetTFlags)852    new_head = self.head - N.UOffsetTFlags.bytewidth853    self.head = new_head854    encode.Write(packer.uoffset, self.Bytes, new_head, x)855 856  ## @endcond857 858## @}859 
codekingpro/portable-devtools · Team Ai