@axpecter/lync 1.5.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +499 -357
- package/package.json +2 -2
- package/src/Types.luau +69 -27
- package/src/api/Group.luau +101 -106
- package/src/api/Packet.luau +191 -157
- package/src/api/Query.luau +223 -282
- package/src/api/Scope.luau +46 -57
- package/src/api/Signal.luau +104 -137
- package/src/codec/Base.luau +69 -20
- package/src/codec/composite/Array.luau +189 -201
- package/src/codec/composite/Map.luau +97 -341
- package/src/codec/composite/Optional.luau +27 -23
- package/src/codec/composite/Shared.luau +96 -65
- package/src/codec/composite/Struct.luau +201 -339
- package/src/codec/composite/Tagged.luau +64 -178
- package/src/codec/composite/Tuple.luau +81 -95
- package/src/codec/datatype/Buffer.luau +49 -21
- package/src/codec/datatype/CFrame.luau +207 -30
- package/src/codec/datatype/Color.luau +21 -11
- package/src/codec/datatype/Instance.luau +29 -19
- package/src/codec/datatype/IntVector.luau +33 -21
- package/src/codec/datatype/NumberRange.luau +19 -10
- package/src/codec/datatype/Ray.luau +26 -22
- package/src/codec/datatype/Rect.luau +20 -16
- package/src/codec/datatype/Region.luau +51 -45
- package/src/codec/datatype/Sequence.luau +64 -56
- package/src/codec/datatype/String.luau +89 -56
- package/src/codec/datatype/UDim.luau +40 -22
- package/src/codec/datatype/Vector.luau +181 -17
- package/src/codec/meta/Auto.luau +295 -253
- package/src/codec/meta/Bitfield.luau +104 -148
- package/src/codec/meta/Custom.luau +8 -4
- package/src/codec/meta/Enum.luau +29 -57
- package/src/codec/meta/Float.luau +64 -0
- package/src/codec/meta/Nothing.luau +9 -5
- package/src/codec/meta/Unknown.luau +44 -35
- package/src/codec/primitive/Bool.luau +16 -26
- package/src/codec/primitive/Float16.luau +58 -64
- package/src/codec/primitive/Int.luau +68 -0
- package/src/codec/primitive/Number.luau +21 -43
- package/src/codec/primitive/Varint.luau +67 -46
- package/src/index.d.ts +249 -306
- package/src/init.luau +332 -173
- package/src/internal/Baseline.luau +29 -24
- package/src/internal/Channel.luau +346 -161
- package/src/internal/Middleware.luau +60 -85
- package/src/internal/Pool.luau +19 -30
- package/src/internal/Registry.luau +61 -101
- package/src/transport/Bridge.luau +64 -43
- package/src/transport/Client.luau +60 -117
- package/src/transport/Gate.luau +282 -133
- package/src/transport/Reader.luau +159 -100
- package/src/transport/Server.luau +147 -292
- package/src/api/Namespace.luau +0 -251
- package/src/codec/meta/Quantized.luau +0 -174
|
@@ -2,277 +2,265 @@
|
|
|
2
2
|
--!native
|
|
3
3
|
-- array and deltaArray codecs.
|
|
4
4
|
|
|
5
|
-
local
|
|
6
|
-
local Channel = require(script.Parent.Parent.Parent.internal.Channel)
|
|
5
|
+
local Base = require(script.Parent.Parent.Base)
|
|
7
6
|
local Shared = require(script.Parent.Shared)
|
|
8
7
|
local Types = require(script.Parent.Parent.Parent.Types)
|
|
9
8
|
local Varint = require(script.Parent.Parent.primitive.Varint)
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
-- Private -------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
local alloc = Base.alloc
|
|
13
|
+
local writeu8 = buffer.writeu8
|
|
14
|
+
local readu8 = buffer.readu8
|
|
15
|
+
local band = bit32.band
|
|
16
|
+
local bor = bit32.bor
|
|
17
|
+
local lshift = bit32.lshift
|
|
14
18
|
|
|
15
|
-
local alloc = Channel.alloc
|
|
16
|
-
local rangeEqual = Shared.rangeEqual
|
|
17
19
|
local acquireScratch = Shared.acquireScratch
|
|
18
20
|
local releaseScratch = Shared.releaseScratch
|
|
21
|
+
local rangeEqual = Shared.rangeEqual
|
|
22
|
+
local allocDeltaId = Shared.allocDeltaId
|
|
19
23
|
|
|
20
|
-
local
|
|
21
|
-
local
|
|
22
|
-
local
|
|
24
|
+
local DELTA_UNCHANGED = Shared.DELTA_UNCHANGED
|
|
25
|
+
local DELTA_FULL_OFFSET = Shared.DELTA_FULL_OFFSET
|
|
26
|
+
local DELTA_MULTI_OFFSET = Shared.DELTA_MULTI_OFFSET
|
|
23
27
|
|
|
24
28
|
-- Public --------------------------------------------------------------
|
|
25
29
|
|
|
26
30
|
local Array = {}
|
|
27
31
|
|
|
28
|
-
function Array.
|
|
29
|
-
local
|
|
30
|
-
|
|
31
|
-
local writeElement = element.write
|
|
32
|
-
local readElement = element.read
|
|
33
|
-
|
|
34
|
-
local internal = element :: InternalCodec<any>
|
|
35
|
-
local elemSize = internal._size
|
|
36
|
-
local elemWrite = internal._directWrite
|
|
37
|
-
local elemRead = internal._directRead
|
|
38
|
-
|
|
39
|
-
return table.freeze({
|
|
40
|
-
_isDelta = true,
|
|
41
|
-
|
|
42
|
-
write = function(ch: ChannelState, value: { any }): ()
|
|
43
|
-
local len = #value
|
|
44
|
-
local cache = ch.deltas[deltaId] :: { raw: buffer, bounds: { number }, len: number }?
|
|
45
|
-
local scratch = acquireScratch()
|
|
32
|
+
function Array.array(element: Types.InternalCodec<any>, maxCount: number?): Types.InternalCodec<any>
|
|
33
|
+
local elemAny = element :: any
|
|
46
34
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
local
|
|
52
|
-
alloc(scratch, totalBytes)
|
|
53
|
-
local b = scratch.buff
|
|
54
|
-
local c = 0
|
|
55
|
-
for i = 1, len do
|
|
56
|
-
elemWrite(b, c, value[i])
|
|
57
|
-
c += elemSize
|
|
58
|
-
bounds[i + 1] = c
|
|
59
|
-
end
|
|
60
|
-
scratch.cursor = totalBytes
|
|
61
|
-
else
|
|
62
|
-
for i = 1, len do
|
|
63
|
-
writeElement(scratch, value[i])
|
|
64
|
-
bounds[i + 1] = scratch.cursor
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
local scratchTotal = scratch.cursor
|
|
69
|
-
|
|
70
|
-
if not cache or cache.len ~= len then
|
|
71
|
-
alloc(ch, 1)
|
|
72
|
-
buffer.writeu8(ch.buff, ch.cursor, FLAG_FULL)
|
|
73
|
-
ch.cursor += 1
|
|
35
|
+
-- Bool array: bitpacked
|
|
36
|
+
if elemAny._isBool then
|
|
37
|
+
return table.freeze({
|
|
38
|
+
write = function(ch: Types.ChannelState, value: { any }): ()
|
|
39
|
+
local len = #value
|
|
74
40
|
Varint.write(ch, len)
|
|
75
|
-
|
|
76
|
-
alloc(ch, scratchTotal)
|
|
77
|
-
buffer.copy(ch.buff, ch.cursor, scratch.buff, 0, scratchTotal)
|
|
78
|
-
ch.cursor += scratchTotal
|
|
79
|
-
else
|
|
80
|
-
local cacheRaw = cache.raw
|
|
81
|
-
local cacheBds = cache.bounds
|
|
82
|
-
local dirty = table.create(len)
|
|
83
|
-
local dirtyN = 0
|
|
84
|
-
|
|
85
|
-
for i = 1, len do
|
|
86
|
-
local newOff = bounds[i]
|
|
87
|
-
local newLen = bounds[i + 1] - newOff
|
|
88
|
-
local oldOff = cacheBds[i]
|
|
89
|
-
local oldLen = cacheBds[i + 1] - oldOff
|
|
90
|
-
|
|
91
|
-
if
|
|
92
|
-
newLen ~= oldLen
|
|
93
|
-
or not rangeEqual(scratch.buff, newOff, cacheRaw, oldOff, newLen)
|
|
94
|
-
then
|
|
95
|
-
dirtyN += 1
|
|
96
|
-
dirty[dirtyN] = i
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
if dirtyN == 0 then
|
|
101
|
-
alloc(ch, 1)
|
|
102
|
-
buffer.writeu8(ch.buff, ch.cursor, FLAG_UNCHANGED)
|
|
103
|
-
ch.cursor += 1
|
|
104
|
-
releaseScratch()
|
|
41
|
+
if len == 0 then
|
|
105
42
|
return
|
|
106
43
|
end
|
|
107
44
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
ch.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
for j = 1, dirtyN do
|
|
114
|
-
local i = dirty[j]
|
|
115
|
-
local newOff = bounds[i]
|
|
116
|
-
local newLen = bounds[i + 1] - newOff
|
|
117
|
-
|
|
118
|
-
Varint.write(ch, i - 1)
|
|
119
|
-
alloc(ch, newLen)
|
|
120
|
-
buffer.copy(ch.buff, ch.cursor, scratch.buff, newOff, newLen)
|
|
121
|
-
ch.cursor += newLen
|
|
45
|
+
local byteCount = (len + 7) // 8
|
|
46
|
+
local cursor = ch.cursor
|
|
47
|
+
if cursor + byteCount > ch.size then
|
|
48
|
+
alloc(ch, byteCount)
|
|
122
49
|
end
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
local rawBuf = buffer.create(scratchTotal)
|
|
126
|
-
buffer.copy(rawBuf, 0, scratch.buff, 0, scratchTotal)
|
|
127
|
-
|
|
128
|
-
table.freeze(bounds)
|
|
129
|
-
ch.deltas[deltaId] = { raw = rawBuf, bounds = bounds, len = len }
|
|
130
|
-
releaseScratch()
|
|
131
|
-
end,
|
|
132
|
-
|
|
133
|
-
read = function(src: buffer, pos: number, refs: { Instance }?): ({ any }, number)
|
|
134
|
-
local flag = buffer.readu8(src, pos)
|
|
135
|
-
local absPos = pos + 1
|
|
136
|
-
|
|
137
|
-
if flag == FLAG_UNCHANGED then
|
|
138
|
-
local cache = Baseline.getCache(deltaId)
|
|
139
|
-
return if cache then table.clone(cache) else {}, 1
|
|
140
|
-
end
|
|
50
|
+
local b = ch.buff
|
|
141
51
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
52
|
+
local idx = 1
|
|
53
|
+
for byteIdx = 0, byteCount - 1 do
|
|
54
|
+
local packed = 0
|
|
55
|
+
local limit = if idx + 8 <= len + 1 then 8 else len - idx + 1
|
|
56
|
+
for bit = 0, limit - 1 do
|
|
57
|
+
if value[idx] then
|
|
58
|
+
packed = bor(packed, lshift(1, bit))
|
|
59
|
+
end
|
|
60
|
+
idx += 1
|
|
61
|
+
end
|
|
62
|
+
writeu8(b, cursor + byteIdx, packed)
|
|
63
|
+
end
|
|
64
|
+
ch.cursor = cursor + byteCount
|
|
65
|
+
end,
|
|
145
66
|
|
|
67
|
+
read = function(src: buffer, pos: number, _refs: { Instance }?): ({ boolean }, number)
|
|
68
|
+
local len, lenBytes = Varint.read(src, pos)
|
|
146
69
|
if maxCount and len > maxCount then
|
|
147
|
-
error(`[Lync] Array count {len} exceeds max {maxCount}`)
|
|
70
|
+
error(`[Lync] Array: count {len} exceeds max {maxCount}`)
|
|
71
|
+
end
|
|
72
|
+
if len == 0 then
|
|
73
|
+
return {}, lenBytes
|
|
148
74
|
end
|
|
149
75
|
|
|
76
|
+
local byteCount = (len + 7) // 8
|
|
77
|
+
local dataStart = pos + lenBytes
|
|
150
78
|
local result = table.create(len)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
local val, n = readElement(src, absPos, refs)
|
|
160
|
-
result[i] = val
|
|
161
|
-
absPos += n
|
|
79
|
+
local idx = 1
|
|
80
|
+
|
|
81
|
+
for byteIdx = 0, byteCount - 1 do
|
|
82
|
+
local byte = readu8(src, dataStart + byteIdx)
|
|
83
|
+
local limit = if idx + 8 <= len + 1 then 8 else len - idx + 1
|
|
84
|
+
for bit = 0, limit - 1 do
|
|
85
|
+
result[idx] = band(byte, lshift(1, bit)) ~= 0
|
|
86
|
+
idx += 1
|
|
162
87
|
end
|
|
163
88
|
end
|
|
164
89
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
local cache = Baseline.getCache(deltaId) :: { any }?
|
|
170
|
-
local result = if cache then table.clone(cache) else {}
|
|
171
|
-
|
|
172
|
-
local dirtyN, dnBytes = Varint.read(src, absPos)
|
|
173
|
-
absPos += dnBytes
|
|
174
|
-
|
|
175
|
-
for _ = 1, dirtyN do
|
|
176
|
-
local idx, idxBytes = Varint.read(src, absPos)
|
|
177
|
-
absPos += idxBytes
|
|
178
|
-
|
|
179
|
-
if elemRead and elemSize then
|
|
180
|
-
result[idx + 1] = elemRead(src, absPos)
|
|
181
|
-
absPos += elemSize
|
|
182
|
-
else
|
|
183
|
-
local val, n = readElement(src, absPos, refs)
|
|
184
|
-
result[idx + 1] = val
|
|
185
|
-
absPos += n
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
Baseline.setCache(deltaId, result)
|
|
190
|
-
return result, absPos - pos
|
|
191
|
-
end,
|
|
192
|
-
})
|
|
193
|
-
end
|
|
90
|
+
return result, lenBytes + byteCount
|
|
91
|
+
end,
|
|
92
|
+
} :: any)
|
|
93
|
+
end
|
|
194
94
|
|
|
195
|
-
|
|
196
|
-
local
|
|
197
|
-
local
|
|
198
|
-
local
|
|
199
|
-
local directRead = internal._directRead
|
|
95
|
+
-- Direct array: element has _size + _directWrite + _directRead
|
|
96
|
+
local elemSize = elemAny._size
|
|
97
|
+
local elemDW = elemAny._directWrite
|
|
98
|
+
local elemDR = elemAny._directRead
|
|
200
99
|
|
|
201
|
-
if
|
|
100
|
+
if elemSize and elemDW and elemDR then
|
|
202
101
|
return table.freeze({
|
|
203
|
-
write = function(ch: ChannelState, value: { any }): ()
|
|
102
|
+
write = function(ch: Types.ChannelState, value: { any }): ()
|
|
204
103
|
local len = #value
|
|
205
104
|
Varint.write(ch, len)
|
|
206
105
|
if len == 0 then
|
|
207
106
|
return
|
|
208
107
|
end
|
|
209
108
|
|
|
210
|
-
local
|
|
211
|
-
local
|
|
212
|
-
if
|
|
213
|
-
alloc(ch,
|
|
109
|
+
local payloadBytes = len * elemSize
|
|
110
|
+
local cursor = ch.cursor
|
|
111
|
+
if cursor + payloadBytes > ch.size then
|
|
112
|
+
alloc(ch, payloadBytes)
|
|
214
113
|
end
|
|
215
|
-
|
|
216
114
|
local b = ch.buff
|
|
115
|
+
|
|
217
116
|
for i = 1, len do
|
|
218
|
-
|
|
219
|
-
c += elementSize
|
|
117
|
+
elemDW(b, cursor + (i - 1) * elemSize, value[i])
|
|
220
118
|
end
|
|
221
|
-
ch.cursor =
|
|
119
|
+
ch.cursor = cursor + payloadBytes
|
|
222
120
|
end,
|
|
121
|
+
|
|
223
122
|
read = function(src: buffer, pos: number, _refs: { Instance }?): ({ any }, number)
|
|
224
123
|
local len, lenBytes = Varint.read(src, pos)
|
|
225
|
-
|
|
226
124
|
if maxCount and len > maxCount then
|
|
227
|
-
error(`[Lync] Array count {len} exceeds max {maxCount}`)
|
|
125
|
+
error(`[Lync] Array: count {len} exceeds max {maxCount}`)
|
|
126
|
+
end
|
|
127
|
+
if len == 0 then
|
|
128
|
+
return {}, lenBytes
|
|
228
129
|
end
|
|
229
130
|
|
|
230
|
-
local
|
|
231
|
-
local
|
|
131
|
+
local payloadBytes = len * elemSize
|
|
132
|
+
local dataStart = pos + lenBytes
|
|
133
|
+
|
|
134
|
+
-- Safety cap
|
|
135
|
+
local remaining = buffer.len(src) - dataStart
|
|
136
|
+
if payloadBytes > remaining then
|
|
137
|
+
len = remaining // elemSize
|
|
138
|
+
payloadBytes = len * elemSize
|
|
139
|
+
end
|
|
232
140
|
|
|
141
|
+
local result = table.create(len)
|
|
233
142
|
for i = 1, len do
|
|
234
|
-
result[i] =
|
|
235
|
-
c += elementSize
|
|
143
|
+
result[i] = elemDR(src, dataStart + (i - 1) * elemSize)
|
|
236
144
|
end
|
|
237
145
|
|
|
238
|
-
return result,
|
|
146
|
+
return result, lenBytes + payloadBytes
|
|
239
147
|
end,
|
|
240
|
-
})
|
|
148
|
+
} :: any)
|
|
241
149
|
end
|
|
242
150
|
|
|
243
|
-
|
|
244
|
-
local readElement = element.read
|
|
245
|
-
|
|
151
|
+
-- Generic array
|
|
246
152
|
return table.freeze({
|
|
247
|
-
write = function(ch: ChannelState, value: { any }): ()
|
|
153
|
+
write = function(ch: Types.ChannelState, value: { any }): ()
|
|
248
154
|
local len = #value
|
|
249
155
|
Varint.write(ch, len)
|
|
250
|
-
if elementSize and len > 0 then
|
|
251
|
-
alloc(ch, len * elementSize)
|
|
252
|
-
end
|
|
253
156
|
for i = 1, len do
|
|
254
|
-
|
|
157
|
+
element.write(ch, value[i])
|
|
255
158
|
end
|
|
256
159
|
end,
|
|
160
|
+
|
|
257
161
|
read = function(src: buffer, pos: number, refs: { Instance }?): ({ any }, number)
|
|
258
162
|
local len, lenBytes = Varint.read(src, pos)
|
|
259
|
-
|
|
260
163
|
if maxCount and len > maxCount then
|
|
261
|
-
error(`[Lync] Array count {len} exceeds max {maxCount}`)
|
|
164
|
+
error(`[Lync] Array: count {len} exceeds max {maxCount}`)
|
|
165
|
+
end
|
|
166
|
+
if len == 0 then
|
|
167
|
+
return {}, lenBytes
|
|
262
168
|
end
|
|
263
169
|
|
|
264
170
|
local result = table.create(len)
|
|
265
|
-
local
|
|
266
|
-
|
|
171
|
+
local total = lenBytes
|
|
267
172
|
for i = 1, len do
|
|
268
|
-
local
|
|
269
|
-
result[i] =
|
|
270
|
-
|
|
173
|
+
local v, consumed = element.read(src, pos + total, refs)
|
|
174
|
+
result[i] = v
|
|
175
|
+
total += consumed
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
return result, total
|
|
179
|
+
end,
|
|
180
|
+
} :: any)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
function Array.deltaArray(
|
|
184
|
+
element: Types.InternalCodec<any>,
|
|
185
|
+
maxCount: number?
|
|
186
|
+
): Types.InternalCodec<any>
|
|
187
|
+
local deltaId = allocDeltaId()
|
|
188
|
+
local innerArray = Array.array(element, maxCount)
|
|
189
|
+
|
|
190
|
+
return table.freeze({
|
|
191
|
+
_isDelta = true,
|
|
192
|
+
|
|
193
|
+
write = function(ch: Types.ChannelState, value: { any }): ()
|
|
194
|
+
local cache = ch.deltas[deltaId]
|
|
195
|
+
|
|
196
|
+
if not cache then
|
|
197
|
+
-- First frame: full
|
|
198
|
+
local cursor = ch.cursor
|
|
199
|
+
if cursor + 1 > ch.size then
|
|
200
|
+
alloc(ch, 1)
|
|
201
|
+
end
|
|
202
|
+
writeu8(ch.buff, cursor, 1) -- FLAG_FULL (len+1 where len=0 for first)
|
|
203
|
+
ch.cursor = cursor + 1
|
|
204
|
+
|
|
205
|
+
local scratch = acquireScratch()
|
|
206
|
+
innerArray.write(scratch, value)
|
|
207
|
+
local snapLen = scratch.cursor
|
|
208
|
+
local snapBuf = buffer.create(snapLen)
|
|
209
|
+
buffer.copy(snapBuf, 0, scratch.buff, 0, snapLen)
|
|
210
|
+
|
|
211
|
+
ch.deltas[deltaId] = { raw = snapBuf, len = snapLen }
|
|
212
|
+
innerArray.write(ch, value)
|
|
213
|
+
releaseScratch()
|
|
214
|
+
return
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
-- Compare against cache
|
|
218
|
+
local scratch = acquireScratch()
|
|
219
|
+
innerArray.write(scratch, value)
|
|
220
|
+
local scratchLen = scratch.cursor
|
|
221
|
+
local cachedLen = cache.len
|
|
222
|
+
|
|
223
|
+
if
|
|
224
|
+
scratchLen == cachedLen and rangeEqual(scratch.buff, 0, cache.raw, 0, scratchLen)
|
|
225
|
+
then
|
|
226
|
+
local cursor = ch.cursor
|
|
227
|
+
if cursor + 1 > ch.size then
|
|
228
|
+
alloc(ch, 1)
|
|
229
|
+
end
|
|
230
|
+
writeu8(ch.buff, cursor, DELTA_UNCHANGED)
|
|
231
|
+
ch.cursor = cursor + 1
|
|
232
|
+
releaseScratch()
|
|
233
|
+
return
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
-- Changed: full re-send
|
|
237
|
+
local cursor = ch.cursor
|
|
238
|
+
if cursor + 1 > ch.size then
|
|
239
|
+
alloc(ch, 1)
|
|
240
|
+
end
|
|
241
|
+
writeu8(ch.buff, cursor, 1)
|
|
242
|
+
ch.cursor = cursor + 1
|
|
243
|
+
innerArray.write(ch, value)
|
|
244
|
+
|
|
245
|
+
local newBuf = buffer.create(scratchLen)
|
|
246
|
+
buffer.copy(newBuf, 0, scratch.buff, 0, scratchLen)
|
|
247
|
+
cache.raw = newBuf
|
|
248
|
+
cache.len = scratchLen
|
|
249
|
+
|
|
250
|
+
releaseScratch()
|
|
251
|
+
end,
|
|
252
|
+
|
|
253
|
+
read = function(src: buffer, pos: number, refs: { Instance }?): ({ any }, number)
|
|
254
|
+
local flag = readu8(src, pos)
|
|
255
|
+
|
|
256
|
+
if flag == DELTA_UNCHANGED then
|
|
257
|
+
return {} :: any, 1
|
|
271
258
|
end
|
|
272
259
|
|
|
273
|
-
|
|
260
|
+
local value, consumed = innerArray.read(src, pos + 1, refs)
|
|
261
|
+
return value, 1 + consumed
|
|
274
262
|
end,
|
|
275
|
-
})
|
|
263
|
+
} :: any)
|
|
276
264
|
end
|
|
277
265
|
|
|
278
266
|
return table.freeze(Array)
|