xref: /aosp_15_r20/external/flatbuffers/lua/flatbuffers/view.lua (revision 890232f25432b36107d06881e0a25aaa6b473652)
1local compat = require("flatbuffers.compat")
2local string_unpack = compat.string_unpack
3
4
5local m = {}
6local mt = {}
7
8local mt_name = "flatbuffers.view.mt"
9
10local N = require("flatbuffers.numTypes")
11local binaryarray = require("flatbuffers.binaryarray")
12
13local function enforceOffset(off)
14    if off < 0 or off > 42949672951 then
15        error("Offset is not valid")
16    end
17end
18
19local function unPackUoffset(bytes, off)
20    return string_unpack("<I4", bytes.str, off + 1)
21end
22
23local function unPackVoffset(bytes, off)
24    return string_unpack("<I2", bytes.str, off + 1)
25end
26
27function m.New(buf, pos)
28    enforceOffset(pos)
29    -- need to convert from a string buffer into
30    -- a binary array
31
32    local o = {
33        bytes = type(buf) == "string" and binaryarray.New(buf) or buf,
34        pos = pos,
35    }
36    setmetatable(o, {__index = mt, __metatable = mt_name})
37    return o
38end
39
40function mt:Offset(vtableOffset)
41    local vtable = self.vtable
42    if not vtable then
43        vtable = self.pos - self:Get(N.SOffsetT, self.pos)
44        self.vtable = vtable
45        self.vtableEnd = self:Get(N.VOffsetT, vtable)
46    end
47    if vtableOffset < self.vtableEnd then
48        return unPackVoffset(self.bytes, vtable + vtableOffset)
49    end
50    return 0
51end
52
53function mt:Indirect(off)
54    enforceOffset(off)
55    return off + unPackUoffset(self.bytes, off)
56end
57
58function mt:String(off)
59    enforceOffset(off)
60    off = off + unPackUoffset(self.bytes, off)
61    local start = off + 4
62    local length = unPackUoffset(self.bytes, off)
63    return self.bytes:Slice(start, start+length)
64end
65
66function mt:VectorLen(off)
67    enforceOffset(off)
68    off = off + self.pos
69    off = off + unPackUoffset(self.bytes, off)
70    return unPackUoffset(self.bytes, off)
71end
72
73function mt:Vector(off)
74    enforceOffset(off)
75    off = off + self.pos
76    return off + self:Get(N.UOffsetT, off) + 4
77end
78
79function mt:VectorAsString(off, start, stop)
80    local o = self:Offset(off)
81    if o ~= 0 then
82        start = start or 1
83        stop = stop or self:VectorLen(o)
84        local a = self:Vector(o) + start - 1
85        return self.bytes:Slice(a, a + stop - start + 1)
86    end
87    return nil
88end
89
90function mt:Union(t2, off)
91    assert(getmetatable(t2) == mt_name)
92    enforceOffset(off)
93    off = off + self.pos
94    t2.pos = off + self:Get(N.UOffsetT, off)
95    t2.bytes = self.bytes
96end
97
98function mt:Get(flags, off)
99    enforceOffset(off)
100    return flags:Unpack(self.bytes, off)
101end
102
103function mt:GetSlot(slot, d, validatorFlags)
104    N.VOffsetT:EnforceNumber(slot)
105    if validatorFlags then
106        validatorFlags:EnforceNumber(d)
107    end
108    local off = self:Offset(slot)
109    if off == 0 then
110        return d
111    end
112    return self:Get(validatorFlags, self.pos + off)
113end
114
115function mt:GetVOffsetTSlot(slot, d)
116    N.VOffsetT:EnforceNumbers(slot, d)
117    local off = self:Offset(slot)
118    if off == 0 then
119        return d
120    end
121    return off
122end
123
124return m