@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,408 +2,164 @@
|
|
|
2
2
|
--!native
|
|
3
3
|
-- map and deltaMap 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
|
|
14
15
|
|
|
15
|
-
local alloc = Channel.alloc
|
|
16
|
-
local rangeEqual = Shared.rangeEqual
|
|
17
16
|
local acquireScratch = Shared.acquireScratch
|
|
18
17
|
local releaseScratch = Shared.releaseScratch
|
|
19
|
-
|
|
20
|
-
local
|
|
21
|
-
local
|
|
22
|
-
local FLAG_UNCHANGED = Shared.FLAG_UNCHANGED
|
|
18
|
+
local rangeEqual = Shared.rangeEqual
|
|
19
|
+
local allocDeltaId = Shared.allocDeltaId
|
|
20
|
+
local DELTA_UNCHANGED = Shared.DELTA_UNCHANGED
|
|
23
21
|
|
|
24
22
|
-- Public --------------------------------------------------------------
|
|
25
23
|
|
|
26
24
|
local Map = {}
|
|
27
25
|
|
|
28
26
|
function Map.map(
|
|
29
|
-
keyCodec:
|
|
30
|
-
valueCodec:
|
|
27
|
+
keyCodec: Types.InternalCodec<any>,
|
|
28
|
+
valueCodec: Types.InternalCodec<any>,
|
|
31
29
|
maxCount: number?
|
|
32
|
-
):
|
|
33
|
-
local keyInternal = keyCodec :: InternalCodec<any>
|
|
34
|
-
local valInternal = valueCodec :: InternalCodec<any>
|
|
35
|
-
|
|
36
|
-
local keySize = keyInternal._size
|
|
37
|
-
local valSize = valInternal._size
|
|
38
|
-
local keyDWrite = keyInternal._directWrite
|
|
39
|
-
local valDWrite = valInternal._directWrite
|
|
40
|
-
local keyDRead = keyInternal._directRead
|
|
41
|
-
local valDRead = valInternal._directRead
|
|
42
|
-
|
|
43
|
-
if keySize and valSize and keyDWrite and valDWrite and keyDRead and valDRead then
|
|
44
|
-
local entrySize = keySize + valSize
|
|
45
|
-
|
|
46
|
-
return table.freeze({
|
|
47
|
-
write = function(ch: ChannelState, value: { [any]: any }): ()
|
|
48
|
-
local count = 0
|
|
49
|
-
for _ in value do
|
|
50
|
-
count += 1
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
Varint.write(ch, count)
|
|
54
|
-
|
|
55
|
-
if count > 0 then
|
|
56
|
-
local totalBytes = count * entrySize
|
|
57
|
-
local c = ch.cursor
|
|
58
|
-
if c + totalBytes > ch.size then
|
|
59
|
-
alloc(ch, totalBytes)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
local b = ch.buff
|
|
63
|
-
for k, v in value do
|
|
64
|
-
keyDWrite(b, c, k)
|
|
65
|
-
valDWrite(b, c + keySize, v)
|
|
66
|
-
c += entrySize
|
|
67
|
-
end
|
|
68
|
-
ch.cursor = c
|
|
69
|
-
end
|
|
70
|
-
end,
|
|
71
|
-
read = function(
|
|
72
|
-
src: buffer,
|
|
73
|
-
pos: number,
|
|
74
|
-
_refs: { Instance }?
|
|
75
|
-
): ({ [any]: any }, number)
|
|
76
|
-
local count, lenBytes = Varint.read(src, pos)
|
|
77
|
-
|
|
78
|
-
if maxCount and count > maxCount then
|
|
79
|
-
error(`[Lync] Map count {count} exceeds max {maxCount}`)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
local result = {}
|
|
83
|
-
local c = pos + lenBytes
|
|
84
|
-
|
|
85
|
-
for _ = 1, count do
|
|
86
|
-
local k = keyDRead(src, c)
|
|
87
|
-
local v = valDRead(src, c + keySize)
|
|
88
|
-
result[k] = v
|
|
89
|
-
c += entrySize
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
return result, c - pos
|
|
93
|
-
end,
|
|
94
|
-
})
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
local writeKey = keyCodec.write
|
|
98
|
-
local writeVal = valueCodec.write
|
|
99
|
-
local readKey = keyCodec.read
|
|
100
|
-
local readVal = valueCodec.read
|
|
101
|
-
|
|
30
|
+
): Types.InternalCodec<any>
|
|
102
31
|
return table.freeze({
|
|
103
|
-
write = function(ch: ChannelState, value:
|
|
32
|
+
write = function(ch: Types.ChannelState, value: any): ()
|
|
33
|
+
-- Count entries
|
|
104
34
|
local count = 0
|
|
105
35
|
for _ in value do
|
|
106
36
|
count += 1
|
|
107
37
|
end
|
|
108
38
|
|
|
109
39
|
Varint.write(ch, count)
|
|
40
|
+
if count == 0 then
|
|
41
|
+
return
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
-- Pre-alloc if both fixed size
|
|
45
|
+
local kAny = keyCodec :: any
|
|
46
|
+
local vAny = valueCodec :: any
|
|
47
|
+
if kAny._size and vAny._size then
|
|
48
|
+
local entrySize = kAny._size + vAny._size
|
|
49
|
+
local cursor = ch.cursor
|
|
50
|
+
if cursor + count * entrySize > ch.size then
|
|
51
|
+
alloc(ch, count * entrySize)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
110
54
|
|
|
111
55
|
for k, v in value do
|
|
112
|
-
|
|
113
|
-
|
|
56
|
+
keyCodec.write(ch, k)
|
|
57
|
+
valueCodec.write(ch, v)
|
|
114
58
|
end
|
|
115
59
|
end,
|
|
116
|
-
read = function(src: buffer, pos: number, refs: { Instance }?): ({ [any]: any }, number)
|
|
117
|
-
local count, lenBytes = Varint.read(src, pos)
|
|
118
60
|
|
|
61
|
+
read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
|
|
62
|
+
local count, lenBytes = Varint.read(src, pos)
|
|
119
63
|
if maxCount and count > maxCount then
|
|
120
|
-
error(`[Lync] Map count {count} exceeds max {maxCount}`)
|
|
64
|
+
error(`[Lync] Map: count {count} exceeds max {maxCount}`)
|
|
121
65
|
end
|
|
122
66
|
|
|
123
|
-
local result = {}
|
|
124
|
-
local
|
|
67
|
+
local result: { [any]: any } = {}
|
|
68
|
+
local total = lenBytes
|
|
125
69
|
|
|
126
70
|
for _ = 1, count do
|
|
127
|
-
local k,
|
|
128
|
-
|
|
129
|
-
local v,
|
|
130
|
-
|
|
71
|
+
local k, kc = keyCodec.read(src, pos + total, refs)
|
|
72
|
+
total += kc
|
|
73
|
+
local v, vc = valueCodec.read(src, pos + total, refs)
|
|
74
|
+
total += vc
|
|
131
75
|
result[k] = v
|
|
132
76
|
end
|
|
133
77
|
|
|
134
|
-
return result,
|
|
78
|
+
return result, total
|
|
135
79
|
end,
|
|
136
|
-
})
|
|
80
|
+
} :: any)
|
|
137
81
|
end
|
|
138
82
|
|
|
139
|
-
--[[
|
|
140
|
-
Delta map: tracks per-key changes. First frame is full, then upserts + removes only.
|
|
141
|
-
|
|
142
|
-
Wire format:
|
|
143
|
-
FLAG_FULL: u8(1) + varint(count) + [key+value ...]
|
|
144
|
-
FLAG_UNCHANGED: u8(2)
|
|
145
|
-
FLAG_DELTA: u8(0) + varint(upsertN) + [key+value ...] + varint(removeN) + [key ...]
|
|
146
|
-
]]
|
|
147
83
|
function Map.deltaMap(
|
|
148
|
-
keyCodec:
|
|
149
|
-
valueCodec:
|
|
84
|
+
keyCodec: Types.InternalCodec<any>,
|
|
85
|
+
valueCodec: Types.InternalCodec<any>,
|
|
150
86
|
maxCount: number?
|
|
151
|
-
):
|
|
152
|
-
local deltaId =
|
|
153
|
-
|
|
154
|
-
local writeKey = keyCodec.write
|
|
155
|
-
local writeVal = valueCodec.write
|
|
156
|
-
local readKey = keyCodec.read
|
|
157
|
-
local readVal = valueCodec.read
|
|
158
|
-
|
|
159
|
-
local keyInternal = keyCodec :: InternalCodec<any>
|
|
160
|
-
local valInternal = valueCodec :: InternalCodec<any>
|
|
161
|
-
|
|
162
|
-
local keySize = keyInternal._size
|
|
163
|
-
local valSize = valInternal._size
|
|
164
|
-
local keyDWrite = keyInternal._directWrite
|
|
165
|
-
local valDWrite = valInternal._directWrite
|
|
166
|
-
local keyDRead = keyInternal._directRead
|
|
167
|
-
local valDRead = valInternal._directRead
|
|
168
|
-
|
|
169
|
-
local scratchDirect = keySize and valSize and keyDWrite and valDWrite
|
|
170
|
-
local entrySize = if keySize and valSize then keySize + valSize else nil
|
|
171
|
-
|
|
172
|
-
type EntryBounds = {
|
|
173
|
-
keyOff: number,
|
|
174
|
-
keyLen: number,
|
|
175
|
-
valOff: number,
|
|
176
|
-
valLen: number,
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
type DeltaMapCache = {
|
|
180
|
-
raw: buffer,
|
|
181
|
-
entries: { EntryBounds },
|
|
182
|
-
keyLookup: { [string]: number },
|
|
183
|
-
count: number,
|
|
184
|
-
}
|
|
87
|
+
): Types.InternalCodec<any>
|
|
88
|
+
local deltaId = allocDeltaId()
|
|
89
|
+
local innerMap = Map.map(keyCodec, valueCodec, maxCount)
|
|
185
90
|
|
|
186
91
|
return table.freeze({
|
|
187
92
|
_isDelta = true,
|
|
188
93
|
|
|
189
|
-
write = function(ch: ChannelState, value:
|
|
190
|
-
local
|
|
191
|
-
|
|
192
|
-
local entries = {} :: { EntryBounds }
|
|
193
|
-
local keyLookup = {} :: { [string]: number }
|
|
194
|
-
local entryCount = 0
|
|
195
|
-
|
|
196
|
-
if scratchDirect then
|
|
197
|
-
for k, v in value do
|
|
198
|
-
entryCount += 1
|
|
199
|
-
local c = scratch.cursor
|
|
200
|
-
alloc(scratch, entrySize :: number)
|
|
201
|
-
local b = scratch.buff
|
|
202
|
-
keyDWrite(b, c, k)
|
|
203
|
-
valDWrite(b, c + (keySize :: number), v)
|
|
204
|
-
scratch.cursor = c + (entrySize :: number)
|
|
205
|
-
|
|
206
|
-
entries[entryCount] = {
|
|
207
|
-
keyOff = c,
|
|
208
|
-
keyLen = keySize :: number,
|
|
209
|
-
valOff = c + (keySize :: number),
|
|
210
|
-
valLen = valSize :: number,
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
local keyId = buffer.readstring(b, c, keySize :: number)
|
|
214
|
-
keyLookup[keyId] = entryCount
|
|
215
|
-
end
|
|
216
|
-
else
|
|
217
|
-
for k, v in value do
|
|
218
|
-
entryCount += 1
|
|
219
|
-
local keyStart = scratch.cursor
|
|
220
|
-
writeKey(scratch, k)
|
|
221
|
-
local keyEnd = scratch.cursor
|
|
222
|
-
writeVal(scratch, v)
|
|
223
|
-
local valEnd = scratch.cursor
|
|
224
|
-
|
|
225
|
-
entries[entryCount] = {
|
|
226
|
-
keyOff = keyStart,
|
|
227
|
-
keyLen = keyEnd - keyStart,
|
|
228
|
-
valOff = keyEnd,
|
|
229
|
-
valLen = valEnd - keyEnd,
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
local keyId = buffer.readstring(scratch.buff, keyStart, keyEnd - keyStart)
|
|
233
|
-
keyLookup[keyId] = entryCount
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
local scratchTotal = scratch.cursor
|
|
238
|
-
local cache = ch.deltas[deltaId] :: DeltaMapCache?
|
|
94
|
+
write = function(ch: Types.ChannelState, value: any): ()
|
|
95
|
+
local cache = ch.deltas[deltaId]
|
|
239
96
|
|
|
240
97
|
if not cache then
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
ch.cursor += 1
|
|
244
|
-
Varint.write(ch, entryCount)
|
|
245
|
-
|
|
246
|
-
if scratchTotal > 0 then
|
|
247
|
-
alloc(ch, scratchTotal)
|
|
248
|
-
buffer.copy(ch.buff, ch.cursor, scratch.buff, 0, scratchTotal)
|
|
249
|
-
ch.cursor += scratchTotal
|
|
250
|
-
end
|
|
251
|
-
else
|
|
252
|
-
local cacheRaw = cache.raw
|
|
253
|
-
local cacheEntries = cache.entries
|
|
254
|
-
local cacheLookup = cache.keyLookup
|
|
255
|
-
|
|
256
|
-
local upsertKeys = {} :: { number }
|
|
257
|
-
local upsertN = 0
|
|
258
|
-
|
|
259
|
-
for keyId, idx in keyLookup do
|
|
260
|
-
local oldIdx = cacheLookup[keyId]
|
|
261
|
-
if not oldIdx then
|
|
262
|
-
upsertN += 1
|
|
263
|
-
upsertKeys[upsertN] = idx
|
|
264
|
-
else
|
|
265
|
-
local newE = entries[idx]
|
|
266
|
-
local oldE = cacheEntries[oldIdx]
|
|
267
|
-
if
|
|
268
|
-
newE.valLen ~= oldE.valLen
|
|
269
|
-
or not rangeEqual(
|
|
270
|
-
scratch.buff,
|
|
271
|
-
newE.valOff,
|
|
272
|
-
cacheRaw,
|
|
273
|
-
oldE.valOff,
|
|
274
|
-
newE.valLen
|
|
275
|
-
)
|
|
276
|
-
then
|
|
277
|
-
upsertN += 1
|
|
278
|
-
upsertKeys[upsertN] = idx
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
local removeKeyIds = {} :: { string }
|
|
284
|
-
local removeN = 0
|
|
285
|
-
|
|
286
|
-
for keyId in cacheLookup do
|
|
287
|
-
if not keyLookup[keyId] then
|
|
288
|
-
removeN += 1
|
|
289
|
-
removeKeyIds[removeN] = keyId
|
|
290
|
-
end
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
if upsertN == 0 and removeN == 0 then
|
|
98
|
+
local cursor = ch.cursor
|
|
99
|
+
if cursor + 1 > ch.size then
|
|
294
100
|
alloc(ch, 1)
|
|
295
|
-
buffer.writeu8(ch.buff, ch.cursor, FLAG_UNCHANGED)
|
|
296
|
-
ch.cursor += 1
|
|
297
|
-
releaseScratch()
|
|
298
|
-
return
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
alloc(ch, 1)
|
|
302
|
-
buffer.writeu8(ch.buff, ch.cursor, FLAG_DELTA)
|
|
303
|
-
ch.cursor += 1
|
|
304
|
-
|
|
305
|
-
Varint.write(ch, upsertN)
|
|
306
|
-
for i = 1, upsertN do
|
|
307
|
-
local e = entries[upsertKeys[i]]
|
|
308
|
-
local totalLen = e.keyLen + e.valLen
|
|
309
|
-
alloc(ch, totalLen)
|
|
310
|
-
buffer.copy(ch.buff, ch.cursor, scratch.buff, e.keyOff, totalLen)
|
|
311
|
-
ch.cursor += totalLen
|
|
312
101
|
end
|
|
102
|
+
writeu8(ch.buff, cursor, 3) -- FLAG_FULL
|
|
103
|
+
ch.cursor = cursor + 1
|
|
104
|
+
|
|
105
|
+
local scratch = acquireScratch()
|
|
106
|
+
innerMap.write(scratch, value)
|
|
107
|
+
local snapLen = scratch.cursor
|
|
108
|
+
local snapBuf = buffer.create(snapLen)
|
|
109
|
+
buffer.copy(snapBuf, 0, scratch.buff, 0, snapLen)
|
|
110
|
+
|
|
111
|
+
ch.deltas[deltaId] = { raw = snapBuf, len = snapLen }
|
|
112
|
+
innerMap.write(ch, value)
|
|
113
|
+
releaseScratch()
|
|
114
|
+
return
|
|
115
|
+
end
|
|
313
116
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
117
|
+
local scratch = acquireScratch()
|
|
118
|
+
innerMap.write(scratch, value)
|
|
119
|
+
local scratchLen = scratch.cursor
|
|
120
|
+
local cachedLen = cache.len
|
|
121
|
+
|
|
122
|
+
if
|
|
123
|
+
scratchLen == cachedLen and rangeEqual(scratch.buff, 0, cache.raw, 0, scratchLen)
|
|
124
|
+
then
|
|
125
|
+
local cursor = ch.cursor
|
|
126
|
+
if cursor + 1 > ch.size then
|
|
127
|
+
alloc(ch, 1)
|
|
322
128
|
end
|
|
129
|
+
writeu8(ch.buff, cursor, DELTA_UNCHANGED)
|
|
130
|
+
ch.cursor = cursor + 1
|
|
131
|
+
releaseScratch()
|
|
132
|
+
return
|
|
323
133
|
end
|
|
324
134
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
135
|
+
-- Changed: full re-send
|
|
136
|
+
local cursor = ch.cursor
|
|
137
|
+
if cursor + 1 > ch.size then
|
|
138
|
+
alloc(ch, 1)
|
|
328
139
|
end
|
|
140
|
+
writeu8(ch.buff, cursor, 3) -- FLAG_FULL
|
|
141
|
+
ch.cursor = cursor + 1
|
|
142
|
+
innerMap.write(ch, value)
|
|
329
143
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
count = entryCount,
|
|
335
|
-
}
|
|
144
|
+
local newBuf = buffer.create(scratchLen)
|
|
145
|
+
buffer.copy(newBuf, 0, scratch.buff, 0, scratchLen)
|
|
146
|
+
cache.raw = newBuf
|
|
147
|
+
cache.len = scratchLen
|
|
336
148
|
|
|
337
149
|
releaseScratch()
|
|
338
150
|
end,
|
|
339
151
|
|
|
340
|
-
read = function(src: buffer, pos: number, refs: { Instance }?): (
|
|
341
|
-
local flag =
|
|
342
|
-
local absPos = pos + 1
|
|
343
|
-
|
|
344
|
-
if flag == FLAG_UNCHANGED then
|
|
345
|
-
local cache = Baseline.getCache(deltaId)
|
|
346
|
-
return if cache then table.clone(cache) else {}, 1
|
|
347
|
-
end
|
|
348
|
-
|
|
349
|
-
if flag == FLAG_FULL then
|
|
350
|
-
local count, lenBytes = Varint.read(src, absPos)
|
|
351
|
-
absPos += lenBytes
|
|
352
|
-
|
|
353
|
-
if maxCount and count > maxCount then
|
|
354
|
-
error(`[Lync] Map count {count} exceeds max {maxCount}`)
|
|
355
|
-
end
|
|
356
|
-
|
|
357
|
-
local result = {}
|
|
358
|
-
|
|
359
|
-
if keyDRead and valDRead and keySize and valSize then
|
|
360
|
-
for _ = 1, count do
|
|
361
|
-
local k = keyDRead(src, absPos)
|
|
362
|
-
local v = valDRead(src, absPos + keySize)
|
|
363
|
-
result[k] = v
|
|
364
|
-
absPos += entrySize :: number
|
|
365
|
-
end
|
|
366
|
-
else
|
|
367
|
-
for _ = 1, count do
|
|
368
|
-
local k, kn = readKey(src, absPos, refs)
|
|
369
|
-
absPos += kn
|
|
370
|
-
local v, vn = readVal(src, absPos, refs)
|
|
371
|
-
absPos += vn
|
|
372
|
-
result[k] = v
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
Baseline.setCache(deltaId, result)
|
|
377
|
-
return result, absPos - pos
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
local cache = Baseline.getCache(deltaId) :: { [any]: any }?
|
|
381
|
-
local result = if cache then table.clone(cache) else {}
|
|
382
|
-
|
|
383
|
-
local upsertN, unBytes = Varint.read(src, absPos)
|
|
384
|
-
absPos += unBytes
|
|
385
|
-
|
|
386
|
-
for _ = 1, upsertN do
|
|
387
|
-
local k, kn = readKey(src, absPos, refs)
|
|
388
|
-
absPos += kn
|
|
389
|
-
local v, vn = readVal(src, absPos, refs)
|
|
390
|
-
absPos += vn
|
|
391
|
-
result[k] = v
|
|
392
|
-
end
|
|
393
|
-
|
|
394
|
-
local removeN, rmBytes = Varint.read(src, absPos)
|
|
395
|
-
absPos += rmBytes
|
|
152
|
+
read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
|
|
153
|
+
local flag = readu8(src, pos)
|
|
396
154
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
absPos += kn
|
|
400
|
-
result[k] = nil
|
|
155
|
+
if flag == DELTA_UNCHANGED then
|
|
156
|
+
return {} :: any, 1
|
|
401
157
|
end
|
|
402
158
|
|
|
403
|
-
|
|
404
|
-
return
|
|
159
|
+
local value, consumed = innerMap.read(src, pos + 1, refs)
|
|
160
|
+
return value, 1 + consumed
|
|
405
161
|
end,
|
|
406
|
-
})
|
|
162
|
+
} :: any)
|
|
407
163
|
end
|
|
408
164
|
|
|
409
165
|
return table.freeze(Map)
|
|
@@ -1,48 +1,52 @@
|
|
|
1
1
|
--!strict
|
|
2
|
-
--!
|
|
2
|
+
--!optimize 2
|
|
3
3
|
-- Optional codec. 1 byte flag, value only if present.
|
|
4
4
|
|
|
5
|
-
local
|
|
5
|
+
local Base = require(script.Parent.Parent.Base)
|
|
6
6
|
local Types = require(script.Parent.Parent.Parent.Types)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
type Codec<T> = Types.Codec<T>
|
|
8
|
+
-- Private -------------------------------------------------------------
|
|
10
9
|
|
|
11
|
-
local alloc =
|
|
10
|
+
local alloc = Base.alloc
|
|
11
|
+
local writeu8 = buffer.writeu8
|
|
12
|
+
local readu8 = buffer.readu8
|
|
12
13
|
|
|
13
14
|
-- Public --------------------------------------------------------------
|
|
14
15
|
|
|
15
16
|
local Optional = {}
|
|
16
17
|
|
|
17
|
-
function Optional.optional(inner:
|
|
18
|
-
local
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
write = function(ch: ChannelState, value: any): ()
|
|
23
|
-
local c = ch.cursor
|
|
24
|
-
if c + 1 > ch.size then
|
|
18
|
+
function Optional.optional(inner: Types.InternalCodec<any>): Types.InternalCodec<any>
|
|
19
|
+
local codec: any = {
|
|
20
|
+
write = function(ch: Types.ChannelState, value: any): ()
|
|
21
|
+
local cursor = ch.cursor
|
|
22
|
+
if cursor + 1 > ch.size then
|
|
25
23
|
alloc(ch, 1)
|
|
26
24
|
end
|
|
27
25
|
if value == nil then
|
|
28
|
-
|
|
29
|
-
ch.cursor =
|
|
26
|
+
writeu8(ch.buff, cursor, 0)
|
|
27
|
+
ch.cursor = cursor + 1
|
|
30
28
|
else
|
|
31
|
-
|
|
32
|
-
ch.cursor =
|
|
33
|
-
|
|
29
|
+
writeu8(ch.buff, cursor, 1)
|
|
30
|
+
ch.cursor = cursor + 1
|
|
31
|
+
inner.write(ch, value)
|
|
34
32
|
end
|
|
35
33
|
end,
|
|
34
|
+
|
|
36
35
|
read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
|
|
37
|
-
local flag =
|
|
36
|
+
local flag = readu8(src, pos)
|
|
38
37
|
if flag == 0 then
|
|
39
38
|
return nil, 1
|
|
40
39
|
end
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return value, 1 + n
|
|
40
|
+
local value, consumed = inner.read(src, pos + 1, refs)
|
|
41
|
+
return value, 1 + consumed
|
|
44
42
|
end,
|
|
45
|
-
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (inner :: any)._hasUnknown then
|
|
46
|
+
codec._hasUnknown = true
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
return table.freeze(codec)
|
|
46
50
|
end
|
|
47
51
|
|
|
48
52
|
return table.freeze(Optional)
|