@axpecter/lync 2.0.0 → 2.1.1

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