@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.
Files changed (55) hide show
  1. package/README.md +499 -357
  2. package/package.json +2 -2
  3. package/src/Types.luau +69 -27
  4. package/src/api/Group.luau +101 -106
  5. package/src/api/Packet.luau +191 -157
  6. package/src/api/Query.luau +223 -282
  7. package/src/api/Scope.luau +46 -57
  8. package/src/api/Signal.luau +104 -137
  9. package/src/codec/Base.luau +69 -20
  10. package/src/codec/composite/Array.luau +189 -201
  11. package/src/codec/composite/Map.luau +97 -341
  12. package/src/codec/composite/Optional.luau +27 -23
  13. package/src/codec/composite/Shared.luau +96 -65
  14. package/src/codec/composite/Struct.luau +201 -339
  15. package/src/codec/composite/Tagged.luau +64 -178
  16. package/src/codec/composite/Tuple.luau +81 -95
  17. package/src/codec/datatype/Buffer.luau +49 -21
  18. package/src/codec/datatype/CFrame.luau +207 -30
  19. package/src/codec/datatype/Color.luau +21 -11
  20. package/src/codec/datatype/Instance.luau +29 -19
  21. package/src/codec/datatype/IntVector.luau +33 -21
  22. package/src/codec/datatype/NumberRange.luau +19 -10
  23. package/src/codec/datatype/Ray.luau +26 -22
  24. package/src/codec/datatype/Rect.luau +20 -16
  25. package/src/codec/datatype/Region.luau +51 -45
  26. package/src/codec/datatype/Sequence.luau +64 -56
  27. package/src/codec/datatype/String.luau +89 -56
  28. package/src/codec/datatype/UDim.luau +40 -22
  29. package/src/codec/datatype/Vector.luau +181 -17
  30. package/src/codec/meta/Auto.luau +295 -253
  31. package/src/codec/meta/Bitfield.luau +104 -148
  32. package/src/codec/meta/Custom.luau +8 -4
  33. package/src/codec/meta/Enum.luau +29 -57
  34. package/src/codec/meta/Float.luau +64 -0
  35. package/src/codec/meta/Nothing.luau +9 -5
  36. package/src/codec/meta/Unknown.luau +44 -35
  37. package/src/codec/primitive/Bool.luau +16 -26
  38. package/src/codec/primitive/Float16.luau +58 -64
  39. package/src/codec/primitive/Int.luau +68 -0
  40. package/src/codec/primitive/Number.luau +21 -43
  41. package/src/codec/primitive/Varint.luau +67 -46
  42. package/src/index.d.ts +249 -306
  43. package/src/init.luau +332 -173
  44. package/src/internal/Baseline.luau +29 -24
  45. package/src/internal/Channel.luau +346 -161
  46. package/src/internal/Middleware.luau +60 -85
  47. package/src/internal/Pool.luau +19 -30
  48. package/src/internal/Registry.luau +61 -101
  49. package/src/transport/Bridge.luau +64 -43
  50. package/src/transport/Client.luau +60 -117
  51. package/src/transport/Gate.luau +282 -133
  52. package/src/transport/Reader.luau +159 -100
  53. package/src/transport/Server.luau +147 -292
  54. package/src/api/Namespace.luau +0 -251
  55. package/src/codec/meta/Quantized.luau +0 -174
@@ -1,192 +1,148 @@
1
1
  --!strict
2
2
  --!native
3
- -- Pack booleans, unsigned and signed integers at the bit level.
3
+ -- Sub-byte packing. 1 to 32 bits across bool/uint/int fields.
4
4
 
5
- local Channel = require(script.Parent.Parent.Parent.internal.Channel)
6
- local Types = require(script.Parent.Parent.Parent.Types)
5
+ local Base = require(script.Parent.Parent.Base)
7
6
 
8
- type ChannelState = Types.ChannelState
9
- type Codec<T> = Types.Codec<T>
10
-
11
- local alloc = Channel.alloc
12
-
13
- -- Constants -----------------------------------------------------------
7
+ -- Private -------------------------------------------------------------
14
8
 
