@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
|
@@ -1,222 +1,108 @@
|
|
|
1
1
|
--!strict
|
|
2
|
-
--!
|
|
2
|
+
--!optimize 2
|
|
3
3
|
-- Discriminated union codec. u8 variant tag + variant payload.
|
|
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>
|
|
10
|
-
type InternalCodec<T> = Types.InternalCodec<T>
|
|
8
|
+
-- Private -------------------------------------------------------------
|
|
11
9
|
|
|
12
|
-
local alloc =
|
|
10
|
+
local alloc = Base.alloc
|
|
11
|
+
local writeu8 = buffer.writeu8
|
|
12
|
+
local readu8 = buffer.readu8
|
|
13
13
|
|
|
14
14
|
-- Public --------------------------------------------------------------
|
|
15
15
|
|
|
16
16
|
local Tagged = {}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
function Tagged.define(
|
|
19
|
+
tagField: string,
|
|
20
|
+
variants: { [string]: Types.InternalCodec<any> }
|
|
21
|
+
): Types.InternalCodec<any>
|
|
22
|
+
if tagField == "" then
|
|
23
|
+
error("[Lync] Lync.tagged: tagField cannot be empty")
|
|
22
24
|
end
|
|
23
25
|
|
|
24
|
-
local names
|
|
26
|
+
local names: { string } = {}
|
|
25
27
|
for name in variants do
|
|
26
|
-
if #name == 0 then
|
|
27
|
-
error("[Lync] Tagged union variant name must not be empty")
|
|
28
|
-
end
|
|
29
28
|
table.insert(names, name)
|
|
30
29
|
end
|
|
31
30
|
table.sort(names)
|
|
32
31
|
|
|
33
|
-
local
|
|
34
|
-
if
|
|
35
|
-
error("[Lync]
|
|
32
|
+
local variantCount = #names
|
|
33
|
+
if variantCount == 0 then
|
|
34
|
+
error("[Lync] Lync.tagged: requires at least one variant")
|
|
36
35
|
end
|
|
37
|
-
if
|
|
38
|
-
error(
|
|
36
|
+
if variantCount > 256 then
|
|
37
|
+
error("[Lync] Lync.tagged: exceeds 256 variants")
|
|
39
38
|
end
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
local
|
|
43
|
-
local
|
|
44
|
-
local
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
tagNames[i] = name
|
|
56
|
-
|
|
57
|
-
local size = codec._size
|
|
58
|
-
tagSizes[i] = size
|
|
59
|
-
|
|
60
|
-
if size ~= uniformSize then
|
|
61
|
-
uniformSize = nil
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
local dw = codec._directWrite
|
|
65
|
-
local dr = codec._directRead
|
|
66
|
-
if dw and dr and size then
|
|
67
|
-
directWrites[i] = dw
|
|
68
|
-
directReads[i] = dr
|
|
69
|
-
else
|
|
70
|
-
allDirect = false
|
|
40
|
+
-- Build lookup tables
|
|
41
|
+
local nameToTag: { [string]: number } = {}
|
|
42
|
+
local tagToCodec = table.create(variantCount)
|
|
43
|
+
local tagToName = table.create(variantCount)
|
|
44
|
+
local hasUnknown = false
|
|
45
|
+
|
|
46
|
+
for i = 1, variantCount do
|
|
47
|
+
local name = names[i]
|
|
48
|
+
local codec = variants[name]
|
|
49
|
+
nameToTag[name] = i - 1
|
|
50
|
+
tagToCodec[i] = codec
|
|
51
|
+
tagToName[i] = name
|
|
52
|
+
if (codec :: any)._hasUnknown then
|
|
53
|
+
hasUnknown = true
|
|
71
54
|
end
|
|
72
55
|
end
|
|
73
56
|
|
|
74
57
|
table.freeze(nameToTag)
|
|
75
|
-
table.freeze(
|
|
76
|
-
table.freeze(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
-- If uniform size, expose _directWrite/_directRead for parent struct/array
|
|
86
|
-
if fixedSize then
|
|
87
|
-
return table.freeze({
|
|
88
|
-
_size = fixedSize,
|
|
89
|
-
_directWrite = function(b: buffer, offset: number, value: any): ()
|
|
90
|
-
local tag = nameToTag[value[tagField]]
|
|
91
|
-
if not tag then
|
|
92
|
-
error(`[Lync] Unknown variant: {value[tagField]}`)
|
|
93
|
-
end
|
|
94
|
-
buffer.writeu8(b, offset, tag - 1)
|
|
95
|
-
directWrites[tag](b, offset + 1, value)
|
|
96
|
-
end,
|
|
97
|
-
_directRead = function(b: buffer, offset: number): any
|
|
98
|
-
local tag = buffer.readu8(b, offset) + 1
|
|
99
|
-
local name = tagNames[tag]
|
|
100
|
-
if not name then
|
|
101
|
-
error(`[Lync] Unknown variant index: {tag - 1}`)
|
|
102
|
-
end
|
|
103
|
-
local data = directReads[tag](b, offset + 1)
|
|
104
|
-
if type(data) == "table" then
|
|
105
|
-
data[tagField] = name
|
|
106
|
-
end
|
|
107
|
-
return data
|
|
108
|
-
end,
|
|
109
|
-
write = function(ch: ChannelState, value: any): ()
|
|
110
|
-
local tag = nameToTag[value[tagField]]
|
|
111
|
-
if not tag then
|
|
112
|
-
error(`[Lync] Unknown variant: {value[tagField]}`)
|
|
113
|
-
end
|
|
114
|
-
local c = ch.cursor
|
|
115
|
-
if c + (fixedSize :: number) > ch.size then
|
|
116
|
-
alloc(ch, fixedSize :: number)
|
|
117
|
-
end
|
|
118
|
-
local b = ch.buff
|
|
119
|
-
buffer.writeu8(b, c, tag - 1)
|
|
120
|
-
directWrites[tag](b, c + 1, value)
|
|
121
|
-
ch.cursor = c + (fixedSize :: number)
|
|
122
|
-
end,
|
|
123
|
-
read = function(src: buffer, pos: number, _refs: { Instance }?): (any, number)
|
|
124
|
-
local tag = buffer.readu8(src, pos) + 1
|
|
125
|
-
local name = tagNames[tag]
|
|
126
|
-
if not name then
|
|
127
|
-
error(`[Lync] Unknown variant index: {tag - 1}`)
|
|
128
|
-
end
|
|
129
|
-
local data = directReads[tag](src, pos + 1)
|
|
130
|
-
if type(data) == "table" then
|
|
131
|
-
data[tagField] = name
|
|
132
|
-
end
|
|
133
|
-
return data, fixedSize :: number
|
|
134
|
-
end,
|
|
135
|
-
})
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
-- Non-uniform sizes but all have direct: use direct dispatch internally
|
|
139
|
-
local fieldSizes = table.clone(tagSizes) :: { number }
|
|
140
|
-
table.freeze(fieldSizes)
|
|
141
|
-
|
|
142
|
-
return table.freeze({
|
|
143
|
-
_size = nil,
|
|
144
|
-
write = function(ch: ChannelState, value: any): ()
|
|
145
|
-
local tag = nameToTag[value[tagField]]
|
|
146
|
-
if not tag then
|
|
147
|
-
error(`[Lync] Unknown variant: {value[tagField]}`)
|
|
148
|
-
end
|
|
149
|
-
local varSize = fieldSizes[tag]
|
|
150
|
-
local totalNeeded = 1 + varSize
|
|
151
|
-
local c = ch.cursor
|
|
152
|
-
if c + totalNeeded > ch.size then
|
|
153
|
-
alloc(ch, totalNeeded)
|
|
154
|
-
end
|
|
155
|
-
local b = ch.buff
|
|
156
|
-
buffer.writeu8(b, c, tag - 1)
|
|
157
|
-
directWrites[tag](b, c + 1, value)
|
|
158
|
-
ch.cursor = c + totalNeeded
|
|
159
|
-
end,
|
|
160
|
-
read = function(src: buffer, pos: number, _refs: { Instance }?): (any, number)
|
|
161
|
-
local tag = buffer.readu8(src, pos) + 1
|
|
162
|
-
local name = tagNames[tag]
|
|
163
|
-
if not name then
|
|
164
|
-
error(`[Lync] Unknown variant index: {tag - 1}`)
|
|
165
|
-
end
|
|
166
|
-
local data = directReads[tag](src, pos + 1)
|
|
167
|
-
if type(data) == "table" then
|
|
168
|
-
data[tagField] = name
|
|
169
|
-
end
|
|
170
|
-
return data, 1 + fieldSizes[tag]
|
|
171
|
-
end,
|
|
172
|
-
})
|
|
173
|
-
end
|
|
58
|
+
table.freeze(tagToCodec)
|
|
59
|
+
table.freeze(tagToName)
|
|
60
|
+
|
|
61
|
+
local codec: any = {
|
|
62
|
+
write = function(ch: Types.ChannelState, value: any): ()
|
|
63
|
+
local name = value[tagField]
|
|
64
|
+
if name == nil then
|
|
65
|
+
error(`[Lync] Tagged: missing tagField "{tagField}" in value`)
|
|
66
|
+
end
|
|
174
67
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
writeFns[i] = tagCodecs[i].write
|
|
179
|
-
readFns[i] = tagCodecs[i].read
|
|
180
|
-
end
|
|
181
|
-
table.freeze(writeFns)
|
|
182
|
-
table.freeze(readFns)
|
|
183
|
-
|
|
184
|
-
return table.freeze({
|
|
185
|
-
_size = fixedSize,
|
|
186
|
-
write = function(ch: ChannelState, value: any): ()
|
|
187
|
-
local tag = nameToTag[value[tagField]]
|
|
188
|
-
if not tag then
|
|
189
|
-
error(`[Lync] Unknown variant: {value[tagField]}`)
|
|
68
|
+
local tag = nameToTag[name]
|
|
69
|
+
if tag == nil then
|
|
70
|
+
error(`[Lync] Tagged: unknown variant "{name}"`)
|
|
190
71
|
end
|
|
191
72
|
|
|
192
|
-
local
|
|
193
|
-
if
|
|
194
|
-
alloc(ch, 1 + variantSize)
|
|
195
|
-
else
|
|
73
|
+
local cursor = ch.cursor
|
|
74
|
+
if cursor + 1 > ch.size then
|
|
196
75
|
alloc(ch, 1)
|
|
197
76
|
end
|
|
77
|
+
writeu8(ch.buff, cursor, tag)
|
|
78
|
+
ch.cursor = cursor + 1
|
|
198
79
|
|
|
199
|
-
|
|
200
|
-
buffer.writeu8(ch.buff, c, tag - 1)
|
|
201
|
-
ch.cursor = c + 1
|
|
202
|
-
writeFns[tag](ch, value)
|
|
80
|
+
tagToCodec[tag + 1].write(ch, value)
|
|
203
81
|
end,
|
|
82
|
+
|
|
204
83
|
read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
|
|
205
|
-
local tag =
|
|
206
|
-
local
|
|
207
|
-
if not
|
|
208
|
-
error(`[Lync]
|
|
84
|
+
local tag = readu8(src, pos)
|
|
85
|
+
local varCodec = tagToCodec[tag + 1]
|
|
86
|
+
if not varCodec then
|
|
87
|
+
error(`[Lync] Tagged: unknown tag {tag}`)
|
|
209
88
|
end
|
|
210
89
|
|
|
211
|
-
local
|
|
90
|
+
local name = tagToName[tag + 1]
|
|
91
|
+
local data, consumed = varCodec.read(src, pos + 1, refs)
|
|
212
92
|
|
|
93
|
+
-- Caller needs the tag field to discriminate the union
|
|
213
94
|
if type(data) == "table" then
|
|
214
95
|
data[tagField] = name
|
|
215
96
|
end
|
|
216
97
|
|
|
217
|
-
return data, 1 +
|
|
98
|
+
return data, 1 + consumed
|
|
218
99
|
end,
|
|
219
|
-
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if hasUnknown then
|
|
103
|
+
codec._hasUnknown = true
|
|
104
|
+
end
|
|
105
|
+
return table.freeze(codec)
|
|
220
106
|
end
|
|
221
107
|
|
|
222
108
|
return table.freeze(Tagged)
|
|
@@ -1,145 +1,131 @@
|
|
|
1
1
|
--!strict
|
|
2
|
-
--!
|
|
2
|
+
--!optimize 2
|
|
3
3
|
-- Positional ordered codec. Like struct but indexed, not keyed.
|
|
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>
|
|
10
|
-
type InternalCodec<T> = Types.InternalCodec<T>
|
|
8
|
+
-- Private -------------------------------------------------------------
|
|
11
9
|
|
|
12
|
-
local alloc =
|
|
10
|
+
local alloc = Base.alloc
|
|
13
11
|
|
|
14
12
|
-- Public --------------------------------------------------------------
|
|
15
13
|
|
|
16
14
|
local Tuple = {}
|
|
17
15
|
|
|
18
|
-
function Tuple.define(...:
|
|
16
|
+
function Tuple.define(...: Types.InternalCodec<any>): Types.InternalCodec<any>
|
|
19
17
|
local codecs = { ... }
|
|
20
18
|
local count = #codecs
|
|
21
19
|
if count == 0 then
|
|
22
|
-
error("[Lync]
|
|
20
|
+
error("[Lync] Lync.tuple: requires at least one codec")
|
|
23
21
|
end
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
local
|
|
28
|
-
local
|
|
29
|
-
local directWrites = table.create(count) :: { any }
|
|
30
|
-
local directReads = table.create(count) :: { any }
|
|
31
|
-
local fieldSizes = table.create(count) :: { number }
|
|
23
|
+
-- Check if all codecs are direct
|
|
24
|
+
local allDirect = true
|
|
25
|
+
local totalSize = 0
|
|
26
|
+
local hasUnknown = false
|
|
32
27
|
|
|
33
28
|
for i = 1, count do
|
|
34
|
-
local
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
fieldSizes[i] = size
|
|
41
|
-
directWrites[i] = dw
|
|
42
|
-
directReads[i] = dr
|
|
43
|
-
totalSize += size
|
|
29
|
+
local c = codecs[i] :: any
|
|
30
|
+
if c._hasUnknown then
|
|
31
|
+
hasUnknown = true
|
|
32
|
+
end
|
|
33
|
+
if not c._size or not c._directWrite or not c._directRead then
|
|
34
|
+
allDirect = false
|
|
44
35
|
else
|
|
45
|
-
|
|
46
|
-
if size then
|
|
47
|
-
totalSize += size
|
|
48
|
-
else
|
|
49
|
-
totalSize = nil :: any
|
|
50
|
-
end
|
|
51
|
-
break
|
|
36
|
+
totalSize += c._size
|
|
52
37
|
end
|
|
53
38
|
end
|
|
54
39
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
40
|
+
table.freeze(codecs)
|
|
41
|
+
|
|
42
|
+
if allDirect then
|
|
43
|
+
-- Build precomputed offsets
|
|
44
|
+
local offsets = table.create(count)
|
|
45
|
+
local directWrites = table.create(count)
|
|
46
|
+
local directReads = table.create(count)
|
|
47
|
+
local cursor = 0
|
|
48
|
+
|
|
58
49
|
for i = 1, count do
|
|
59
|
-
local
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
break
|
|
65
|
-
end
|
|
50
|
+
local c = codecs[i] :: any
|
|
51
|
+
offsets[i] = cursor
|
|
52
|
+
directWrites[i] = c._directWrite
|
|
53
|
+
directReads[i] = c._directRead
|
|
54
|
+
cursor += c._size
|
|
66
55
|
end
|
|
67
|
-
end
|
|
68
56
|
|
|
69
|
-
|
|
57
|
+
table.freeze(offsets)
|
|
70
58
|
table.freeze(directWrites)
|
|
71
59
|
table.freeze(directReads)
|
|
72
|
-
table.freeze(fieldSizes)
|
|
73
60
|
|
|
74
|
-
local
|
|
75
|
-
|
|
76
|
-
directWrites[i](b, c, value[i])
|
|
77
|
-
c += fieldSizes[i]
|
|
78
|
-
end
|
|
79
|
-
end
|
|
61
|
+
local codec: any = {
|
|
62
|
+
_size = totalSize,
|
|
80
63
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
c += fieldSizes[i]
|
|
87
|
-
end
|
|
88
|
-
return result
|
|
89
|
-
end
|
|
64
|
+
_directWrite = function(b: buffer, off: number, value: any): ()
|
|
65
|
+
for i = 1, count do
|
|
66
|
+
directWrites[i](b, off + offsets[i], value[i])
|
|
67
|
+
end
|
|
68
|
+
end,
|
|
90
69
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
70
|
+
_directRead = function(b: buffer, off: number): any
|
|
71
|
+
local result = table.create(count)
|
|
72
|
+
for i = 1, count do
|
|
73
|
+
result[i] = directReads[i](b, off + offsets[i])
|
|
74
|
+
end
|
|
75
|
+
return result
|
|
76
|
+
end,
|
|
77
|
+
|
|
78
|
+
write = function(ch: Types.ChannelState, value: any): ()
|
|
96
79
|
local c = ch.cursor
|
|
97
80
|
if c + totalSize > ch.size then
|
|
98
81
|
alloc(ch, totalSize)
|
|
99
82
|
end
|
|
100
|
-
|
|
83
|
+
local b = ch.buff
|
|
84
|
+
for i = 1, count do
|
|
85
|
+
directWrites[i](b, c + offsets[i], value[i])
|
|
86
|
+
end
|
|
101
87
|
ch.cursor = c + totalSize
|
|
102
88
|
end,
|
|
103
|
-
|
|
104
|
-
|
|
89
|
+
|
|
90
|
+
read = function(src: buffer, pos: number, _refs: { Instance }?): (any, number)
|
|
91
|
+
local result = table.create(count)
|
|
92
|
+
for i = 1, count do
|
|
93
|
+
result[i] = directReads[i](src, pos + offsets[i])
|
|
94
|
+
end
|
|
95
|
+
return result, totalSize
|
|
105
96
|
end,
|
|
106
|
-
}
|
|
107
|
-
end
|
|
97
|
+
}
|
|
108
98
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
readFns[i] = codecs[i].read
|
|
99
|
+
if hasUnknown then
|
|
100
|
+
codec._hasUnknown = true
|
|
101
|
+
end
|
|
102
|
+
return table.freeze(codec)
|
|
114
103
|
end
|
|
115
|
-
table.freeze(writeFns)
|
|
116
|
-
table.freeze(readFns)
|
|
117
|
-
|
|
118
|
-
local hasFixedTotal = totalSize ~= nil
|
|
119
104
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
write = function(ch: ChannelState, value:
|
|
123
|
-
if hasFixedTotal then
|
|
124
|
-
alloc(ch, totalSize :: number)
|
|
125
|
-
end
|
|
105
|
+
-- Generic path
|
|
106
|
+
local codec: any = {
|
|
107
|
+
write = function(ch: Types.ChannelState, value: any): ()
|
|
126
108
|
for i = 1, count do
|
|
127
|
-
|
|
109
|
+
codecs[i].write(ch, value[i])
|
|
128
110
|
end
|
|
129
111
|
end,
|
|
130
|
-
read = function(src: buffer, pos: number, refs: { Instance }?): ({ any }, number)
|
|
131
|
-
local result = table.create(count)
|
|
132
|
-
local absPos = pos
|
|
133
112
|
|
|
113
|
+
read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
|
|
114
|
+
local result = table.create(count)
|
|
115
|
+
local total = 0
|
|
134
116
|
for i = 1, count do
|
|
135
|
-
local
|
|
136
|
-
result[i] =
|
|
137
|
-
|
|
117
|
+
local v, consumed = codecs[i].read(src, pos + total, refs)
|
|
118
|
+
result[i] = v
|
|
119
|
+
total += consumed
|
|
138
120
|
end
|
|
139
|
-
|
|
140
|
-
return result, absPos - pos
|
|
121
|
+
return result, total
|
|
141
122
|
end,
|
|
142
|
-
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if hasUnknown then
|
|
126
|
+
codec._hasUnknown = true
|
|
127
|
+
end
|
|
128
|
+
return table.freeze(codec)
|
|
143
129
|
end
|
|
144
130
|
|
|
145
131
|
return table.freeze(Tuple)
|
|
@@ -1,45 +1,73 @@
|
|
|
1
1
|
--!strict
|
|
2
|
-
--!
|
|
3
|
-
-- Raw buffer codec with varint length prefix.
|
|
2
|
+
--!optimize 2
|
|
3
|
+
-- Raw buffer codec with dense-prefix-varint length prefix.
|
|
4
4
|
|
|
5
|
-
local
|
|
5
|
+
local Base = require(script.Parent.Parent.Base)
|
|
6
6
|
local Types = require(script.Parent.Parent.Parent.Types)
|
|
7
7
|
local Varint = require(script.Parent.Parent.primitive.Varint)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
-- Private -------------------------------------------------------------
|
|
10
10
|
|
|
11
|
-
local alloc =
|
|
11
|
+
local alloc = Base.alloc
|
|
12
|
+
local INLINE = Varint.INLINE_MAX
|
|
12
13
|
|
|
13
14
|
-- Public --------------------------------------------------------------
|
|
14
15
|
|
|
15
|
-
local
|
|
16
|
+
local BufferCodec = {}
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
BufferCodec.buff = table.freeze({
|
|
19
|
+
_typeCheck = "buffer",
|
|
20
|
+
|
|
21
|
+
write = function(ch: Types.ChannelState, value: buffer): ()
|
|
19
22
|
local len = buffer.len(value)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if
|
|
23
|
-
|
|
23
|
+
local cursor = ch.cursor
|
|
24
|
+
|
|
25
|
+
if len <= INLINE then
|
|
26
|
+
if cursor + 1 + len > ch.size then
|
|
27
|
+
alloc(ch, 1 + len)
|
|
28
|
+
end
|
|
29
|
+
local b = ch.buff
|
|
30
|
+
buffer.writeu8(b, cursor, len)
|
|
31
|
+
if len > 0 then
|
|
32
|
+
buffer.copy(b, cursor + 1, value, 0, len)
|
|
33
|
+
end
|
|
34
|
+
ch.cursor = cursor + 1 + len
|
|
35
|
+
else
|
|
36
|
+
Varint.write(ch, len)
|
|
37
|
+
cursor = ch.cursor
|
|
38
|
+
if cursor + len > ch.size then
|
|
39
|
+
alloc(ch, len)
|
|
40
|
+
end
|
|
41
|
+
buffer.copy(ch.buff, cursor, value, 0, len)
|
|
42
|
+
ch.cursor = cursor + len
|
|
24
43
|
end
|
|
25
|
-
buffer.copy(ch.buff, c, value, 0, len)
|
|
26
|
-
ch.cursor = c + len
|
|
27
44
|
end,
|
|
45
|
+
|
|
28
46
|
read = function(src: buffer, pos: number, _refs: { Instance }?): (buffer, number)
|
|
29
|
-
local
|
|
47
|
+
local b0 = buffer.readu8(src, pos)
|
|
48
|
+
local len: number
|
|
49
|
+
local lenBytes: number
|
|
50
|
+
|
|
51
|
+
if b0 <= INLINE then
|
|
52
|
+
len = b0
|
|
53
|
+
lenBytes = 1
|
|
54
|
+
else
|
|
55
|
+
len, lenBytes = Varint.read(src, pos)
|
|
56
|
+
end
|
|
57
|
+
|
|
30
58
|
if len == 0 then
|
|
31
59
|
return buffer.create(0), lenBytes
|
|
32
60
|
end
|
|
33
61
|
|
|
34
|
-
local
|
|
35
|
-
if len >
|
|
36
|
-
error(
|
|
62
|
+
local dataStart = pos + lenBytes
|
|
63
|
+
if dataStart + len > buffer.len(src) then
|
|
64
|
+
error("[Lync] Buffer: length exceeds remaining buffer")
|
|
37
65
|
end
|
|
38
66
|
|
|
39
67
|
local out = buffer.create(len)
|
|
40
|
-
buffer.copy(out, 0, src,
|
|
68
|
+
buffer.copy(out, 0, src, dataStart, len)
|
|
41
69
|
return out, lenBytes + len
|
|
42
70
|
end,
|
|
43
|
-
})
|
|
71
|
+
} :: any)
|
|
44
72
|
|
|
45
|
-
return table.freeze(
|
|
73
|
+
return table.freeze(BufferCodec)
|