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