15
9
  local band = bit32.band
16
10
  local bor = bit32.bor
17
11
  local lshift = bit32.lshift
18
12
  local rshift = bit32.rshift
19
13
 
20
- -- Private -------------------------------------------------------------
21
-
22
- type FieldSpec = {
23
- type: "bool" | "uint" | "int",
24
- width: number?,
25
- }
26
-
27
- local function selectIO(bytes: number): ((b: buffer, offset: number, v: number) -> (), (
28
- b: buffer,
29
- offset: number
30
- ) -> number)
31
- if bytes == 1 then
32
- return buffer.writeu8, buffer.readu8
33
- end
34
- if bytes == 2 then
35
- return buffer.writeu16, buffer.readu16
36
- end
37
- return buffer.writeu32, buffer.readu32
38
- end
14
+ -- Field type constants
15
+ local TYPE_BOOL = 0
16
+ local TYPE_UINT = 1
17
+ local TYPE_INT = 2
39
18
 
40
19
  -- Public --------------------------------------------------------------
41
20
 
42
21
  local Bitfield = {}
43
22
 
44
- function Bitfield.define(schema: { [string]: FieldSpec }): Codec<any>
45
- local sortedKeys = {} :: { string }
46
-
23
+ function Bitfield.define(schema: { [string]: { type: string, width: number? } }): any
24
+ -- Collect and sort keys alphabetically
25
+ local keys = {}
47
26
  for key in schema do
48
- table.insert(sortedKeys, key)
27
+ table.insert(keys, key)
49
28
  end
29
+ table.sort(keys)
50
30
 
51
- table.sort(sortedKeys)
52
-
53
- local count = #sortedKeys
54
- if count == 0 then
55
- error("[Lync] Bitfield requires at least one field")
31
+ if #keys == 0 then
32
+ error("[Lync] Lync.bitfield: requires at least one field")
56
33
  end
57
34
 
58
- local keys = table.create(count) :: { string }
59
- local isBool = table.create(count) :: { boolean }
60
- local offsets = table.create(count) :: { number }
61
- local masks = table.create(count) :: { number }
62
-
63
- local hasSigned = false
64
- local signBits = nil :: { number }?
65
- local signExtends = nil :: { number }?
66
-
35
+ local fieldCount = #keys
36
+ local fieldKeys = table.create(fieldCount)
37
+ local fieldTypes = table.create(fieldCount)
38
+ local fieldOffsets = table.create(fieldCount)
39
+ local fieldMasks = table.create(fieldCount)
40
+ local fieldSignBit = table.create(fieldCount)
41
+ local fieldSignExt = table.create(fieldCount)
67
42
  local totalBits = 0
68
- for i = 1, count do
69
- local key = sortedKeys[i]
70
- local spec = schema[key]
71
- local specIsBool = spec.type == "bool"
72
- local specIsSigned = spec.type == "int"
73
- local width: number
74
43
 
75
- if specIsBool then
76
- width = 1
77
- else
78
- if not spec.width then
79
- error(`[Lync] Bitfield field requires a width: "{key}"`)
44
+ for i = 1, fieldCount do
45
+ local key = keys[i]
46
+ local spec = schema[key]
47
+ fieldKeys[i] = key
48
+ fieldOffsets[i] = totalBits
49
+
50
+ if spec.type == "bool" then
51
+ fieldTypes[i] = TYPE_BOOL
52
+ fieldMasks[i] = 1
53
+ fieldSignBit[i] = 0
54
+ fieldSignExt[i] = 0
55
+ totalBits += 1
56
+ elseif spec.type == "uint" then
57
+ local width = spec.width
58
+ if not width or width < 1 or width > 32 then
59
+ error(`[Lync] Lync.bitfield: field "{key}" uint width must be 1-32`)
80
60
  end
