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