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