81
- width = spec.width
82
- if width < 1 or width > 32 then
83
- error(`[Lync] Bitfield width must be 1-32: "{key}" got {width}`)
61
+ fieldTypes[i] = TYPE_UINT
62
+ fieldMasks[i] = lshift(1, width) - 1
63
+ fieldSignBit[i] = 0
64
+ fieldSignExt[i] = 0
65
+ totalBits += width
66
+ elseif spec.type == "int" then
67
+ local width = spec.width
68
+ if not width or width < 2 or width > 32 then
69
+ error(`[Lync] Lync.bitfield: field "{key}" int width must be 2-32`)
84
70
  end
71
+ fieldTypes[i] = TYPE_INT
72
+ fieldMasks[i] = lshift(1, width) - 1
73
+ fieldSignBit[i] = lshift(1, width - 1)
74
+ fieldSignExt[i] = lshift(1, width)
75
+ totalBits += width
76
+ else
77
+ error(`[Lync] Lync.bitfield: unknown field type "{spec.type}"`)
85
78
  end
86
-
87
- if specIsSigned then
88
- hasSigned = true
89
- end
90
-
91
- keys[i] = key
92
- isBool[i] = specIsBool
93
- offsets[i] = totalBits
94
- masks[i] = lshift(1, width) - 1
95
- totalBits += width
96
79
  end
97
80
 
98
81
  if totalBits > 32 then
99
- error(`[Lync] Bitfield exceeds 32 bits: {totalBits}`)
82
+ error(`[Lync] Lync.bitfield: total exceeds 32 bits ({totalBits})`)
100
83
  end
101
84
 
102
- -- Only build sign tables when at least one field is signed
103
- if hasSigned then
104
- signBits = table.create(count) :: { number }
105
- signExtends = table.create(count) :: { number }
106
-
107
- for i = 1, count do
108
- local spec = schema[sortedKeys[i]]
109
- if spec.type == "int" then
110
- (signBits :: { number })[i] = lshift(1, (spec.width :: number) - 1);
111
- (signExtends :: { number })[i] = lshift(1, spec.width :: number)
112
- else
113
- (signBits :: { number })[i] = 0
114
- (signExtends :: { number })[i] = 0
115
- end
116
- end
117
-
118
- table.freeze(signBits :: { number })
119
- table.freeze(signExtends :: { number })
85
+ -- Determine wire size
86
+ local wireBytes: number
87
+ local wfn: (buffer, number, number) -> ()
88
+ local rfn: (buffer, number) -> number
89
+
90
+ if totalBits <= 8 then
91
+ wireBytes = 1
92
+ wfn = buffer.writeu8
93
+ rfn = buffer.readu8
94
+ elseif totalBits <= 16 then
95
+ wireBytes = 2
96
+ wfn = buffer.writeu16
97
+ rfn = buffer.readu16
98
+ else
99
+ wireBytes = 4
100
+ wfn = buffer.writeu32
101
+ rfn = buffer.readu32
120
102
  end
121
103
 
122
- table.freeze(keys)
123
- table.freeze(isBool)
124
- table.freeze(offsets)
125
- table.freeze(masks)
104
+ -- Freeze all descriptor arrays
105
+ table.freeze(fieldKeys)
106
+ table.freeze(fieldTypes)
107
+ table.freeze(fieldOffsets)
108
+ table.freeze(fieldMasks)
109
+ table.freeze(fieldSignBit)
110
+ table.freeze(fieldSignExt)
126
111
 
