James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame^] | 1 | local compat = require("flatbuffers.compat") |
| 2 | local string_unpack = compat.string_unpack |
| 3 | |
| 4 | |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 5 | local m = {} |
| 6 | local mt = {} |
| 7 | |
| 8 | local mt_name = "flatbuffers.view.mt" |
| 9 | |
| 10 | local N = require("flatbuffers.numTypes") |
| 11 | local binaryarray = require("flatbuffers.binaryarray") |
| 12 | |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 13 | local function enforceOffset(off) |
| 14 | if off < 0 or off > 42949672951 then |
| 15 | error("Offset is not valid") |
| 16 | end |
| 17 | end |
| 18 | |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 19 | local function unPackUoffset(bytes, off) |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame^] | 20 | return string_unpack("<I4", bytes.str, off + 1) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 21 | end |
| 22 | |
| 23 | local function unPackVoffset(bytes, off) |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame^] | 24 | return string_unpack("<I2", bytes.str, off + 1) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 25 | end |
| 26 | |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 27 | function m.New(buf, pos) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 28 | enforceOffset(pos) |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 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, |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 34 | pos = pos, |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 35 | } |
| 36 | setmetatable(o, {__index = mt, __metatable = mt_name}) |
| 37 | return o |
| 38 | end |
| 39 | |
| 40 | function mt:Offset(vtableOffset) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 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) |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 49 | end |
| 50 | return 0 |
| 51 | end |
| 52 | |
| 53 | function mt:Indirect(off) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 54 | enforceOffset(off) |
| 55 | return off + unPackUoffset(self.bytes, off) |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 56 | end |
| 57 | |
| 58 | function mt:String(off) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 59 | enforceOffset(off) |
| 60 | off = off + unPackUoffset(self.bytes, off) |
| 61 | local start = off + 4 |
| 62 | local length = unPackUoffset(self.bytes, off) |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 63 | return self.bytes:Slice(start, start+length) |
| 64 | end |
| 65 | |
| 66 | function mt:VectorLen(off) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 67 | enforceOffset(off) |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 68 | off = off + self.pos |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 69 | off = off + unPackUoffset(self.bytes, off) |
| 70 | return unPackUoffset(self.bytes, off) |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 71 | end |
| 72 | |
| 73 | function mt:Vector(off) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 74 | enforceOffset(off) |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 75 | off = off + self.pos |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 76 | return off + self:Get(N.UOffsetT, off) + 4 |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 77 | end |
| 78 | |
James Kuszmaul | 8e62b02 | 2022-03-22 09:33:25 -0700 | [diff] [blame^] | 79 | function 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 |
| 88 | end |
| 89 | |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 90 | function mt:Union(t2, off) |
| 91 | assert(getmetatable(t2) == mt_name) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 92 | enforceOffset(off) |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 93 | off = off + self.pos |
| 94 | t2.pos = off + self:Get(N.UOffsetT, off) |
| 95 | t2.bytes = self.bytes |
| 96 | end |
| 97 | |
| 98 | function mt:Get(flags, off) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 99 | enforceOffset(off) |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 100 | return flags:Unpack(self.bytes, off) |
| 101 | end |
| 102 | |
| 103 | function 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) |
| 113 | end |
| 114 | |
| 115 | function mt:GetVOffsetTSlot(slot, d) |
Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame] | 116 | N.VOffsetT:EnforceNumbers(slot, d) |
Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame] | 117 | local off = self:Offset(slot) |
| 118 | if off == 0 then |
| 119 | return d |
| 120 | end |
| 121 | return off |
| 122 | end |
| 123 | |
| 124 | return m |