@axpecter/lync 2.2.1 → 2.3.2
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 +109 -147
- package/package.json +1 -1
- package/src/Types.luau +34 -22
- package/src/api/Group.luau +40 -33
- package/src/api/Packet.luau +140 -66
- package/src/api/Query.luau +103 -65
- package/src/api/Scope.luau +26 -10
- package/src/api/Signal.luau +43 -52
- package/src/codec/Base.luau +28 -14
- package/src/codec/composite/Array.luau +296 -115
- package/src/codec/composite/Map.luau +377 -57
- package/src/codec/composite/Optional.luau +10 -2
- package/src/codec/composite/Shared.luau +134 -64
- package/src/codec/composite/Struct.luau +294 -43
- package/src/codec/composite/Tagged.luau +21 -16
- package/src/codec/composite/Tuple.luau +32 -15
- package/src/codec/datatype/Buffer.luau +7 -7
- package/src/codec/datatype/CFrame.luau +34 -122
- package/src/codec/datatype/Color.luau +10 -10
- package/src/codec/datatype/Instance.luau +15 -12
- package/src/codec/datatype/IntVector.luau +2 -2
- package/src/codec/datatype/NumberRange.luau +15 -8
- package/src/codec/datatype/Ray.luau +13 -14
- package/src/codec/datatype/Rect.luau +12 -12
- package/src/codec/datatype/Region.luau +13 -14
- package/src/codec/datatype/Sequence.luau +87 -65
- package/src/codec/datatype/String.luau +17 -10
- package/src/codec/datatype/UDim.luau +10 -8
- package/src/codec/datatype/Vector.luau +20 -59
- package/src/codec/meta/Auto.luau +94 -126
- package/src/codec/meta/Bitfield.luau +12 -14
- package/src/codec/meta/Custom.luau +3 -1
- package/src/codec/meta/DeltaScalar.luau +390 -0
- package/src/codec/meta/Enum.luau +9 -9
- package/src/codec/meta/Float.luau +6 -28
- package/src/codec/meta/Nothing.luau +1 -1
- package/src/codec/meta/Unknown.luau +10 -7
- package/src/codec/primitive/Bool.luau +6 -4
- package/src/codec/primitive/Float16.luau +5 -2
- package/src/codec/primitive/Int.luau +5 -6
- package/src/codec/primitive/Number.luau +6 -4
- package/src/codec/primitive/Signed.luau +2 -2
- package/src/codec/primitive/Varint.luau +76 -39
- package/src/codec/primitive/Zint.luau +99 -0
- package/src/index.d.ts +207 -53
- package/src/init.luau +116 -103
- package/src/internal/Baseline.luau +9 -1
- package/src/internal/Channel.luau +191 -157
- package/src/internal/Middleware.luau +22 -6
- package/src/internal/Pool.luau +12 -4
- package/src/internal/Registry.luau +25 -16
- package/src/internal/Transport.luau +1 -1
- package/src/transport/Bridge.luau +47 -33
- package/src/transport/Client.luau +25 -21
- package/src/transport/Gate.luau +227 -172
- package/src/transport/Reader.luau +174 -106
- package/src/transport/Server.luau +46 -57
- package/src/util/Array.luau +18 -0
- package/src/util/Buffer.luau +90 -0
- package/src/util/Constants.luau +30 -0
- package/src/util/Log.luau +68 -0
- package/src/util/Player.luau +14 -0
- package/src/util/Quantize.luau +84 -0
- package/src/util/Quat.luau +124 -0
- package/src/internal/Util.luau +0 -26
|
@@ -1,28 +1,41 @@
|
|
|
1
1
|
--!strict
|
|
2
2
|
--!native
|
|
3
|
-
-- Dense prefix varint
|
|
3
|
+
-- Dense prefix varint over [0, 2^32 - 1]. Single-branch decode.
|
|
4
4
|
|
|
5
5
|
local Base = require(script.Parent.Parent.Base)
|
|
6
|
+
local Constants = require(script.Parent.Parent.Parent.util.Constants)
|
|
7
|
+
local Log = require(script.Parent.Parent.Parent.util.Log)
|
|
6
8
|
local Types = require(script.Parent.Parent.Parent.Types)
|
|
7
9
|
|
|
8
10
|
-- Constants --------------------------------------------------------------
|
|
9
11
|
|
|
10
12
|
--[[
|
|
11
|
-
Wire layout (first byte
|
|
12
|
-
0x00..0xBF 1 byte value = b0
|
|
13
|
-
0xC0..0xDF 2 bytes value = (b0 & 0x1F)<<8 | b1 + 192
|
|
14
|
-
0xE0..0xEF 3 bytes value = (b0 & 0x0F)<<16 | u16 + 8384
|
|
15
|
-
0xF0..0xFF 5 bytes value = u32
|
|
13
|
+
Wire layout (first byte tag selects length):
|
|
14
|
+
0x00..0xBF 1 byte value = b0 [0..191]
|
|
15
|
+
0xC0..0xDF 2 bytes value = (b0 & 0x1F)<<8 | b1 + 192 [192..8383]
|
|
16
|
+
0xE0..0xEF 3 bytes value = (b0 & 0x0F)<<16 | u16 + 8384 [8384..1056959]
|
|
17
|
+
0xF0..0xFF 5 bytes value = u32 [..0xFFFFFFFF]
|
|
16
18
|
]]
|
|
17
19
|
local INLINE_MAX = 0xBF
|
|
20
|
+
local TWO_TAG = 0xC0
|
|
21
|
+
local TWO_END = 0xDF
|
|
22
|
+
local TWO_MASK = 0x1F
|
|
23
|
+
local THREE_TAG = 0xE0
|
|
24
|
+
local THREE_END = 0xEF
|
|
25
|
+
local THREE_MASK = 0x0F
|
|
26
|
+
local FIVE_TAG = 0xF0
|
|
18
27
|
local TWO_MAX = 8383
|
|
19
28
|
local THREE_MAX = 1056959
|
|
20
29
|
local TWO_BIAS = 192
|
|
21
30
|
local THREE_BIAS = 8384
|
|
22
31
|
|
|
32
|
+
local U8_MAX = Constants.U8_MAX
|
|
33
|
+
local U16_MAX = Constants.U16_MAX
|
|
34
|
+
local U32_MAX = Constants.U32_MAX
|
|
35
|
+
|
|
23
36
|
-- Private ----------------------------------------------------------------
|
|
24
37
|
|
|
25
|
-
local
|
|
38
|
+
local ensure = Base.ensure
|
|
26
39
|
local band = bit32.band
|
|
27
40
|
local bor = bit32.bor
|
|
28
41
|
local rshift = bit32.rshift
|
|
@@ -39,85 +52,109 @@ local Varint = {}
|
|
|
39
52
|
|
|
40
53
|
Varint.INLINE_MAX = INLINE_MAX
|
|
41
54
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
-- Wire byte count for a value, without encoding it. Used by cost heuristics.
|
|
56
|
+
function Varint.length(value: number): number
|
|
57
|
+
if value <= INLINE_MAX then
|
|
58
|
+
return 1
|
|
59
|
+
elseif value <= TWO_MAX then
|
|
60
|
+
return 2
|
|
61
|
+
elseif value <= THREE_MAX then
|
|
62
|
+
return 3
|
|
45
63
|
end
|
|
64
|
+
return 5
|
|
65
|
+
end
|
|
46
66
|
|
|
47
|
-
|
|
67
|
+
function Varint.write(ch: Types.ChannelState, value: number): ()
|
|
68
|
+
if value < 0 or value > U32_MAX or value % 1 ~= 0 then
|
|
69
|
+
Log.error(`value must be an integer in [0, {U32_MAX}], got {value}`)
|
|
70
|
+
end
|
|
48
71
|
|
|
49
72
|
if value <= INLINE_MAX then
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
end
|
|
73
|
+
ensure(ch, 1)
|
|
74
|
+
local cursor = ch.cursor
|
|
53
75
|
writeu8(ch.buff, cursor, value)
|
|
54
76
|
ch.cursor = cursor + 1
|
|
55
77
|
return
|
|
56
78
|
end
|
|
57
79
|
|
|
58
80
|
if value <= TWO_MAX then
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
end
|
|
81
|
+
ensure(ch, 2)
|
|
82
|
+
local cursor = ch.cursor
|
|
62
83
|
local adjusted = value - TWO_BIAS
|
|
63
84
|
local b = ch.buff
|
|
64
|
-
writeu8(b, cursor, bor(
|
|
65
|
-
writeu8(b, cursor + 1, band(adjusted,
|
|
85
|
+
writeu8(b, cursor, bor(TWO_TAG, rshift(adjusted, 8)))
|
|
86
|
+
writeu8(b, cursor + 1, band(adjusted, U8_MAX))
|
|
66
87
|
ch.cursor = cursor + 2
|
|
67
88
|
return
|
|
68
89
|
end
|
|
69
90
|
|
|
70
91
|
if value <= THREE_MAX then
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
end
|
|
92
|
+
ensure(ch, 3)
|
|
93
|
+
local cursor = ch.cursor
|
|
74
94
|
local adjusted = value - THREE_BIAS
|
|
75
95
|
local b = ch.buff
|
|
76
|
-
writeu8(b, cursor, bor(
|
|
77
|
-
writeu16(b, cursor + 1, band(adjusted,
|
|
96
|
+
writeu8(b, cursor, bor(THREE_TAG, rshift(adjusted, 16)))
|
|
97
|
+
writeu16(b, cursor + 1, band(adjusted, U16_MAX))
|
|
78
98
|
ch.cursor = cursor + 3
|
|
79
99
|
return
|
|
80
100
|
end
|
|
81
101
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
end
|
|
102
|
+
ensure(ch, 5)
|
|
103
|
+
local cursor = ch.cursor
|
|
85
104
|
local b = ch.buff
|
|
86
|
-
writeu8(b, cursor,
|
|
105
|
+
writeu8(b, cursor, FIVE_TAG)
|
|
87
106
|
writeu32(b, cursor + 1, value)
|
|
88
107
|
ch.cursor = cursor + 5
|
|
89
108
|
end
|
|
90
109
|
|
|
110
|
+
--[[
|
|
111
|
+
Returns (value, bytesConsumed). On insufficient bytes returns (0, 0) so
|
|
112
|
+
the transport can abort the frame instead of letting the buffer access
|
|
113
|
+
raise — required for recovery from truncated/desynced incoming buffers.
|
|
114
|
+
]]
|
|
91
115
|
function Varint.read(src: buffer, pos: number): (number, number)
|
|
116
|
+
local available = buffer.len(src) - pos
|
|
117
|
+
if available < 1 then
|
|
118
|
+
return 0, 0
|
|
119
|
+
end
|
|
92
120
|
local b0 = readu8(src, pos)
|
|
93
121
|
if b0 <= INLINE_MAX then
|
|
94
122
|
return b0, 1
|
|
95
123
|
end
|
|
96
|
-
if b0 <=
|
|
97
|
-
|
|
124
|
+
if b0 <= TWO_END then
|
|
125
|
+
if available < 2 then
|
|
126
|
+
return 0, 0
|
|
127
|
+
end
|
|
128
|
+
return band(b0, TWO_MASK) * 256 + readu8(src, pos + 1) + TWO_BIAS, 2
|
|
129
|
+
end
|
|
130
|
+
if b0 <= THREE_END then
|
|
131
|
+
if available < 3 then
|
|
132
|
+
return 0, 0
|
|
133
|
+
end
|
|
134
|
+
return band(b0, THREE_MASK) * 65536 + readu16(src, pos + 1) + THREE_BIAS, 3
|
|
98
135
|
end
|
|
99
|
-
if
|
|
100
|
-
return
|
|
136
|
+
if available < 5 then
|
|
137
|
+
return 0, 0
|
|
101
138
|
end
|
|
102
139
|
return readu32(src, pos + 1), 5
|
|
103
140
|
end
|
|
104
141
|
|
|
105
|
-
--
|
|
142
|
+
-- Caller-asserted: value is known to fit in INLINE_MAX.
|
|
106
143
|
function Varint.writeInline(ch: Types.ChannelState, value: number): ()
|
|
144
|
+
ensure(ch, 1)
|
|
107
145
|
local cursor = ch.cursor
|
|
108
|
-
if cursor + 1 > ch.size then
|
|
109
|
-
alloc(ch, 1)
|
|
110
|
-
end
|
|
111
146
|
writeu8(ch.buff, cursor, value)
|
|
112
147
|
ch.cursor = cursor + 1
|
|
113
148
|
end
|
|
114
149
|
|
|
115
150
|
--[[
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
Used by Buffer, String, and Auto's string branch.
|
|
151
|
+
Length-prefix decode that fast-paths the [0, INLINE_MAX] single-byte form
|
|
152
|
+
before falling through to full varint. Used by Buffer, String, and Auto.
|
|
119
153
|
]]
|
|
120
154
|
function Varint.readLengthPrefix(src: buffer, pos: number): (number, number)
|
|
155
|
+
if buffer.len(src) - pos < 1 then
|
|
156
|
+
return 0, 0
|
|
157
|
+
end
|
|
121
158
|
local b0 = readu8(src, pos)
|
|
122
159
|
if b0 <= INLINE_MAX then
|
|
123
160
|
return b0, 1
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
-- Signed varint via zigzag mapping. Small magnitudes pack in 1 byte.
|
|
4
|
+
|
|
5
|
+
local Log = require(script.Parent.Parent.Parent.util.Log)
|
|
6
|
+
local Types = require(script.Parent.Parent.Parent.Types)
|
|
7
|
+
local Varint = require(script.Parent.Parent.primitive.Varint)
|
|
8
|
+
|
|
9
|
+
-- Constants --------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
--[[
|
|
12
|
+
Zigzag fold maps signed values onto unsigned varint space:
|
|
13
|
+
n >= 0 -> 2n
|
|
14
|
+
n < 0 -> -2n - 1
|
|
15
|
+
Inverse: low bit selects sign, shift down 1 bit.
|
|
16
|
+
|
|
17
|
+
Wire ranges (using Varint dense form):
|
|
18
|
+
1 byte: [-96, 95]
|
|
19
|
+
2 bytes: [-4192, 4191]
|
|
20
|
+
3 bytes: [-528480, 528479]
|
|
21
|
+
5 bytes: full i32
|
|
22
|
+
]]
|
|
23
|
+
local I32_MIN = -0x80000000
|
|
24
|
+
local I32_MAX = 0x7FFFFFFF
|
|
25
|
+
|
|
26
|
+
-- Private ----------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
local floor = math.floor
|
|
29
|
+
local band = bit32.band
|
|
30
|
+
local varintWrite = Varint.write
|
|
31
|
+
local varintRead = Varint.read
|
|
32
|
+
|
|
33
|
+
-- Signed -> unsigned. Hot path; called per write of every delta scalar.
|
|
34
|
+
local function encode(value: number): number
|
|
35
|
+
if value >= 0 then
|
|
36
|
+
return value * 2
|
|
37
|
+
end
|
|
38
|
+
return value * -2 - 1
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
-- Inverse of encode. Even -> n/2; odd -> -((n+1)/2). Branchless on the half.
|
|
42
|
+
local function decode(raw: number): number
|
|
43
|
+
local low = band(raw, 1)
|
|
44
|
+
local half = (raw - low) / 2
|
|
45
|
+
return if low == 1 then -half - 1 else half
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
-- Public -----------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
local Zint = {}
|
|
51
|
+
|
|
52
|
+
Zint.encode = encode
|
|
53
|
+
Zint.decode = decode
|
|
54
|
+
|
|
55
|
+
--[[
|
|
56
|
+
Variable-length signed integer in [I32_MIN, I32_MAX]. Optional [min, max]
|
|
57
|
+
bounds gate input at write time so out-of-range payloads error early
|
|
58
|
+
rather than corrupting downstream decoders.
|
|
59
|
+
]]
|
|
60
|
+
function Zint.zint(min: number?, max: number?): Types.InternalCodec<number>
|
|
61
|
+
local lo = min or I32_MIN
|
|
62
|
+
local hi = max or I32_MAX
|
|
63
|
+
if lo > hi then
|
|
64
|
+
Log.error(`min ({lo}) must be <= max ({hi})`)
|
|
65
|
+
end
|
|
66
|
+
if floor(lo) ~= lo or floor(hi) ~= hi then
|
|
67
|
+
Log.error("bounds must be integers")
|
|
68
|
+
end
|
|
69
|
+
if lo < I32_MIN or hi > I32_MAX then
|
|
70
|
+
Log.error(`range [{lo}, {hi}] exceeds i32 bounds`)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
return table.freeze({
|
|
74
|
+
_typeCheck = "number",
|
|
75
|
+
_isInteger = true,
|
|
76
|
+
_min = lo,
|
|
77
|
+
_max = hi,
|
|
78
|
+
|
|
79
|
+
write = function(ch: Types.ChannelState, value: number): ()
|
|
80
|
+
if value < lo or value > hi then
|
|
81
|
+
Log.error(`value {value} out of range [{lo}, {hi}]`)
|
|
82
|
+
end
|
|
83
|
+
if floor(value) ~= value then
|
|
84
|
+
Log.error(`value {value} must be an integer`)
|
|
85
|
+
end
|
|
86
|
+
varintWrite(ch, encode(value))
|
|
87
|
+
end,
|
|
88
|
+
|
|
89
|
+
read = function(src: buffer, pos: number, _refs: { Instance }?): (number, number)
|
|
90
|
+
local raw, consumed = varintRead(src, pos)
|
|
91
|
+
if consumed == 0 then
|
|
92
|
+
Log.error("truncated zint")
|
|
93
|
+
end
|
|
94
|
+
return decode(raw), consumed
|
|
95
|
+
end,
|
|
96
|
+
}) :: Types.InternalCodec<number>
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
return table.freeze(Zint)
|