127
- local bytes = if totalBits <= 8 then 1 elseif totalBits <= 16 then 2 else 4
128
- local wfn, rfn = selectIO(bytes)
129
-
130
- -- Shared pack logic
131
- local function packValue(value: any): number
112
+ return Base.define(wireBytes, function(b: buffer, off: number, value: any): ()
132
113
  local packed = 0
133
- for i = 1, count do
134
- local bits = if isBool[i]
135
- then (if value[keys[i]] then 1 else 0)
136
- else band(value[keys[i]], masks[i])
137
- packed = bor(packed, lshift(bits, offsets[i]))
114
+ for i = 1, fieldCount do
115
+ local v = value[fieldKeys[i]]
116
+ if fieldTypes[i] == TYPE_BOOL then
117
+ if v then
118
+ packed = bor(packed, lshift(1, fieldOffsets[i]))
119
+ end
120
+ else
121
+ packed = bor(packed, lshift(band(v, fieldMasks[i]), fieldOffsets[i]))
122
+ end
138
123
  end
139
- return packed
140
- end
141
-
142
- -- Shared unpack logic
143
- local function unpackValue(packed: number): any
144
- local result = {}
145
-
146
- if hasSigned then
147
- local sb = signBits :: { number }
148
- local se = signExtends :: { number }
149
-
150
- for i = 1, count do
151
- local raw = band(rshift(packed, offsets[i]), masks[i])
152
- if isBool[i] then
153
- result[keys[i]] = raw ~= 0
154
- elseif sb[i] > 0 and raw >= sb[i] then
155
- result[keys[i]] = raw - se[i]
124
+ wfn(b, off, packed)
125
+ end, function(b: buffer, off: number): any
126
+ local packed = rfn(b, off)
127
+ local result: { [string]: any } = {}
128
+
129
+ for i = 1, fieldCount do
130
+ local raw = band(rshift(packed, fieldOffsets[i]), fieldMasks[i])
131
+ if fieldTypes[i] == TYPE_BOOL then
132
+ result[fieldKeys[i]] = raw ~= 0
133
+ elseif fieldTypes[i] == TYPE_INT then
134
+ if raw >= fieldSignBit[i] then
135
+ result[fieldKeys[i]] = raw - fieldSignExt[i]
156
136
  else
157
- result[keys[i]] = raw
137
+ result[fieldKeys[i]] = raw
158
138
  end
159
- end
160
- else
161
- for i = 1, count do
162
- local raw = band(rshift(packed, offsets[i]), masks[i])
163
- result[keys[i]] = if isBool[i] then raw ~= 0 else raw
139
+ else
140
+ result[fieldKeys[i]] = raw
164
141
  end
165
142
  end
166
143
 
167
144
  return result
168
- end
169
-
170
- return table.freeze({
171
- _size = bytes,
172
- _directWrite = function(b: buffer, offset: number, value: any): ()
173
- wfn(b, offset, packValue(value))
174
- end,
175
- _directRead = function(b: buffer, offset: number): any
176
- return unpackValue(rfn(b, offset))
177
- end,
178
- write = function(ch: ChannelState, value: any): ()
179
- local c = ch.cursor
180
- if c + bytes > ch.size then
181
- alloc(ch, bytes)
182
- end
183
- wfn(ch.buff, c, packValue(value))
184
- ch.cursor = c + bytes
185
- end,
186
- read = function(src: buffer, pos: number, _refs: { Instance }?): (any, number)
187
- return unpackValue(rfn(src, pos)), bytes
188
- end,
189
- })
145
+ end)
190
146
  end
191
147
 
192
148
  return table.freeze(Bitfield)
@@ -1,11 +1,15 @@
1
1
  --!strict
2
- --!native
3
- -- User-defined fixed-size codec factory. Public API wrapper over Base.define.
2
+ --!optimize 2
3
+ -- User-defined fixed-size codec.
4
4
 
5
5
  local Base = require(script.Parent.Parent.Base)
6
6
 
7
+ -- Private -------------------------------------------------------------
8
+
7
9
  local floor = math.floor
8
10
 
11
+ -- Public --------------------------------------------------------------
12
+
9
13
  local Custom = {}
10
14
 
