1*890232f2SAndroid Build Coastguard Worker# Copyright 2014 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 Workerfrom . import encode 16*890232f2SAndroid Build Coastguard Workerfrom . import number_types as N 17*890232f2SAndroid Build Coastguard Worker 18*890232f2SAndroid Build Coastguard Worker 19*890232f2SAndroid Build Coastguard Workerclass Table(object): 20*890232f2SAndroid Build Coastguard Worker """Table wraps a byte slice and provides read access to its data. 21*890232f2SAndroid Build Coastguard Worker 22*890232f2SAndroid Build Coastguard Worker The variable `Pos` indicates the root of the FlatBuffers object therein.""" 23*890232f2SAndroid Build Coastguard Worker 24*890232f2SAndroid Build Coastguard Worker __slots__ = ("Bytes", "Pos") 25*890232f2SAndroid Build Coastguard Worker 26*890232f2SAndroid Build Coastguard Worker def __init__(self, buf, pos): 27*890232f2SAndroid Build Coastguard Worker N.enforce_number(pos, N.UOffsetTFlags) 28*890232f2SAndroid Build Coastguard Worker 29*890232f2SAndroid Build Coastguard Worker self.Bytes = buf 30*890232f2SAndroid Build Coastguard Worker self.Pos = pos 31*890232f2SAndroid Build Coastguard Worker 32*890232f2SAndroid Build Coastguard Worker def Offset(self, vtableOffset): 33*890232f2SAndroid Build Coastguard Worker """Offset provides access into the Table's vtable. 34*890232f2SAndroid Build Coastguard Worker 35*890232f2SAndroid Build Coastguard Worker Deprecated fields are ignored by checking the vtable's length.""" 36*890232f2SAndroid Build Coastguard Worker 37*890232f2SAndroid Build Coastguard Worker vtable = self.Pos - self.Get(N.SOffsetTFlags, self.Pos) 38*890232f2SAndroid Build Coastguard Worker vtableEnd = self.Get(N.VOffsetTFlags, vtable) 39*890232f2SAndroid Build Coastguard Worker if vtableOffset < vtableEnd: 40*890232f2SAndroid Build Coastguard Worker return self.Get(N.VOffsetTFlags, vtable + vtableOffset) 41*890232f2SAndroid Build Coastguard Worker return 0 42*890232f2SAndroid Build Coastguard Worker 43*890232f2SAndroid Build Coastguard Worker def Indirect(self, off): 44*890232f2SAndroid Build Coastguard Worker """Indirect retrieves the relative offset stored at `offset`.""" 45*890232f2SAndroid Build Coastguard Worker N.enforce_number(off, N.UOffsetTFlags) 46*890232f2SAndroid Build Coastguard Worker return off + encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off) 47*890232f2SAndroid Build Coastguard Worker 48*890232f2SAndroid Build Coastguard Worker def String(self, off): 49*890232f2SAndroid Build Coastguard Worker """String gets a string from data stored inside the flatbuffer.""" 50*890232f2SAndroid Build Coastguard Worker N.enforce_number(off, N.UOffsetTFlags) 51*890232f2SAndroid Build Coastguard Worker off += encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off) 52*890232f2SAndroid Build Coastguard Worker start = off + N.UOffsetTFlags.bytewidth 53*890232f2SAndroid Build Coastguard Worker length = encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off) 54*890232f2SAndroid Build Coastguard Worker return bytes(self.Bytes[start:start+length]) 55*890232f2SAndroid Build Coastguard Worker 56*890232f2SAndroid Build Coastguard Worker def VectorLen(self, off): 57*890232f2SAndroid Build Coastguard Worker """VectorLen retrieves the length of the vector whose offset is stored 58*890232f2SAndroid Build Coastguard Worker at "off" in this object.""" 59*890232f2SAndroid Build Coastguard Worker N.enforce_number(off, N.UOffsetTFlags) 60*890232f2SAndroid Build Coastguard Worker 61*890232f2SAndroid Build Coastguard Worker off += self.Pos 62*890232f2SAndroid Build Coastguard Worker off += encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off) 63*890232f2SAndroid Build Coastguard Worker ret = encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off) 64*890232f2SAndroid Build Coastguard Worker return ret 65*890232f2SAndroid Build Coastguard Worker 66*890232f2SAndroid Build Coastguard Worker def Vector(self, off): 67*890232f2SAndroid Build Coastguard Worker """Vector retrieves the start of data of the vector whose offset is 68*890232f2SAndroid Build Coastguard Worker stored at "off" in this object.""" 69*890232f2SAndroid Build Coastguard Worker N.enforce_number(off, N.UOffsetTFlags) 70*890232f2SAndroid Build Coastguard Worker 71*890232f2SAndroid Build Coastguard Worker off += self.Pos 72*890232f2SAndroid Build Coastguard Worker x = off + self.Get(N.UOffsetTFlags, off) 73*890232f2SAndroid Build Coastguard Worker # data starts after metadata containing the vector length 74*890232f2SAndroid Build Coastguard Worker x += N.UOffsetTFlags.bytewidth 75*890232f2SAndroid Build Coastguard Worker return x 76*890232f2SAndroid Build Coastguard Worker 77*890232f2SAndroid Build Coastguard Worker def Union(self, t2, off): 78*890232f2SAndroid Build Coastguard Worker """Union initializes any Table-derived type to point to the union at 79*890232f2SAndroid Build Coastguard Worker the given offset.""" 80*890232f2SAndroid Build Coastguard Worker assert type(t2) is Table 81*890232f2SAndroid Build Coastguard Worker N.enforce_number(off, N.UOffsetTFlags) 82*890232f2SAndroid Build Coastguard Worker 83*890232f2SAndroid Build Coastguard Worker off += self.Pos 84*890232f2SAndroid Build Coastguard Worker t2.Pos = off + self.Get(N.UOffsetTFlags, off) 85*890232f2SAndroid Build Coastguard Worker t2.Bytes = self.Bytes 86*890232f2SAndroid Build Coastguard Worker 87*890232f2SAndroid Build Coastguard Worker def Get(self, flags, off): 88*890232f2SAndroid Build Coastguard Worker """ 89*890232f2SAndroid Build Coastguard Worker Get retrieves a value of the type specified by `flags` at the 90*890232f2SAndroid Build Coastguard Worker given offset. 91*890232f2SAndroid Build Coastguard Worker """ 92*890232f2SAndroid Build Coastguard Worker N.enforce_number(off, N.UOffsetTFlags) 93*890232f2SAndroid Build Coastguard Worker return flags.py_type(encode.Get(flags.packer_type, self.Bytes, off)) 94*890232f2SAndroid Build Coastguard Worker 95*890232f2SAndroid Build Coastguard Worker def GetSlot(self, slot, d, validator_flags): 96*890232f2SAndroid Build Coastguard Worker N.enforce_number(slot, N.VOffsetTFlags) 97*890232f2SAndroid Build Coastguard Worker if validator_flags is not None: 98*890232f2SAndroid Build Coastguard Worker N.enforce_number(d, validator_flags) 99*890232f2SAndroid Build Coastguard Worker off = self.Offset(slot) 100*890232f2SAndroid Build Coastguard Worker if off == 0: 101*890232f2SAndroid Build Coastguard Worker return d 102*890232f2SAndroid Build Coastguard Worker return self.Get(validator_flags, self.Pos + off) 103*890232f2SAndroid Build Coastguard Worker 104*890232f2SAndroid Build Coastguard Worker def GetVectorAsNumpy(self, flags, off): 105*890232f2SAndroid Build Coastguard Worker """ 106*890232f2SAndroid Build Coastguard Worker GetVectorAsNumpy returns the vector that starts at `Vector(off)` 107*890232f2SAndroid Build Coastguard Worker as a numpy array with the type specified by `flags`. The array is 108*890232f2SAndroid Build Coastguard Worker a `view` into Bytes, so modifying the returned array will 109*890232f2SAndroid Build Coastguard Worker modify Bytes in place. 110*890232f2SAndroid Build Coastguard Worker """ 111*890232f2SAndroid Build Coastguard Worker offset = self.Vector(off) 112*890232f2SAndroid Build Coastguard Worker length = self.VectorLen(off) # TODO: length accounts for bytewidth, right? 113*890232f2SAndroid Build Coastguard Worker numpy_dtype = N.to_numpy_type(flags) 114*890232f2SAndroid Build Coastguard Worker return encode.GetVectorAsNumpy(numpy_dtype, self.Bytes, length, offset) 115*890232f2SAndroid Build Coastguard Worker 116*890232f2SAndroid Build Coastguard Worker def GetVOffsetTSlot(self, slot, d): 117*890232f2SAndroid Build Coastguard Worker """ 118*890232f2SAndroid Build Coastguard Worker GetVOffsetTSlot retrieves the VOffsetT that the given vtable location 119*890232f2SAndroid Build Coastguard Worker points to. If the vtable value is zero, the default value `d` 120*890232f2SAndroid Build Coastguard Worker will be returned. 121*890232f2SAndroid Build Coastguard Worker """ 122*890232f2SAndroid Build Coastguard Worker 123*890232f2SAndroid Build Coastguard Worker N.enforce_number(slot, N.VOffsetTFlags) 124*890232f2SAndroid Build Coastguard Worker N.enforce_number(d, N.VOffsetTFlags) 125*890232f2SAndroid Build Coastguard Worker 126*890232f2SAndroid Build Coastguard Worker off = self.Offset(slot) 127*890232f2SAndroid Build Coastguard Worker if off == 0: 128*890232f2SAndroid Build Coastguard Worker return d 129*890232f2SAndroid Build Coastguard Worker return off 130