xref: /aosp_15_r20/external/flatbuffers/lua/flatbuffers/compat_luajit.lua (revision 890232f25432b36107d06881e0a25aaa6b473652)
1local bit = require("bit")
2local ffi = require("ffi")
3local band = bit.band
4local bnot = bit.bnot
5
6
7local m = {}
8local Uint8Bound = 256 -- bound is the max uintN + 1
9local Uint16Bound = 65536
10local Uint32Bound = 4294967296
11
12if not table.unpack then
13    table.unpack = unpack
14end
15
16if not table.pack then
17    table.pack = pack
18end
19
20m.GetAlignSize = function(k, size)
21    return band((bnot(k) + 1), (size - 1))
22end
23
24
25local function pack_I1(n)
26    return string.char(n)
27end
28local function pack_i1(n)
29    if n < 0 then
30        n = Uint8Bound + n
31    end
32    return pack_I1(n)
33end
34
35local function unpack_I1(n, pos)
36    return string.byte(n, pos)
37end
38local function unpack_i1(n, pos)
39    local res = unpack_I1(n, pos)
40    if res >= Uint8Bound / 2 then
41        return res - Uint8Bound
42    end
43    return res
44end
45
46local b2 = ffi.new("unsigned char[2]")
47local function pack_I2(n)
48    for i = 0, 1 do
49        b2[i] = bit.band(n, 255)
50        n = bit.rshift(n, 8)
51    end
52    return ffi.string(b2, 2)
53end
54local function pack_i2(n)
55    if n < 0 then
56        n = Uint16Bound + n
57    end
58    return pack_I2(n)
59end
60
61local function unpack_I2(n, pos)
62    local a, b = string.byte(n, pos, pos + 1)
63    return b * Uint8Bound + a
64end
65local function unpack_i2(n, pos)
66    local res = unpack_I2(n, pos)
67    if res >= Uint16Bound / 2 then
68        return res - Uint16Bound
69    end
70    return res
71end
72
73local b4 = ffi.new("unsigned char[4]")
74local function pack_I4(n)
75    for i = 0, 3 do
76        b4[i] = bit.band(n, 255)
77        n = bit.rshift(n, 8)
78    end
79    return ffi.string(b4, 4)
80end
81local function pack_i4(n)
82    if n < 0 then
83        n = Uint32Bound + n
84    end
85    return pack_I4(n)
86end
87
88local function unpack_I4(n, pos)
89    local a, b, c, d = string.byte(n, pos, pos + 3)
90    return Uint8Bound * (Uint8Bound * ((Uint8Bound * d) + c) + b) + a
91end
92local function unpack_i4(n, pos)
93    local res = unpack_I4(n, pos)
94    if res >= Uint32Bound / 2 then
95        return res - Uint32Bound
96    end
97    return res
98end
99
100local b8 = ffi.new("unsigned char[8]")
101local function pack_I8(n)
102    n = ffi.cast("unsigned long long", n)
103    local hi = math.floor(tonumber(n / Uint32Bound))
104    local li = n % Uint32Bound
105    for i = 0, 3 do
106        b8[i] = bit.band(li, 255)
107        li = bit.rshift(li, 8)
108    end
109    for i = 4, 7 do
110        b8[i] = bit.band(hi, 255)
111        hi = bit.rshift(hi, 8)
112    end
113    return ffi.string(b8, 8)
114end
115local function pack_i8(n)
116    n = ffi.cast("signed long long", n)
117    return pack_I8(n)
118end
119
120local function unpack_I8(n, pos)
121    local a, b, c, d = string.byte(n, pos, pos + 3)
122    local li = Uint8Bound * (Uint8Bound * ((Uint8Bound * d) + c) + b) + a
123    local a, b, c, d = string.byte(n, pos + 4, pos + 7)
124    local hi = Uint8Bound * (Uint8Bound * ((Uint8Bound * d) + c) + b) + a
125    return ffi.cast("unsigned long long", hi) * Uint32Bound + li
126end
127local function unpack_i8(n, pos)
128    local res = unpack_I8(n, pos)
129    return ffi.cast("signed long long", res)
130end
131
132local bf = ffi.new("float[1]")
133local function pack_f(n)
134    bf[0] = n
135    return ffi.string(bf, 4)
136end
137
138local function unpack_f(n, pos)
139    ffi.copy(bf, ffi.cast("char *", n) + pos - 1, 4)
140    return tonumber(bf[0])
141end
142
143local bd = ffi.new("double[1]")
144local function pack_d(n)
145    bd[0] = n
146    return ffi.string(bd, 8)
147end
148
149local function unpack_d(n, pos)
150    ffi.copy(bd, ffi.cast("char *", n) + pos - 1, 8)
151    return tonumber(bd[0])
152end
153
154
155m.string_pack = function(fmt, i, ...)
156    if fmt == "<I1" then
157        return pack_I1(i)
158    elseif fmt == "<I2" then
159        return pack_I2(i)
160    elseif fmt == "<I4" then
161        return pack_I4(i)
162    elseif fmt == "<I8" then
163        return pack_I8(i)
164    elseif fmt == "<i1" then
165        return pack_i1(i)
166    elseif fmt == "<i2" then
167        return pack_i2(i)
168    elseif fmt == "<i4" then
169        return pack_i4(i)
170    elseif fmt == "<i8" then
171        return pack_i8(i)
172    elseif fmt == "<f" then
173        return pack_f(i)
174    elseif fmt == "<d" then
175        return pack_d(i)
176    else
177        error(string.format("FIXME: support fmt %s", fmt))
178    end
179end
180
181
182m.string_unpack = function(fmt, s, pos)
183    if not pos then
184        pos = 1
185    end
186
187    if fmt == "<I1" then
188        return unpack_I1(s, pos)
189    elseif fmt == "<I2" then
190        return unpack_I2(s, pos)
191    elseif fmt == "<I4" then
192        return unpack_I4(s, pos)
193    elseif fmt == "<I8" then
194        return unpack_I8(s, pos)
195    elseif fmt == "<i1" then
196        return unpack_i1(s, pos)
197    elseif fmt == "<i2" then
198        return unpack_i2(s, pos)
199    elseif fmt == "<i4" then
200        return unpack_i4(s, pos)
201    elseif fmt == "<i8" then
202        return unpack_i8(s, pos)
203    elseif fmt == "<f" then
204        return unpack_f(s, pos)
205    elseif fmt == "<d" then
206        return unpack_d(s, pos)
207    else
208        error(string.format("FIXME: support fmt %s", fmt))
209    end
210end
211
212
213return m
214