11
15
  function Custom.define(
@@ -13,8 +17,8 @@ function Custom.define(
13
17
  writeFn: (b: buffer, offset: number, value: any) -> (),
14
18
  readFn: (b: buffer, offset: number) -> any
15
19
  ): any
16
- if size < 0 or size ~= floor(size) then
17
- error(`[Lync] Custom codec size must be a non-negative integer, got {size}`)
20
+ if type(size) ~= "number" or size < 0 or floor(size) ~= size then
21
+ error("[Lync] Lync.custom: size must be a non-negative integer")
18
22
  end
19
23
 
20
24
  if size == 0 then
@@ -1,81 +1,53 @@
1
1
  --!strict
2
- --!native
3
- -- String enum codec. Maps values to u8 indices at definition time.
2
+ --!optimize 2
3
+ -- String enum codec. Maps values to u8 indices at define time.
4
4
 
5
- local Channel = require(script.Parent.Parent.Parent.internal.Channel)
6
- local Types = require(script.Parent.Parent.Parent.Types)
7
-
8
- type ChannelState = Types.ChannelState
9
- type Codec<T> = Types.Codec<T>
10
-
11
- local alloc = Channel.alloc
5
+ local Base = require(script.Parent.Parent.Base)
12
6
 
13
7
  -- Public --------------------------------------------------------------
14
8
 
15
9
  local EnumCodec = {}
16
10
 
17
- function EnumCodec.define(...: string): Codec<string>
11
+ function EnumCodec.define(...: string): any
18
12
  local values = { ... }
19
13
  local count = #values
20
14
  if count == 0 then
21
- error("[Lync] Enum requires at least one value")
15
+ error("[Lync] Lync.enum: requires at least one value")
22
16
  end
23
17
  if count > 256 then
24
- error(`[Lync] Enum exceeds 256 values: {count}`)
18
+ error("[Lync] Lync.enum: exceeds 256 variants")
25
19
  end
26
20
 
27
- local toIndex = {} :: { [string]: number }
28
- local toValue = table.create(count) :: { string }
21
+ -- Build lookup tables
22
+ local toIndex: { [string]: number } = {}
23
+ local toValue = table.create(count)
29
24
 
30
- for i, value in values do
31
- if toIndex[value] ~= nil then
32
- error(`[Lync] Duplicate enum value: "{value}"`)
25
+ for i = 1, count do
26
+ local val = values[i]
27
+ if toIndex[val] then
28
+ error(`[Lync] Lync.enum: duplicate value "{val}"`)
33
29
  end
34
- toIndex[value] = i - 1
35
- toValue[i] = value
30
+ toIndex[val] = i - 1
31
+ toValue[i] = val
36
32
  end
37
33
 
38
34
  table.freeze(toIndex)
39
35
  table.freeze(toValue)
40
36
 
41
- return table.freeze({
42
- _size = 1,
43
- _directWrite = function(b: buffer, offset: number, value: string): ()
44
- local idx = toIndex[value]
45
- if idx == nil then
46
- error(`[Lync] Invalid enum value: "{value}"`)
47
- end
48
- buffer.writeu8(b, offset, idx)
49
- end,
50
- _directRead = function(b: buffer, offset: number): string
51
- local idx = buffer.readu8(b, offset)
52
- local value = toValue[idx + 1]
53
- if value == nil then
54
- error(`[Lync] Invalid enum index: {idx}`)
55
- end
56
- return value
57
- end,
58
- write = function(ch: ChannelState, value: string): ()
59
- local idx = toIndex[value]
60
- if idx == nil then
61
- error(`[Lync] Invalid enum value: "{value}"`)
62
- end
63
- local c = ch.cursor
64
- if c + 1 > ch.size then
65
- alloc(ch, 1)
66
- end
67
- buffer.writeu8(ch.buff, c, idx)
68
- ch.cursor = c + 1
69
- end,
70
- read = function(src: buffer, pos: number, _refs: { Instance }?): (string, number)
71
- local idx = buffer.readu8(src, pos)
72
- local value = toValue[idx + 1]
73
- if value == nil then
74
- error(`[Lync] Invalid enum index: {idx}`)
75
- end
76
- return value, 1
77
- end,
78
- })
37
+ return Base.define(1, function(b: buffer, off: number, value: string): ()
38
+ local idx = toIndex[value]
39
+ if idx == nil then
40
+ error(`[Lync] Enum: invalid value "{value}"`)
41
+ end
42
+ buffer.writeu8(b, off, idx)
43
+ end, function(b: buffer, off: number): string
44
+ local idx = buffer.readu8(b, off)
45
+ local val = toValue[idx + 1]
46
+ if val == nil then
47
+ error(`[Lync] Enum: invalid index {idx}`)
48
+ end
49
+ return val
50
+ end, { _typeCheck = "string" })
79
51
  end
80
52
 
81
53
  return table.freeze(EnumCodec)
@@ -0,0 +1,64 @@
1
+ --!strict
2
+ --!native
3
+ -- Fixed-point quantization codec. Maps float ranges to integer ranges.
4
+
5
+ local Base = require(script.Parent.Parent.Base)
6
+
7
+ -- Private -------------------------------------------------------------
8
+
9
+ local ceil = math.ceil
10
+ local clamp = math.clamp
11
+ local round = math.round
12
+ local max = math.max
13
+ local min = math.min
14
+
15
+ -- Public --------------------------------------------------------------
16
+
17
+ local Float = {}
18
+
19
+ function Float.float(rangeMin: number, rangeMax: number, precision: number): any
20
+ if rangeMin > rangeMax then
21
+ error(`[Lync] Lync.float: min ({rangeMin}) must be <= max ({rangeMax})`)
22
+ end
23
+ if precision <= 0 then
24
+ error("[Lync] Lync.float: precision must be positive")
25
+ end
26
+
27
+ local delta = rangeMax - rangeMin
28
+
29
+ -- Constant value: zero bytes
30
+ if delta == 0 then
31
+ return Base.zero()
32
+ end
33
+
34
+ local maxInt = min(0xFFFFFFFF, max(1, ceil(delta / precision)))
35
+
36
+ local compBytes: number
37
+ local wfn: (buffer, number, number) -> ()
38
+ local rfn: (buffer, number) -> number
39
+
40
+ if maxInt <= 0xFF then
41
+ compBytes = 1
42
+ wfn = buffer.writeu8
43
+ rfn = buffer.readu8
44
+ elseif maxInt <= 0xFFFF then
45
+ compBytes = 2
46
+ wfn = buffer.writeu16
47
+ rfn = buffer.readu16
48
+ else
49
+ compBytes = 4
50
+ wfn = buffer.writeu32
51
+ rfn = buffer.readu32
52
+ end
53
+
54
+ local scale = maxInt / delta
55
+ local invScale = delta / maxInt
56
+
57
+ return Base.define(compBytes, function(b: buffer, off: number, value: number): ()
58
+ wfn(b, off, round(clamp(value - rangeMin, 0, delta) * scale))
59
+ end, function(b: buffer, off: number): number
60
+ return rfn(b, off) * invScale + rangeMin
61
+ end, { _min = rangeMin, _max = rangeMax, _typeCheck = "number" })
62
+ end
63
+
64
+ return table.freeze(Float)
@@ -1,9 +1,13 @@
1
1
  --!strict
2
- --!native
3
- -- Zero-byte codec. Reads nil. Good for fire-and-forget signals.
2
+ --!optimize 2
3
+ -- Zero-byte codec. Reads nil. For fire-and-forget signals.
4
4
 
5
5
  local Base = require(script.Parent.Parent.Base)
6
6
 
7
- return table.freeze({
8
- nothing = Base.zero(),
9
- })
7
+ -- Public --------------------------------------------------------------
8
+
9
+ local Nothing = {}
10
+
11
+ Nothing.nothing = Base.zero()
12
+
13
+ return table.freeze(Nothing)
@@ -1,39 +1,48 @@
1
1
  --!strict
2
- --!native
3
- -- Sidecar codec. Bypasses buffer serialization, uses Roblox remote refs.
2
+ --!optimize 2
3
+ -- Bypasses buffer serialization. Uses Roblox remote sidecar refs.
4
4
 
5
- local Channel = require(script.Parent.Parent.Parent.internal.Channel)
5
+ local Base = require(script.Parent.Parent.Base)
6
6
  local Types = require(script.Parent.Parent.Parent.Types)
7
7
 
8
- type ChannelState = Types.ChannelState
9
-
10
- local alloc = Channel.alloc
11
-
12
- return table.freeze({
13
- unknown = table.freeze({
14
- write = function(ch: ChannelState, value: any): ()
15
- local refs = ch.refs
16
- local idx = #refs + 1
17
- if idx > 65535 then
18
- error(`[Lync] Unknown ref overflow: {idx} exceeds u16 max`)
19
- end
20
-
21
- refs[idx] = value
22
-
23
- local c = ch.cursor
24
- if c + 2 > ch.size then
25
- alloc(ch, 2)
26
- end
27
- buffer.writeu16(ch.buff, c, idx)
28
- ch.cursor = c + 2
29
- end,
30
- read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
31
- if not refs then
32
- error("[Lync] Unknown read requires refs array")
33
- end
34
-
35
- local idx = buffer.readu16(src, pos)
36
- return refs[idx], 2
37
- end,
38
- }),
39
- })
8
+ -- Private -------------------------------------------------------------
9
+
10
+ local alloc = Base.alloc
11
+ local writeu16 = buffer.writeu16
12
+ local readu16 = buffer.readu16
13
+
14
+ -- Public --------------------------------------------------------------
15
+
16
+ local Unknown = {}
17
+
18
+ Unknown.unknown = table.freeze({
19
+ _hasUnknown = true,
20
+
21
+ write = function(ch: Types.ChannelState, value: any): ()
22
+ local idx = ch.refCount + 1
23
+ if idx > 0xFFFF then
24
+ error("[Lync] Unknown: ref overflow (>65535)")
25
+ end
26
+
27
+ ch.refs[idx] = value :: any
28
+ ch.refCount = idx
29
+
30
+ local cursor = ch.cursor
31
+ if cursor + 2 > ch.size then
32
+ alloc(ch, 2)
33
+ end
34
+ writeu16(ch.buff, cursor, idx)
35
+ ch.cursor = cursor + 2
36
+ end,
37
+
38
+ read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
39
+ if not refs then
40
+ error("[Lync] Unknown: read requires refs array")
41
+ end
42
+
43
+ local idx = readu16(src, pos)
44
+ return (refs :: any)[idx], 2
45
+ end,
46
+ } :: any)
47
+
48
+ return table.freeze(Unknown)
@@ -1,30 +1,20 @@
1
1
  --!strict
2
- --!native
3
- -- Boolean codec. _isBool tells struct to pack into bitfields.
2
+ --!optimize 2
3
+ -- Boolean codec with bitpacking flag for struct and array codecs.
4
4
 
5
- local Channel = require(script.Parent.Parent.Parent.internal.Channel)
6
- local alloc = Channel.alloc
5
+ local Base = require(script.Parent.Parent.Base)
7
6
 
8
- return table.freeze({
9
- bool = table.freeze({
10
- _size = 1,
11
- _isBool = true,
12
- _directWrite = function(b: buffer, offset: number, value: boolean): ()
13
- buffer.writeu8(b, offset, if value then 1 else 0)
14
- end,
15
- _directRead = function(b: buffer, offset: number): boolean
16
- return buffer.readu8(b, offset) ~= 0
17
- end,
18
- write = function(ch: any, value: boolean): ()
19
- local c = ch.cursor
20
- if c + 1 > ch.size then
21
- alloc(ch, 1)
22
- end
23
- buffer.writeu8(ch.buff, c, if value then 1 else 0)
24
- ch.cursor = c + 1
25
- end,
26
- read = function(src: buffer, pos: number, _refs: { Instance }?): (boolean, number)
27
- return buffer.readu8(src, pos) ~= 0, 1
28
- end,
29
- }),
7
+ -- Public --------------------------------------------------------------
8
+
9
+ local Bool = {}
10
+
11
+ Bool.bool = Base.define(1, function(b: buffer, off: number, value: boolean): ()
12
+ buffer.writeu8(b, off, if value then 1 else 0)
13
+ end, function(b: buffer, off: number): boolean
14
+ return buffer.readu8(b, off) ~= 0
15
+ end, {
16
+ _isBool = true,
17
+ _typeCheck = "boolean",
30
18
  })
19
+
20
+ return table.freeze(Bool)