@axpecter/lync 2.3.2 → 3.0.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 (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +302 -299
  3. package/Types.luau +215 -0
  4. package/api/Define.luau +154 -0
  5. package/api/Lifecycle.luau +119 -0
  6. package/api/Packet.luau +108 -0
  7. package/api/Query.luau +149 -0
  8. package/api/Set.luau +189 -0
  9. package/channel/Blocks.luau +124 -0
  10. package/channel/Group.luau +118 -0
  11. package/channel/Link.luau +135 -0
  12. package/channel/Outbox.luau +261 -0
  13. package/channel/Recipients.luau +129 -0
  14. package/channel/Transport.luau +138 -0
  15. package/codec/Base.luau +236 -0
  16. package/codec/Composites.luau +128 -0
  17. package/codec/Datatypes.luau +162 -0
  18. package/codec/Legality.luau +61 -0
  19. package/codec/Scalars.luau +72 -0
  20. package/codec/Text.luau +89 -0
  21. package/codec/init.luau +39 -0
  22. package/index.d.ts +285 -0
  23. package/init.luau +91 -0
  24. package/kernel/Bits.luau +16 -0
  25. package/kernel/Catalog.luau +121 -0
  26. package/kernel/Heap.luau +80 -0
  27. package/kernel/Listeners.luau +95 -0
  28. package/kernel/Log.luau +197 -0
  29. package/kernel/Tally.luau +128 -0
  30. package/kernel/Threads.luau +44 -0
  31. package/kernel/Wide.luau +267 -0
  32. package/package.json +15 -32
  33. package/runtime/Boundary.luau +180 -0
  34. package/runtime/Dispatch.luau +91 -0
  35. package/runtime/Handles.luau +114 -0
  36. package/runtime/Handshake.luau +90 -0
  37. package/runtime/Pending.luau +196 -0
  38. package/runtime/Router.luau +379 -0
  39. package/runtime/Session.luau +731 -0
  40. package/shape/Compile.luau +340 -0
  41. package/shape/Folds.luau +332 -0
  42. package/shape/Frames.luau +170 -0
  43. package/shape/Grid.luau +169 -0
  44. package/shape/Ir.luau +540 -0
  45. package/shape/Joins.luau +125 -0
  46. package/shape/Legality.luau +273 -0
  47. package/shape/Lower.luau +419 -0
  48. package/shape/Order.luau +64 -0
  49. package/shape/Regions.luau +113 -0
  50. package/shape/Rotation.luau +472 -0
  51. package/shape/Serial.luau +258 -0
  52. package/shape/Words.luau +89 -0
  53. package/shape/emit/Block.luau +453 -0
  54. package/shape/emit/Column.luau +338 -0
  55. package/shape/emit/Leaf.luau +462 -0
  56. package/shape/emit/Word.luau +234 -0
  57. package/shape/emit/init.luau +222 -0
  58. package/shape/init.luau +78 -0
  59. package/state/Apply.luau +330 -0
  60. package/state/Audience.luau +126 -0
  61. package/state/Catchup.luau +218 -0
  62. package/state/Coalesce.luau +43 -0
  63. package/state/Fieldset.luau +177 -0
  64. package/state/Newest.luau +339 -0
  65. package/state/Plan.luau +441 -0
  66. package/state/Sections.luau +468 -0
  67. package/state/Store.luau +188 -0
  68. package/state/Sync.luau +762 -0
  69. package/wire/Bytes.luau +118 -0
  70. package/wire/Clock.luau +37 -0
  71. package/wire/Protocol.luau +110 -0
  72. package/wire/Sequence.luau +40 -0
  73. package/wire/Varint.luau +124 -0
  74. package/src/Types.luau +0 -180
  75. package/src/api/Group.luau +0 -156
  76. package/src/api/Packet.luau +0 -319
  77. package/src/api/Query.luau +0 -338
  78. package/src/api/Scope.luau +0 -90
  79. package/src/api/Signal.luau +0 -188
  80. package/src/codec/Base.luau +0 -136
  81. package/src/codec/composite/Array.luau +0 -456
  82. package/src/codec/composite/Map.luau +0 -469
  83. package/src/codec/composite/Optional.luau +0 -54
  84. package/src/codec/composite/Shared.luau +0 -291
  85. package/src/codec/composite/Struct.luau +0 -494
  86. package/src/codec/composite/Tagged.luau +0 -103
  87. package/src/codec/composite/Tuple.luau +0 -143
  88. package/src/codec/datatype/Buffer.luau +0 -66
  89. package/src/codec/datatype/CFrame.luau +0 -109
  90. package/src/codec/datatype/Color.luau +0 -32
  91. package/src/codec/datatype/Instance.luau +0 -52
  92. package/src/codec/datatype/IntVector.luau +0 -39
  93. package/src/codec/datatype/NumberRange.luau +0 -39
  94. package/src/codec/datatype/Ray.luau +0 -36
  95. package/src/codec/datatype/Rect.luau +0 -31
  96. package/src/codec/datatype/Region.luau +0 -62
  97. package/src/codec/datatype/Sequence.luau +0 -184
  98. package/src/codec/datatype/String.luau +0 -94
  99. package/src/codec/datatype/UDim.luau +0 -46
  100. package/src/codec/datatype/Vector.luau +0 -130
  101. package/src/codec/meta/Auto.luau +0 -318
  102. package/src/codec/meta/Bitfield.luau +0 -147
  103. package/src/codec/meta/Custom.luau +0 -33
  104. package/src/codec/meta/DeltaScalar.luau +0 -390
  105. package/src/codec/meta/Enum.luau +0 -50
  106. package/src/codec/meta/Float.luau +0 -38
  107. package/src/codec/meta/Nothing.luau +0 -13
  108. package/src/codec/meta/Unknown.luau +0 -41
  109. package/src/codec/primitive/Bool.luau +0 -26
  110. package/src/codec/primitive/Float16.luau +0 -99
  111. package/src/codec/primitive/Int.luau +0 -59
  112. package/src/codec/primitive/Number.luau +0 -24
  113. package/src/codec/primitive/Signed.luau +0 -32
  114. package/src/codec/primitive/Varint.luau +0 -165
  115. package/src/codec/primitive/Zint.luau +0 -99
  116. package/src/index.d.ts +0 -423
  117. package/src/init.luau +0 -362
  118. package/src/internal/Baseline.luau +0 -57
  119. package/src/internal/Channel.luau +0 -390
  120. package/src/internal/Middleware.luau +0 -100
  121. package/src/internal/Pool.luau +0 -65
  122. package/src/internal/Registry.luau +0 -119
  123. package/src/internal/Transport.luau +0 -28
  124. package/src/transport/Bridge.luau +0 -110
  125. package/src/transport/Client.luau +0 -97
  126. package/src/transport/Gate.luau +0 -488
  127. package/src/transport/Reader.luau +0 -331
  128. package/src/transport/Server.luau +0 -211
  129. package/src/util/Array.luau +0 -18
  130. package/src/util/Buffer.luau +0 -90
  131. package/src/util/Constants.luau +0 -30
  132. package/src/util/Log.luau +0 -68
  133. package/src/util/Player.luau +0 -14
  134. package/src/util/Quantize.luau +0 -84
  135. package/src/util/Quat.luau +0 -124
@@ -1,469 +0,0 @@
1
- --!strict
2
- --!native
3
- -- map() and deltaMap(). Keys sorted at encode for stable wire bytes.
4
-
5
- local Base = require(script.Parent.Parent.Base)
6
- local Baseline = require(script.Parent.Parent.Parent.internal.Baseline)
7
- local Log = require(script.Parent.Parent.Parent.util.Log)
8
- local Shared = require(script.Parent.Parent.composite.Shared)
9
- local Types = require(script.Parent.Parent.Parent.Types)
10
- local Varint = require(script.Parent.Parent.primitive.Varint)
11
-
12
- -- Constants --------------------------------------------------------------
13
-
14
- -- deltaMap wire flags. Distinct from Shared's struct/array flag spaces.
15
- local DM_UNCHANGED = 0
16
- local DM_FULL = 1
17
- local DM_DIFF = 2
18
-
19
- -- State ------------------------------------------------------------------
20
-
21
- --[[
22
- Depth-stacked key scratch. A nested Map.write (Map<K, Map<K2, V>>) would
23
- clobber a single shared array mid-iteration; the stack gives each frame
24
- its own slot. Mirrors Shared.acquireScratch / releaseScratch.
25
- ]]
26
- local _keyStacks: { { any } } = {}
27
- local _keyDepth = 0
28
-
29
- -- Private ----------------------------------------------------------------
30
-
31
- local ensure = Base.ensure
32
- local allocDeltaId = Shared.allocDeltaId
33
- local acquireScratch = Shared.acquireScratch
34
- local releaseScratch = Shared.releaseScratch
35
- local rangeEqual = Shared.rangeEqual
36
- local copyToBuf = Shared.copyToBuf
37
- local containsDelta = Shared.containsDelta
38
- local enforceMaxCount = Shared.enforceMaxCount
39
- local writeu8 = buffer.writeu8
40
- local readu8 = buffer.readu8
41
- local bufCopy = buffer.copy
42
- local bufLen = buffer.len
43
- local varintRead = Varint.read
44
- local varintWrite = Varint.write
45
-
46
- type DeltaMapEntry = { kBuf: buffer, kLen: number, vBuf: buffer, vLen: number }
47
-
48
- local function acquireKeys(): { any }
49
- _keyDepth += 1
50
- local keys = _keyStacks[_keyDepth]
51
- if keys then
52
- return keys
53
- end
54
- keys = {}
55
- _keyStacks[_keyDepth] = keys
56
- return keys
57
- end
58
-
59
- local function releaseKeys(): ()
60
- _keyDepth -= 1
61
- end
62
-
63
- -- Module-level so the mixed-type sort path doesn't allocate a closure per write.
64
- local function tostringLess(a: any, b: any): boolean
65
- return tostring(a) < tostring(b)
66
- end
67
-
68
- local function sortKeys(keys: { any }, canSortDirect: boolean): ()
69
- if canSortDirect then
70
- table.sort(keys :: { any })
71
- else
72
- table.sort(keys, tostringLess)
73
- end
74
- end
75
-
76
- --[[
77
- Acquire a scratch keys array, populate it from `value`, nil any leftover
78
- tail entries from a prior reuse, then sort. Returns the keys array and
79
- the populated count. Caller MUST releaseKeys() after consuming the keys.
80
- ]]
81
- local function collectAndSortKeys(value: { [any]: any }, canSortDirect: boolean): ({ any }, number)
82
- local keys = acquireKeys()
83
- local count = 0
84
- for k in value do
85
- count += 1
86
- keys[count] = k
87
- end
88
- local prevTail = #keys
89
- for i = count + 1, prevTail do
90
- keys[i] = nil
91
- end
92
- sortKeys(keys, canSortDirect)
93
- return keys, count
94
- end
95
-
96
- -- Public -----------------------------------------------------------------
97
-
98
- local Map = {}
99
-
100
- function Map.map(
101
- keyCodec: Types.InternalCodec<any>,
102
- valueCodec: Types.InternalCodec<any>,
103
- maxCount: number?
104
- ): Types.InternalCodec<any>
105
- local fixedKey = keyCodec._size
106
- local fixedValue = valueCodec._size
107
- local hasUnknown = keyCodec._hasUnknown or valueCodec._hasUnknown
108
- local hasDelta = containsDelta(keyCodec) or containsDelta(valueCodec)
109
-
110
- --[[
111
- Numbers and strings sort by `<` directly; everything else (Instance,
112
- vector, mixed-type via Auto) routes through tostring. Pinned at codec
113
- creation so writes don't re-sniff the key type.
114
- ]]
115
- local typeCheck = keyCodec._typeCheck
116
- local canSortDirect = typeCheck == "number" or typeCheck == "string"
117
-
118
- local codec: Types.InternalCodec<any> = {
119
- _isMap = true,
120
- _keyCodec = keyCodec,
121
- _valueCodec = valueCodec,
122
- _maxCount = maxCount,
123
-
124
- --[[
125
- Sort keys for deterministic wire layout. Without this, two
126
- structurally-equal maps yield different byte sequences across
127
- frames, which breaks every downstream byte-equality cache (the
128
- XOR baseline and deltaMap).
129
- ]]
130
- write = function(ch: Types.ChannelState, value: { [any]: any }): ()
131
- if typeof(value) ~= "table" then
132
- Log.error(`expected table, got {typeof(value)}`)
133
- end
134
-
135
- local keys, count = collectAndSortKeys(value, canSortDirect)
136
-
137
- varintWrite(ch, count)
138
- if count == 0 then
139
- releaseKeys()
140
- return
141
- end
142
-
143
- -- Single alloc when both halves are fixed-size.
144
- if fixedKey and fixedValue then
145
- ensure(ch, count * (fixedKey + fixedValue))
146
- end
147
-
148
- for i = 1, count do
149
- local k = keys[i]
150
- keyCodec.write(ch, k)
151
- valueCodec.write(ch, value[k])
152
- end
153
- releaseKeys()
154
- end,
155
-
156
- read = function(src: buffer, pos: number, refs: { Instance }?): ({ [any]: any }, number)
157
- local count, lenBytes = varintRead(src, pos)
158
- enforceMaxCount(count, maxCount)
159
-
160
- -- Fixed-size: reject corrupt counts before per-entry decode.
161
- if fixedKey and fixedValue and count > 0 then
162
- local payloadBytes = count * (fixedKey + fixedValue)
163
- if payloadBytes > bufLen(src) - (pos + lenBytes) then
164
- Log.error(`payload {payloadBytes}B exceeds remaining buffer`)
165
- end
166
- end
167
-
168
- local result: { [any]: any } = {}
169
- local total = lenBytes
170
- for i = 1, count do
171
- local k, kc = keyCodec.read(src, pos + total, refs)
172
- if kc == 0 then
173
- Log.error(`truncated key at index {i}`)
174
- end
175
- total += kc
176
- local v, vc = valueCodec.read(src, pos + total, refs)
177
- if vc == 0 then
178
- Log.error(`truncated value at index {i}`)
179
- end
180
- total += vc
181
- result[k] = v
182
- end
183
- return result, total
184
- end,
185
- }
186
- if hasUnknown then
187
- codec._hasUnknown = true
188
- end
189
- if hasDelta then
190
- codec._hasDelta = true
191
- end
192
- return table.freeze(codec)
193
- end
194
-
195
- --[[
196
- Per-key deltaMap. Wire:
197
- [0] UNCHANGED (1 byte)
198
- [1] FULL <count varint> <(k,v) pairs ...>
199
- [2] DIFF <removeCount varint> <removed key bytes ...>
200
- <changeCount varint> <(k,v) pair bytes ...>
201
-
202
- Cache: per-key encoded value bytes for byte-equality diffing plus per-key
203
- encoded key bytes so removed-key emission doesn't re-encode the key codec
204
- for keys that no longer live in the map.
205
- ]]
206
- function Map.deltaMap(
207
- keyCodec: Types.InternalCodec<any>,
208
- valueCodec: Types.InternalCodec<any>,
209
- maxCount: number?
210
- ): Types.InternalCodec<any>
211
- -- Inner delta would chain-diff across pairs within a frame, not across frames.
212
- if containsDelta(keyCodec) then
213
- Log.error("deltaMap key codec cannot contain delta state")
214
- end
215
- if containsDelta(valueCodec) then
216
- Log.error("deltaMap value codec cannot contain delta state")
217
- end
218
-
219
- local deltaId = allocDeltaId()
220
- local typeCheck = keyCodec._typeCheck
221
- local canSortDirect = typeCheck == "number" or typeCheck == "string"
222
- local inner = Map.map(keyCodec, valueCodec, maxCount)
223
-
224
- --[[
225
- Encode each (key, value) pair into `scratch` and capture per-pair byte
226
- ranges. Returns the sorted-keys list plus four parallel arrays of
227
- offset/length so the diff path can compare and emit individual entries
228
- without re-encoding.
229
- ]]
230
- local function encodePerKey(
231
- scratch: Types.ChannelState,
232
- value: { [any]: any }
233
- ): ({ any }, { number }, { number }, { number }, { number })
234
- local keys, count = collectAndSortKeys(value, canSortDirect)
235
- local kOff = table.create(count)
236
- local kLen = table.create(count)
237
- local vOff = table.create(count)
238
- local vLen = table.create(count)
239
-
240
- for i = 1, count do
241
- local k = keys[i]
242
- local before = scratch.cursor
243
- keyCodec.write(scratch, k)
244
- local mid = scratch.cursor
245
- kOff[i] = before
246
- kLen[i] = mid - before
247
- valueCodec.write(scratch, value[k])
248
- vOff[i] = mid
249
- vLen[i] = scratch.cursor - mid
250
- end
251
- return keys, kOff, kLen, vOff, vLen
252
- end
253
-
254
- return table.freeze({
255
- _isDelta = true,
256
- _isMap = true,
257
- _keyCodec = keyCodec,
258
- _valueCodec = valueCodec,
259
- _maxCount = maxCount,
260
-
261
- write = function(ch: Types.ChannelState, value: { [any]: any }): ()
262
- if typeof(value) ~= "table" then
263
- Log.error(`expected table, got {typeof(value)}`)
264
- end
265
-
266
- local cache = ch.deltas[deltaId] :: any
267
- local scratch = acquireScratch()
268
- local keys, kOff, kLen, vOff, vLen = encodePerKey(scratch, value)
269
- local count = #keys
270
- local scratchBuf = scratch.buff
271
-
272
- -- First frame: emit FULL. Per-key scratch bytes ARE the inner map payload.
273
- if not cache then
274
- ensure(ch, 1)
275
- writeu8(ch.buff, ch.cursor, DM_FULL)
276
- ch.cursor += 1
277
- varintWrite(ch, count)
278
- local payloadLen = scratch.cursor
279
- ensure(ch, payloadLen)
280
- bufCopy(ch.buff, ch.cursor, scratchBuf, 0, payloadLen)
281
- ch.cursor += payloadLen
282
-
283
- local perKey: { [any]: DeltaMapEntry } = {}
284
- for i = 1, count do
285
- local kbLen = kLen[i]
286
- local vbLen = vLen[i]
287
- perKey[keys[i]] = {
288
- kBuf = copyToBuf(nil, scratchBuf, kOff[i], kbLen),
289
- kLen = kbLen,
290
- vBuf = copyToBuf(nil, scratchBuf, vOff[i], vbLen),
291
- vLen = vbLen,
292
- }
293
- end
294
- ch.deltas[deltaId] = { perKey = perKey } :: any
295
- releaseKeys()
296
- releaseScratch()
297
- return
298
- end
299
-
300
- local cachedPerKey = cache.perKey :: { [any]: DeltaMapEntry }
301
-
302
- local seen: { [any]: boolean } = {}
303
- local changed: { number } = {}
304
- local changedCount = 0
305
- for i = 1, count do
306
- local k = keys[i]
307
- seen[k] = true
308
- local entry = cachedPerKey[k]
309
- local newLen = vLen[i]
310
- if
311
- not entry
312
- or newLen ~= entry.vLen
313
- or not rangeEqual(scratchBuf, vOff[i], entry.vBuf, 0, newLen)
314
- then
315
- changedCount += 1
316
- changed[changedCount] = i
317
- end
318
- end
319
-
320
- local removed: { any } = {}
321
- local removedCount = 0
322
- for k in cachedPerKey do
323
- if not seen[k] then
324
- removedCount += 1
325
- removed[removedCount] = k
326
- end
327
- end
328
-
329
- if removedCount == 0 and changedCount == 0 then
330
- ensure(ch, 1)
331
- writeu8(ch.buff, ch.cursor, DM_UNCHANGED)
332
- ch.cursor += 1
333
- releaseKeys()
334
- releaseScratch()
335
- return
336
- end
337
-
338
- -- Sort removed keys so the XOR baseline can collapse identical drops.
339
- sortKeys(removed, canSortDirect)
340
-
341
- ensure(ch, 1)
342
- writeu8(ch.buff, ch.cursor, DM_DIFF)
343
- ch.cursor += 1
344
-
345
- varintWrite(ch, removedCount)
346
- for i = 1, removedCount do
347
- local entry = cachedPerKey[removed[i]]
348
- local n = entry.kLen
349
- ensure(ch, n)
350
- bufCopy(ch.buff, ch.cursor, entry.kBuf, 0, n)
351
- ch.cursor += n
352
- end
353
-
354
- varintWrite(ch, changedCount)
355
- for i = 1, changedCount do
356
- local idx = changed[i]
357
- local kbLen = kLen[idx]
358
- local vbLen = vLen[idx]
359
- ensure(ch, kbLen + vbLen)
360
- bufCopy(ch.buff, ch.cursor, scratchBuf, kOff[idx], kbLen)
361
- bufCopy(ch.buff, ch.cursor + kbLen, scratchBuf, vOff[idx], vbLen)
362
- ch.cursor += kbLen + vbLen
363
- end
364
-
365
- -- Update cache: drop removed, refresh changed, leave untouched in place.
366
- for i = 1, removedCount do
367
- cachedPerKey[removed[i]] = nil
368
- end
369
- for i = 1, changedCount do
370
- local idx = changed[i]
371
- local k = keys[idx]
372
- local kbLen = kLen[idx]
373
- local vbLen = vLen[idx]
374
- local entry = cachedPerKey[k]
375
- if entry then
376
- entry.kBuf = copyToBuf(entry.kBuf, scratchBuf, kOff[idx], kbLen)
377
- entry.kLen = kbLen
378
- entry.vBuf = copyToBuf(entry.vBuf, scratchBuf, vOff[idx], vbLen)
379
- entry.vLen = vbLen
380
- else
381
- cachedPerKey[k] = {
382
- kBuf = copyToBuf(nil, scratchBuf, kOff[idx], kbLen),
383
- kLen = kbLen,
384
- vBuf = copyToBuf(nil, scratchBuf, vOff[idx], vbLen),
385
- vLen = vbLen,
386
- }
387
- end
388
- end
389
-
390
- releaseKeys()
391
- releaseScratch()
392
- end,
393
-
394
- read = function(src: buffer, pos: number, refs: { Instance }?): ({ [any]: any }, number)
395
- if pos >= bufLen(src) then
396
- Log.error("truncated deltaMap header")
397
- end
398
- local flag = readu8(src, pos)
399
-
400
- if flag == DM_UNCHANGED then
401
- local cached = Baseline.getCache(deltaId)
402
- if cached == nil then
403
- Log.error("UNCHANGED flag before any FULL frame; baseline missing")
404
- end
405
- return cached, 1
406
- end
407
-
408
- if flag == DM_FULL then
409
- local value, consumed = inner.read(src, pos + 1, refs)
410
- Baseline.setCache(deltaId, value)
411
- return value, 1 + consumed
412
- end
413
-
414
- if flag == DM_DIFF then
415
- local cached = Baseline.getCache(deltaId)
416
- if cached == nil then
417
- Log.error("deltaMap DIFF before any FULL frame; baseline missing")
418
- end
419
- local result: { [any]: any } = table.clone(cached)
420
- local total = 1
421
-
422
- local removeCount, rcLen = varintRead(src, pos + total)
423
- if rcLen == 0 then
424
- Log.error("truncated deltaMap remove count")
425
- end
426
- -- Both counts bounded by maxCount; otherwise a malicious DIFF
427
- -- could spin the loop arbitrarily long before erroring on
428
- -- buffer overrun.
429
- enforceMaxCount(removeCount, maxCount, "removeCount")
430
- total += rcLen
431
- for _ = 1, removeCount do
432
- local k, kc = keyCodec.read(src, pos + total, refs)
433
- if kc == 0 then
434
- Log.error("truncated deltaMap removed key")
435
- end
436
- total += kc
437
- result[k] = nil
438
- end
439
-
440
- local changeCount, ccLen = varintRead(src, pos + total)
441
- if ccLen == 0 then
442
- Log.error("truncated deltaMap change count")
443
- end
444
- enforceMaxCount(changeCount, maxCount, "changeCount")
445
- total += ccLen
446
- for _ = 1, changeCount do
447
- local k, kc = keyCodec.read(src, pos + total, refs)
448
- if kc == 0 then
449
- Log.error("truncated deltaMap changed key")
450
- end
451
- total += kc
452
- local v, vc = valueCodec.read(src, pos + total, refs)
453
- if vc == 0 then
454
- Log.error("truncated deltaMap changed value")
455
- end
456
- total += vc
457
- result[k] = v
458
- end
459
-
460
- Baseline.setCache(deltaId, result)
461
- return result, total
462
- end
463
-
464
- Log.error(`invalid deltaMap flag {flag}`)
465
- end,
466
- }) :: Types.InternalCodec<any>
467
- end
468
-
469
- return table.freeze(Map)
@@ -1,54 +0,0 @@
1
- --!strict
2
- --!native
3
- -- Optional codec. 1-byte present/absent flag, value only when present.
4
-
5
- local Channel = require(script.Parent.Parent.Parent.internal.Channel)
6
- local Log = require(script.Parent.Parent.Parent.util.Log)
7
- local Shared = require(script.Parent.Parent.composite.Shared)
8
- local Types = require(script.Parent.Parent.Parent.Types)
9
-
10
- -- Private ----------------------------------------------------------------
11
-
12
- local writeByte = Channel.writeByte
13
- local readu8 = buffer.readu8
14
- local bufferLen = buffer.len
15
-
16
- -- Public -----------------------------------------------------------------
17
-
18
- local Optional = {}
19
-
20
- function Optional.optional(inner: Types.InternalCodec<any>): Types.InternalCodec<any>
21
- local codec: Types.InternalCodec<any> = {
22
- _isOptional = true,
23
- _inner = inner,
24
-
25
- write = function(ch: Types.ChannelState, value: any): ()
26
- if value == nil then
27
- writeByte(ch, 0)
28
- return
29
- end
30
- writeByte(ch, 1)
31
- inner.write(ch, value)
32
- end,
33
-
34
- read = function(src: buffer, pos: number, refs: { Instance }?): (any, number)
35
- Log.assert(pos < bufferLen(src), "presence byte missing at end of buffer")
36
- if readu8(src, pos) == 0 then
37
- return nil, 1
38
- end
39
- local value, consumed = inner.read(src, pos + 1, refs)
40
- return value, 1 + consumed
41
- end,
42
- }
43
-
44
- -- Propagate _hasUnknown so Gate skips schema validation upstream.
45
- if inner._hasUnknown then
46
- codec._hasUnknown = true
47
- end
48
- if Shared.containsDelta(inner) then
49
- codec._hasDelta = true
50
- end
51
- return table.freeze(codec)
52
- end
53
-
54
- return table.freeze(Optional)