@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,222 +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")
32
+ local variantCount = #names
33
+ if variantCount == 0 then
34
+ error("[Lync] Lync.tagged: requires at least one variant")
36
35
  end
37
- if count > 256 then
38
- error(`[Lync] Tagged union exceeds 256 variants: {count}`)
36
+ if variantCount > 256 then
37
+ error("[Lync] Lync.tagged: exceeds 256 variants")
39
38
  end
40
39
 
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
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(tagCodecs)
76
- table.freeze(tagNames)
77
- table.freeze(tagSizes)
78
-
79
- local fixedSize: number? = if uniformSize then 1 + uniformSize else nil
80
-
81
- if allDirect then
82
- table.freeze(directWrites)
83
- table.freeze(directReads)
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
- local writeFns = table.create(count) :: { any }
176
- local readFns = table.create(count) :: { any }
177
- for i = 1, count do
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 variantSize = tagSizes[tag]
193
- if variantSize then
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
- local c = ch.cursor
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 = buffer.readu8(src, pos) + 1
206
- local name = tagNames[tag]
207
- if not name then
208
- 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}`)
209
88
  end
210
89
 
211
- 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)
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 + bytes
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
- --!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
-
27
- local canDirect = true
28
- local totalSize: number = 0
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 internal = codecs[i] :: InternalCodec<any>
35
- local size = internal._size
36
- local dw = internal._directWrite
37
- local dr = internal._directRead
38
-
39
- if size and dw and dr then
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
- canDirect = false
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
- -- Recompute totalSize for generic path if direct failed partway
56
- if not canDirect then
57
- 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
+
58
49
  for i = 1, count do
59
- local size = (codecs[i] :: InternalCodec<any>)._size
60
- if size then
61
- totalSize = (totalSize :: number) + size
62
- else
63
- totalSize = nil :: any
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
- if canDirect then
57
+ table.freeze(offsets)
70
58
  table.freeze(directWrites)
71
59
  table.freeze(directReads)
72
- table.freeze(fieldSizes)
73
60
 
74
- local function directWriteBody(b: buffer, c: number, value: { any }): ()
75
- for i = 1, count do
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
- local function directReadBody(b: buffer, pos: number): { any }
82
- local result = table.create(count)
83
- local c = pos
84
- for i = 1, count do
85
- result[i] = directReads[i](b, c)
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
- return table.freeze({
92
- _size = totalSize,
93
- _directWrite = directWriteBody,
94
- _directRead = directReadBody,
95
- 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): ()
96
79
  local c = ch.cursor
97
80
  if c + totalSize > ch.size then
98
81
  alloc(ch, totalSize)
99
82
  end
100
- 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
101
87
  ch.cursor = c + totalSize
102
88
  end,
103
- read = function(src: buffer, pos: number, _refs: { Instance }?): ({ any }, number)
104
- 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
105
96
  end,
106
- })
107
- end
97
+ }
108
98
 
109
- local writeFns = table.create(count) :: { any }
110
- local readFns = table.create(count) :: { any }
111
- for i = 1, count do
112
- writeFns[i] = codecs[i].write
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
- return table.freeze({
121
- _size = totalSize,
122
- write = function(ch: ChannelState, value: { any }): ()
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
- writeFns[i](ch, value[i])
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 value, n = readFns[i](src, absPos, refs)
136
- result[i] = value
137
- absPos += n
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
- --!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)