@axpecter/lync 2.1.2 → 2.2.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 +241 -349
- package/package.json +1 -1
- package/src/Types.luau +53 -13
- package/src/api/Group.luau +41 -51
- package/src/api/Packet.luau +145 -143
- package/src/api/Query.luau +204 -202
- package/src/api/Scope.luau +36 -38
- package/src/api/Signal.luau +68 -94
- package/src/codec/Base.luau +43 -23
- package/src/codec/composite/Array.luau +161 -152
- package/src/codec/composite/Map.luau +37 -53
- package/src/codec/composite/Optional.luau +15 -21
- package/src/codec/composite/Shared.luau +78 -41
- package/src/codec/composite/Struct.luau +64 -125
- package/src/codec/composite/Tagged.luau +15 -25
- package/src/codec/composite/Tuple.luau +15 -20
- package/src/codec/datatype/Buffer.luau +44 -51
- package/src/codec/datatype/CFrame.luau +72 -104
- package/src/codec/datatype/Color.luau +14 -10
- package/src/codec/datatype/Instance.luau +32 -42
- package/src/codec/datatype/IntVector.luau +24 -22
- package/src/codec/datatype/NumberRange.luau +21 -12
- package/src/codec/datatype/Ray.luau +13 -7
- package/src/codec/datatype/Rect.luau +13 -7
- package/src/codec/datatype/Region.luau +25 -22
- package/src/codec/datatype/Sequence.luau +144 -118
- package/src/codec/datatype/String.luau +29 -59
- package/src/codec/datatype/UDim.luau +29 -30
- package/src/codec/datatype/Vector.luau +89 -105
- package/src/codec/meta/Auto.luau +194 -246
- package/src/codec/meta/Bitfield.luau +37 -36
- package/src/codec/meta/Custom.luau +10 -10
- package/src/codec/meta/Enum.luau +8 -11
- package/src/codec/meta/Float.luau +16 -20
- package/src/codec/meta/Nothing.luau +2 -2
- package/src/codec/meta/Unknown.luau +22 -32
- package/src/codec/primitive/Bool.luau +9 -5
- package/src/codec/primitive/Float16.luau +13 -23
- package/src/codec/primitive/Int.luau +20 -28
- package/src/codec/primitive/Number.luau +6 -10
- package/src/codec/primitive/Signed.luau +32 -0
- package/src/codec/primitive/Varint.luau +59 -28
- package/src/index.d.ts +8 -2
- package/src/init.luau +118 -143
- package/src/internal/Baseline.luau +17 -18
- package/src/internal/Channel.luau +143 -212
- package/src/internal/Middleware.luau +37 -47
- package/src/internal/Pool.luau +10 -10
- package/src/internal/Registry.luau +38 -34
- package/src/internal/Transport.luau +28 -0
- package/src/internal/Util.luau +26 -0
- package/src/transport/Bridge.luau +32 -24
- package/src/transport/Client.luau +51 -53
- package/src/transport/Gate.luau +183 -113
- package/src/transport/Reader.luau +95 -66
- package/src/transport/Server.luau +130 -125
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!native
|
|
3
|
-
--
|
|
3
|
+
-- Array and deltaArray codecs. Bool elements are bit-packed.
|
|
4
4
|
|
|
5
5
|
local Base = require(script.Parent.Parent.Base)
|
|
6
|
+
local Channel = require(script.Parent.Parent.Parent.internal.Channel)
|
|
6
7
|
local Shared = require(script.Parent.Shared)
|
|
7
8
|
local Types = require(script.Parent.Parent.Parent.Types)
|
|
8
9
|
local Varint = require(script.Parent.Parent.primitive.Varint)
|
|
9
10
|
|
|
10
|
-
-- Private
|
|
11
|
+
-- Private ----------------------------------------------------------------
|
|
11
12
|
|
|
12
13
|
local alloc = Base.alloc
|
|
14
|
+
local writeByte = Channel.writeByte
|
|
13
15
|
local writeu8 = buffer.writeu8
|
|
14
16
|
local readu8 = buffer.readu8
|
|
15
17
|
local band = bit32.band
|
|
@@ -19,137 +21,149 @@ local lshift = bit32.lshift
|
|
|
19
21
|
local acquireScratch = Shared.acquireScratch
|
|
20
22
|
local releaseScratch = Shared.releaseScratch
|
|
21
23
|
local rangeEqual = Shared.rangeEqual
|
|
24
|
+
local snapshot = Shared.snapshot
|
|
22
25
|
local allocDeltaId = Shared.allocDeltaId
|
|
23
|
-
|
|
24
26
|
local DELTA_UNCHANGED = Shared.DELTA_UNCHANGED
|
|
25
|
-
local
|
|
26
|
-
local DELTA_MULTI_OFFSET = Shared.DELTA_MULTI_OFFSET
|
|
27
|
-
|
|
28
|
-
-- Public --------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
local Array = {}
|
|
31
|
-
|
|
32
|
-
function Array.array(element: Types.InternalCodec<any>, maxCount: number?): Types.InternalCodec<any>
|
|
33
|
-
local elemAny = element :: any
|
|
34
|
-
|
|
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
|
|
40
|
-
Varint.write(ch, len)
|
|
41
|
-
if len == 0 then
|
|
42
|
-
return
|
|
43
|
-
end
|
|
27
|
+
local DELTA_FULL = Shared.DELTA_FULL
|
|
44
28
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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,
|
|
29
|
+
local function makeBoolArray(
|
|
30
|
+
element: Types.InternalCodec<any>,
|
|
31
|
+
maxCount: number?
|
|
32
|
+
): Types.InternalCodec<any>
|
|
33
|
+
return table.freeze({
|
|
34
|
+
_isArray = true,
|
|
35
|
+
_element = element,
|
|
36
|
+
_maxCount = maxCount,
|
|
66
37
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return {}, lenBytes
|
|
74
|
-
end
|
|
38
|
+
write = function(ch: Types.ChannelState, value: { boolean }): ()
|
|
39
|
+
local len = #value
|
|
40
|
+
Varint.write(ch, len)
|
|
41
|
+
if len == 0 then
|
|
42
|
+
return
|
|
43
|
+
end
|
|
75
44
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
45
|
+
local byteCount = (len + 7) // 8
|
|
46
|
+
local cursor = ch.cursor
|
|
47
|
+
if cursor + byteCount > ch.size then
|
|
48
|
+
alloc(ch, byteCount)
|
|
49
|
+
end
|
|
50
|
+
local b = ch.buff
|
|
51
|
+
|
|
52
|
+
local idx = 1
|
|
53
|
+
for byteIdx = 0, byteCount - 1 do
|
|
54
|
+
local packed = 0
|
|
55
|
+
local remaining = len - idx + 1
|
|
56
|
+
local limit = if remaining >= 8 then 8 else remaining
|
|
57
|
+
for bit = 0, limit - 1 do
|
|
58
|
+
if value[idx] then
|
|
59
|
+
packed = bor(packed, lshift(1, bit))
|
|
87
60
|
end
|
|
61
|
+
idx += 1
|
|
88
62
|
end
|
|
63
|
+
writeu8(b, cursor + byteIdx, packed)
|
|
64
|
+
end
|
|
65
|
+
ch.cursor = cursor + byteCount
|
|
66
|
+
end,
|
|
89
67
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
68
|
+
read = function(src: buffer, pos: number, _refs: { Instance }?): ({ boolean }, number)
|
|
69
|
+
local len, lenBytes = Varint.read(src, pos)
|
|
70
|
+
if maxCount and len > maxCount then
|
|
71
|
+
error(`[Lync] Array.read: count {len} exceeds max {maxCount}`)
|
|
72
|
+
end
|
|
73
|
+
if len == 0 then
|
|
74
|
+
return {}, lenBytes
|
|
75
|
+
end
|
|
94
76
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
local elemDR = elemAny._directRead
|
|
77
|
+
local byteCount = (len + 7) // 8
|
|
78
|
+
local dataStart = pos + lenBytes
|
|
79
|
+
local result = table.create(len)
|
|
99
80
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
local
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
81
|
+
local idx = 1
|
|
82
|
+
for byteIdx = 0, byteCount - 1 do
|
|
83
|
+
local byte = readu8(src, dataStart + byteIdx)
|
|
84
|
+
local remaining = len - idx + 1
|
|
85
|
+
local limit = if remaining >= 8 then 8 else remaining
|
|
86
|
+
for bit = 0, limit - 1 do
|
|
87
|
+
result[idx] = band(byte, lshift(1, bit)) ~= 0
|
|
88
|
+
idx += 1
|
|
107
89
|
end
|
|
90
|
+
end
|
|
91
|
+
return result, lenBytes + byteCount
|
|
92
|
+
end,
|
|
93
|
+
})
|
|
94
|
+
end
|
|
108
95
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
96
|
+
local function makeDirectArray(
|
|
97
|
+
element: Types.InternalCodec<any>,
|
|
98
|
+
elemSize: number,
|
|
99
|
+
elemDW: (b: buffer, off: number, value: any) -> (),
|
|
100
|
+
elemDR: (b: buffer, off: number) -> any,
|
|
101
|
+
maxCount: number?
|
|
102
|
+
): Types.InternalCodec<any>
|
|
103
|
+
return table.freeze({
|
|
104
|
+
_isArray = true,
|
|
105
|
+
_element = element,
|
|
106
|
+
_maxCount = maxCount,
|
|
115
107
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
108
|
+
write = function(ch: Types.ChannelState, value: { any }): ()
|
|
109
|
+
local len = #value
|
|
110
|
+
Varint.write(ch, len)
|
|
111
|
+
if len == 0 then
|
|
112
|
+
return
|
|
113
|
+
end
|
|
121
114
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return {}, lenBytes
|
|
129
|
-
end
|
|
115
|
+
local payloadBytes = len * elemSize
|
|
116
|
+
local cursor = ch.cursor
|
|
117
|
+
if cursor + payloadBytes > ch.size then
|
|
118
|
+
alloc(ch, payloadBytes)
|
|
119
|
+
end
|
|
120
|
+
local b = ch.buff
|
|
130
121
|
|
|
131
|
-
|
|
132
|
-
|
|
122
|
+
local off = cursor
|
|
123
|
+
for i = 1, len do
|
|
124
|
+
elemDW(b, off, value[i])
|
|
125
|
+
off += elemSize
|
|
126
|
+
end
|
|
127
|
+
ch.cursor = cursor + payloadBytes
|
|
128
|
+
end,
|
|
133
129
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
130
|
+
read = function(src: buffer, pos: number, _refs: { Instance }?): ({ any }, number)
|
|
131
|
+
local len, lenBytes = Varint.read(src, pos)
|
|
132
|
+
if maxCount and len > maxCount then
|
|
133
|
+
error(`[Lync] Array.read: count {len} exceeds max {maxCount}`)
|
|
134
|
+
end
|
|
135
|
+
if len == 0 then
|
|
136
|
+
return {}, lenBytes
|
|
137
|
+
end
|
|
140
138
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
139
|
+
local payloadBytes = len * elemSize
|
|
140
|
+
local dataStart = pos + lenBytes
|
|
141
|
+
local remaining = buffer.len(src) - dataStart
|
|
142
|
+
if payloadBytes > remaining then
|
|
143
|
+
len = remaining // elemSize
|
|
144
|
+
payloadBytes = len * elemSize
|
|
145
|
+
end
|
|
145
146
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
local result = table.create(len)
|
|
148
|
+
local off = dataStart
|
|
149
|
+
for i = 1, len do
|
|
150
|
+
result[i] = elemDR(src, off)
|
|
151
|
+
off += elemSize
|
|
152
|
+
end
|
|
153
|
+
return result, lenBytes + payloadBytes
|
|
154
|
+
end,
|
|
155
|
+
})
|
|
156
|
+
end
|
|
150
157
|
|
|
151
|
-
|
|
158
|
+
local function makeGenericArray(
|
|
159
|
+
element: Types.InternalCodec<any>,
|
|
160
|
+
maxCount: number?
|
|
161
|
+
): Types.InternalCodec<any>
|
|
152
162
|
return table.freeze({
|
|
163
|
+
_isArray = true,
|
|
164
|
+
_element = element,
|
|
165
|
+
_maxCount = maxCount,
|
|
166
|
+
|
|
153
167
|
write = function(ch: Types.ChannelState, value: { any }): ()
|
|
154
168
|
local len = #value
|
|
155
169
|
Varint.write(ch, len)
|
|
@@ -161,7 +175,7 @@ function Array.array(element: Types.InternalCodec<any>, maxCount: number?): Type
|
|
|
161
175
|
read = function(src: buffer, pos: number, refs: { Instance }?): ({ any }, number)
|
|
162
176
|
local len, lenBytes = Varint.read(src, pos)
|
|
163
177
|
if maxCount and len > maxCount then
|
|
164
|
-
error(`[Lync] Array: count {len} exceeds max {maxCount}`)
|
|
178
|
+
error(`[Lync] Array.read: count {len} exceeds max {maxCount}`)
|
|
165
179
|
end
|
|
166
180
|
if len == 0 then
|
|
167
181
|
return {}, lenBytes
|
|
@@ -171,13 +185,34 @@ function Array.array(element: Types.InternalCodec<any>, maxCount: number?): Type
|
|
|
171
185
|
local total = lenBytes
|
|
172
186
|
for i = 1, len do
|
|
173
187
|
local v, consumed = element.read(src, pos + total, refs)
|
|
188
|
+
if consumed == 0 then
|
|
189
|
+
error(`[Lync] Array.read: element codec consumed 0 bytes at index {i}`)
|
|
190
|
+
end
|
|
174
191
|
result[i] = v
|
|
175
192
|
total += consumed
|
|
176
193
|
end
|
|
177
|
-
|
|
178
194
|
return result, total
|
|
179
195
|
end,
|
|
180
|
-
}
|
|
196
|
+
})
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
-- Public -----------------------------------------------------------------
|
|
200
|
+
|
|
201
|
+
local Array = {}
|
|
202
|
+
|
|
203
|
+
function Array.array(element: Types.InternalCodec<any>, maxCount: number?): Types.InternalCodec<any>
|
|
204
|
+
if element._isBool then
|
|
205
|
+
return makeBoolArray(element, maxCount)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
local elemSize = element._size
|
|
209
|
+
local elemDW = element._directWrite
|
|
210
|
+
local elemDR = element._directRead
|
|
211
|
+
if elemSize and elemDW and elemDR then
|
|
212
|
+
return makeDirectArray(element, elemSize, elemDW, elemDR, maxCount)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
return makeGenericArray(element, maxCount)
|
|
181
216
|
end
|
|
182
217
|
|
|
183
218
|
function Array.deltaArray(
|
|
@@ -194,73 +229,47 @@ function Array.deltaArray(
|
|
|
194
229
|
local cache = ch.deltas[deltaId]
|
|
195
230
|
|
|
196
231
|
if not cache then
|
|
197
|
-
|
|
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
|
|
232
|
+
writeByte(ch, DELTA_FULL)
|
|
204
233
|
|
|
205
234
|
local scratch = acquireScratch()
|
|
206
235
|
innerArray.write(scratch, value)
|
|
207
236
|
local snapLen = scratch.cursor
|
|
208
|
-
local snapBuf = buffer.create(snapLen)
|
|
209
|
-
buffer.copy(snapBuf, 0, scratch.buff, 0, snapLen)
|
|
210
237
|
|
|
211
|
-
ch.deltas[deltaId] = { raw =
|
|
238
|
+
ch.deltas[deltaId] = { raw = snapshot(scratch.buff, snapLen), len = snapLen }
|
|
212
239
|
innerArray.write(ch, value)
|
|
213
240
|
releaseScratch()
|
|
214
241
|
return
|
|
215
242
|
end
|
|
216
243
|
|
|
217
|
-
-- Compare against cache
|
|
218
244
|
local scratch = acquireScratch()
|
|
219
245
|
innerArray.write(scratch, value)
|
|
220
246
|
local scratchLen = scratch.cursor
|
|
221
|
-
local cachedLen = cache.len
|
|
222
247
|
|
|
223
248
|
if
|
|
224
|
-
scratchLen ==
|
|
249
|
+
scratchLen == cache.len
|
|
250
|
+
and rangeEqual(scratch.buff, 0, cache.raw, 0, scratchLen)
|
|
225
251
|
then
|
|
226
|
-
|
|
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
|
|
252
|
+
writeByte(ch, DELTA_UNCHANGED)
|
|
232
253
|
releaseScratch()
|
|
233
254
|
return
|
|
234
255
|
end
|
|
235
256
|
|
|
236
|
-
|
|
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
|
|
257
|
+
writeByte(ch, DELTA_FULL)
|
|
243
258
|
innerArray.write(ch, value)
|
|
244
259
|
|
|
245
|
-
|
|
246
|
-
buffer.copy(newBuf, 0, scratch.buff, 0, scratchLen)
|
|
247
|
-
cache.raw = newBuf
|
|
260
|
+
cache.raw = snapshot(scratch.buff, scratchLen)
|
|
248
261
|
cache.len = scratchLen
|
|
249
|
-
|
|
250
262
|
releaseScratch()
|
|
251
263
|
end,
|
|
252
264
|
|
|
253
265
|
read = function(src: buffer, pos: number, refs: { Instance }?): ({ any }, number)
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
if flag == DELTA_UNCHANGED then
|
|
257
|
-
return {} :: any, 1
|
|
266
|
+
if readu8(src, pos) == DELTA_UNCHANGED then
|
|
267
|
+
return {}, 1
|
|
258
268
|
end
|
|
259
|
-
|
|
260
269
|
local value, consumed = innerArray.read(src, pos + 1, refs)
|
|
261
270
|
return value, 1 + consumed
|
|
262
271
|
end,
|
|
263
|
-
}
|
|
272
|
+
})
|
|
264
273
|
end
|
|
265
274
|
|
|
266
275
|
return table.freeze(Array)
|
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!native
|
|
3
|
-
--
|
|
3
|
+
-- Map and deltaMap codecs.
|
|
4
4
|
|
|
5
5
|
local Base = require(script.Parent.Parent.Base)
|
|
6
|
+
local Channel = require(script.Parent.Parent.Parent.internal.Channel)
|
|
6
7
|
local Shared = require(script.Parent.Shared)
|
|
7
8
|
local Types = require(script.Parent.Parent.Parent.Types)
|
|
8
9
|
local Varint = require(script.Parent.Parent.primitive.Varint)
|
|
9
10
|
|
|
10
|
-
-- Private
|
|
11
|
+
-- Private ----------------------------------------------------------------
|
|
11
12
|
|
|
12
13
|
local alloc = Base.alloc
|
|
13
|
-
local
|
|
14
|
+
local writeByte = Channel.writeByte
|
|
14
15
|
local readu8 = buffer.readu8
|
|
15
16
|
|
|
16
17
|
local acquireScratch = Shared.acquireScratch
|
|
17
18
|
local releaseScratch = Shared.releaseScratch
|
|
18
19
|
local rangeEqual = Shared.rangeEqual
|
|
20
|
+
local snapshot = Shared.snapshot
|
|
19
21
|
local allocDeltaId = Shared.allocDeltaId
|
|
20
22
|
local DELTA_UNCHANGED = Shared.DELTA_UNCHANGED
|
|
23
|
+
local DELTA_FULL = Shared.DELTA_FULL
|
|
21
24
|
|
|
22
|
-
-- Public
|
|
25
|
+
-- Public -----------------------------------------------------------------
|
|
23
26
|
|
|
24
27
|
local Map = {}
|
|
25
28
|
|
|
@@ -28,9 +31,16 @@ function Map.map(
|
|
|
28
31
|
valueCodec: Types.InternalCodec<any>,
|
|
29
32
|
maxCount: number?
|
|
30
33
|
): Types.InternalCodec<any>
|
|
34
|
+
local fixedKey = keyCodec._size
|
|
35
|
+
local fixedValue = valueCodec._size
|
|
36
|
+
|
|
31
37
|
return table.freeze({
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
_isMap = true,
|
|
39
|
+
_keyCodec = keyCodec,
|
|
40
|
+
_valueCodec = valueCodec,
|
|
41
|
+
_maxCount = maxCount,
|
|
42
|
+
|
|
43
|
+
write = function(ch: Types.ChannelState, value: { [any]: any }): ()
|
|
34
44
|
local count = 0
|
|
35
45
|
for _ in value do
|
|
36
46
|
count += 1
|
|
@@ -41,11 +51,8 @@ function Map.map(
|
|
|
41
51
|
return
|
|
42
52
|
end
|
|
43
53
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
local vAny = valueCodec :: any
|
|
47
|
-
if kAny._size and vAny._size then
|
|
48
|
-
local entrySize = kAny._size + vAny._size
|
|
54
|
+
if fixedKey and fixedValue then
|
|
55
|
+
local entrySize = fixedKey + fixedValue
|
|
49
56
|
local cursor = ch.cursor
|
|
50
57
|
if cursor + count * entrySize > ch.size then
|
|
51
58
|
alloc(ch, count * entrySize)
|
|
@@ -58,26 +65,27 @@ function Map.map(
|
|
|
58
65
|
end
|
|
59
66
|
end,
|
|
60
67
|
|
|
61
|
-
read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
|
|
68
|
+
read = function(src: buffer, pos: number, refs: { Instance }?): ({ [any]: any }, number)
|
|
62
69
|
local count, lenBytes = Varint.read(src, pos)
|
|
63
70
|
if maxCount and count > maxCount then
|
|
64
|
-
error(`[Lync] Map: count {count} exceeds max {maxCount}`)
|
|
71
|
+
error(`[Lync] Map.read: count {count} exceeds max {maxCount}`)
|
|
65
72
|
end
|
|
66
73
|
|
|
67
74
|
local result: { [any]: any } = {}
|
|
68
75
|
local total = lenBytes
|
|
69
|
-
|
|
70
|
-
for _ = 1, count do
|
|
76
|
+
for i = 1, count do
|
|
71
77
|
local k, kc = keyCodec.read(src, pos + total, refs)
|
|
72
78
|
total += kc
|
|
73
79
|
local v, vc = valueCodec.read(src, pos + total, refs)
|
|
74
80
|
total += vc
|
|
81
|
+
if kc == 0 and vc == 0 then
|
|
82
|
+
error(`[Lync] Map.read: zero-byte entry at index {i}`)
|
|
83
|
+
end
|
|
75
84
|
result[k] = v
|
|
76
85
|
end
|
|
77
|
-
|
|
78
86
|
return result, total
|
|
79
87
|
end,
|
|
80
|
-
}
|
|
88
|
+
})
|
|
81
89
|
end
|
|
82
90
|
|
|
83
91
|
function Map.deltaMap(
|
|
@@ -91,24 +99,17 @@ function Map.deltaMap(
|
|
|
91
99
|
return table.freeze({
|
|
92
100
|
_isDelta = true,
|
|
93
101
|
|
|
94
|
-
write = function(ch: Types.ChannelState, value: any): ()
|
|
102
|
+
write = function(ch: Types.ChannelState, value: { [any]: any }): ()
|
|
95
103
|
local cache = ch.deltas[deltaId]
|
|
96
104
|
|
|
97
105
|
if not cache then
|
|
98
|
-
|
|
99
|
-
if cursor + 1 > ch.size then
|
|
100
|
-
alloc(ch, 1)
|
|
101
|
-
end
|
|
102
|
-
writeu8(ch.buff, cursor, 3) -- FLAG_FULL
|
|
103
|
-
ch.cursor = cursor + 1
|
|
106
|
+
writeByte(ch, DELTA_FULL)
|
|
104
107
|
|
|
105
108
|
local scratch = acquireScratch()
|
|
106
109
|
innerMap.write(scratch, value)
|
|
107
110
|
local snapLen = scratch.cursor
|
|
108
|
-
local snapBuf = buffer.create(snapLen)
|
|
109
|
-
buffer.copy(snapBuf, 0, scratch.buff, 0, snapLen)
|
|
110
111
|
|
|
111
|
-
ch.deltas[deltaId] = { raw =
|
|
112
|
+
ch.deltas[deltaId] = { raw = snapshot(scratch.buff, snapLen), len = snapLen }
|
|
112
113
|
innerMap.write(ch, value)
|
|
113
114
|
releaseScratch()
|
|
114
115
|
return
|
|
@@ -117,49 +118,32 @@ function Map.deltaMap(
|
|
|
117
118
|
local scratch = acquireScratch()
|
|
118
119
|
innerMap.write(scratch, value)
|
|
119
120
|
local scratchLen = scratch.cursor
|
|
120
|
-
local cachedLen = cache.len
|
|
121
121
|
|
|
122
122
|
if
|
|
123
|
-
scratchLen ==
|
|
123
|
+
scratchLen == cache.len
|
|
124
|
+
and rangeEqual(scratch.buff, 0, cache.raw, 0, scratchLen)
|
|
124
125
|
then
|
|
125
|
-
|
|
126
|
-
if cursor + 1 > ch.size then
|
|
127
|
-
alloc(ch, 1)
|
|
128
|
-
end
|
|
129
|
-
writeu8(ch.buff, cursor, DELTA_UNCHANGED)
|
|
130
|
-
ch.cursor = cursor + 1
|
|
126
|
+
writeByte(ch, DELTA_UNCHANGED)
|
|
131
127
|
releaseScratch()
|
|
132
128
|
return
|
|
133
129
|
end
|
|
134
130
|
|
|
135
|
-
|
|
136
|
-
local cursor = ch.cursor
|
|
137
|
-
if cursor + 1 > ch.size then
|
|
138
|
-
alloc(ch, 1)
|
|
139
|
-
end
|
|
140
|
-
writeu8(ch.buff, cursor, 3) -- FLAG_FULL
|
|
141
|
-
ch.cursor = cursor + 1
|
|
131
|
+
writeByte(ch, DELTA_FULL)
|
|
142
132
|
innerMap.write(ch, value)
|
|
143
133
|
|
|
144
|
-
|
|
145
|
-
buffer.copy(newBuf, 0, scratch.buff, 0, scratchLen)
|
|
146
|
-
cache.raw = newBuf
|
|
134
|
+
cache.raw = snapshot(scratch.buff, scratchLen)
|
|
147
135
|
cache.len = scratchLen
|
|
148
|
-
|
|
149
136
|
releaseScratch()
|
|
150
137
|
end,
|
|
151
138
|
|
|
152
|
-
read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if flag == DELTA_UNCHANGED then
|
|
156
|
-
return {} :: any, 1
|
|
139
|
+
read = function(src: buffer, pos: number, refs: { Instance }?): ({ [any]: any }, number)
|
|
140
|
+
if readu8(src, pos) == DELTA_UNCHANGED then
|
|
141
|
+
return {}, 1
|
|
157
142
|
end
|
|
158
|
-
|
|
159
143
|
local value, consumed = innerMap.read(src, pos + 1, refs)
|
|
160
144
|
return value, 1 + consumed
|
|
161
145
|
end,
|
|
162
|
-
}
|
|
146
|
+
})
|
|
163
147
|
end
|
|
164
148
|
|
|
165
149
|
return table.freeze(Map)
|
|
@@ -1,40 +1,35 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!optimize 2
|
|
3
|
-
-- Optional codec. 1
|
|
3
|
+
-- Optional codec. 1-byte present/absent flag, value only if present.
|
|
4
4
|
|
|
5
|
-
local
|
|
5
|
+
local Channel = require(script.Parent.Parent.Parent.internal.Channel)
|
|
6
6
|
local Types = require(script.Parent.Parent.Parent.Types)
|
|
7
7
|
|
|
8
|
-
-- Private
|
|
8
|
+
-- Private ----------------------------------------------------------------
|
|
9
9
|
|
|
10
|
-
local
|
|
11
|
-
local writeu8 = buffer.writeu8
|
|
10
|
+
local writeByte = Channel.writeByte
|
|
12
11
|
local readu8 = buffer.readu8
|
|
13
12
|
|
|
14
|
-
-- Public
|
|
13
|
+
-- Public -----------------------------------------------------------------
|
|
15
14
|
|
|
16
15
|
local Optional = {}
|
|
17
16
|
|
|
18
17
|
function Optional.optional(inner: Types.InternalCodec<any>): Types.InternalCodec<any>
|
|
19
|
-
local codec: any = {
|
|
18
|
+
local codec: Types.InternalCodec<any> = {
|
|
19
|
+
_isOptional = true,
|
|
20
|
+
_inner = inner,
|
|
21
|
+
|
|
20
22
|
write = function(ch: Types.ChannelState, value: any): ()
|
|
21
|
-
local cursor = ch.cursor
|
|
22
|
-
if cursor + 1 > ch.size then
|
|
23
|
-
alloc(ch, 1)
|
|
24
|
-
end
|
|
25
23
|
if value == nil then
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
else
|
|
29
|
-
writeu8(ch.buff, cursor, 1)
|
|
30
|
-
ch.cursor = cursor + 1
|
|
31
|
-
inner.write(ch, value)
|
|
24
|
+
writeByte(ch, 0)
|
|
25
|
+
return
|
|
32
26
|
end
|
|
27
|
+
writeByte(ch, 1)
|
|
28
|
+
inner.write(ch, value)
|
|
33
29
|
end,
|
|
34
30
|
|
|
35
31
|
read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
|
|
36
|
-
|
|
37
|
-
if flag == 0 then
|
|
32
|
+
if readu8(src, pos) == 0 then
|
|
38
33
|
return nil, 1
|
|
39
34
|
end
|
|
40
35
|
local value, consumed = inner.read(src, pos + 1, refs)
|
|
@@ -42,10 +37,9 @@ function Optional.optional(inner: Types.InternalCodec<any>): Types.InternalCodec
|
|
|
42
37
|
end,
|
|
43
38
|
}
|
|
44
39
|
|
|
45
|
-
if
|
|
40
|
+
if inner._hasUnknown then
|
|
46
41
|
codec._hasUnknown = true
|
|
47
42
|
end
|
|
48
|
-
|
|
49
43
|
return table.freeze(codec)
|
|
50
44
|
end
|
|
51
45
|
|