@axpecter/lync 2.3.3 → 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 -317
  77. package/src/api/Query.luau +0 -338
  78. package/src/api/Scope.luau +0 -90
  79. package/src/api/Signal.luau +0 -193
  80. package/src/codec/Base.luau +0 -136
  81. package/src/codec/composite/Array.luau +0 -473
  82. package/src/codec/composite/Map.luau +0 -485
  83. package/src/codec/composite/Optional.luau +0 -54
  84. package/src/codec/composite/Shared.luau +0 -311
  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 -160
  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 -484
  120. package/src/internal/Middleware.luau +0 -100
  121. package/src/internal/Pool.luau +0 -66
  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 -233
  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
@@ -0,0 +1,118 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- How a buffer holds things: a field at a bit, the order two ranges compare in, and a seal.
4
+
5
+ local Protocol = require (script.Parent.Protocol)
6
+ local Wide = require (script.Parent.Parent.kernel.Wide)
7
+
8
+ local Bytes = {}
9
+
10
+ -- Constants -----------------------------------------------------------
11
+
12
+ -- Bytes in the wide word, whichever of its two carriers this build got.
13
+ const STRIDE = 8
14
+
15
+ const BYTE = Protocol.BYTE_BITS
16
+
17
+ -- Public --------------------------------------------------------------
18
+
19
+ -- A run of bits as the whole bytes that hold it, rounded up.
20
+ function Bytes.whole (bits: number): number return math.ceil (bits / BYTE) end
21
+
22
+ -- One value of `width` bits at a bit offset, and the offset past it.
23
+ function Bytes.put (b: buffer, at: number, width: number, value: number): number
24
+ local held = at
25
+ local left = width
26
+ local of = value
27
+
28
+ while left > 0 do
29
+ local byte = held // BYTE
30
+ local shift = held % BYTE
31
+ local room = BYTE - shift
32
+ local step = if left < room then left else room
33
+
34
+ local was = if shift == 0 then 0 else buffer.readu8 (b, byte)
35
+ local piece = bit32.lshift (bit32.extract (of, 0, step), shift)
36
+ buffer.writeu8 (b, byte, bit32.bor (was, piece))
37
+
38
+ of = bit32.rshift (of, step)
39
+ held += step
40
+ left -= step
41
+ end
42
+
43
+ return at + width
44
+ end
45
+
46
+ --[[
47
+ The same value back, and the offset past it. A width of nothing is a value of nothing, which is
48
+ what a ranged int over one possibility is, and it reads no byte at all.
49
+ ]]
50
+ function Bytes.take (b: buffer, at: number, width: number): (number, number)
51
+ local of = 0
52
+ local held = at
53
+ local left = width
54
+ local got = 0
55
+
56
+ while left > 0 do
57
+ local byte = held // BYTE
58
+ local shift = held % BYTE
59
+ local room = BYTE - shift
60
+ local step = if left < room then left else room
61
+
62
+ local piece = bit32.extract (buffer.readu8 (b, byte), shift, step)
63
+ of = bit32.bor (of, bit32.lshift (piece, got))
64
+
65
+ got += step
66
+ held += step
67
+ left -= step
68
+ end
69
+
70
+ return of, at + width
71
+ end
72
+
73
+ -- The byte a bit run ends on, and whether what it left above itself is zero.
74
+ function Bytes.aligned (b: buffer, at: number): (number, boolean)
75
+ local over = at % BYTE
76
+ if over == 0 then return at // BYTE, true end
77
+
78
+ local pad = bit32.rshift (buffer.readu8 (b, at // BYTE), over)
79
+ return at // BYTE + 1, pad == 0
80
+ end
81
+
82
+ --[[
83
+ The swap makes the word compare a byte compare: a read takes the first byte as the least of the
84
+ word, and reversing it spells the magnitude the bytes read as. A word is taken only where a
85
+ whole one remains inside the shorter range, because the bytes past it are not ours. Never
86
+ through a float, where plus and minus zero are equal and one NaN payload is unequal.
87
+ ]]
88
+ @native
89
+ function Bytes.rangeLess (b: buffer, atA: number, lenA: number, atB: number, lenB: number): boolean
90
+ local shared = math.min (lenA, lenB)
91
+ local words = shared - shared % STRIDE
92
+ local at = 0
93
+
94
+ while at < words do
95
+ local wordA = Wide.ordered (b, atA + at)
96
+ local wordB = Wide.ordered (b, atB + at)
97
+ if not Wide.same (wordA, wordB) then return Wide.below (wordA, wordB) end
98
+ at += STRIDE
99
+ end
100
+
101
+ while at < shared do
102
+ local byteA = buffer.readu8 (b, atA + at)
103
+ local byteB = buffer.readu8 (b, atB + at)
104
+ if byteA ~= byteB then return byteA < byteB end
105
+ at += 1
106
+ end
107
+
108
+ return lenA < lenB
109
+ end
110
+
111
+ -- A copy rather than the scratch, because the next block encodes into that same scratch.
112
+ function Bytes.seal (scratch: buffer, length: number): buffer
113
+ local sealed = buffer.create (length)
114
+ buffer.copy (sealed, 0, scratch, 0, length)
115
+ return sealed
116
+ end
117
+
118
+ return table.freeze (Bytes)
@@ -0,0 +1,37 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- Milliseconds against an epoch, the field they wrap into, and the instant one is unwrapped to.
4
+
5
+ local Protocol = require (script.Parent.Protocol)
6
+
7
+ local Clock = {}
8
+
9
+ -- Constants -----------------------------------------------------------
10
+
11
+ const RATE = Protocol.STAMP_RATE
12
+ const SPAN = 2 ^ Protocol.STAMP_BITS
13
+
14
+ -- Public --------------------------------------------------------------
15
+
16
+ --[[
17
+ Floored rather than rounded, so a count never runs ahead of the clock it read, and negative
18
+ where the reading is behind the epoch: a client's shared clock sits there for a moment after
19
+ start and clamping would move its stamps.
20
+ ]]
21
+ function Clock.elapsed (now: number, epoch: number): number
22
+ local since = now - epoch
23
+ return math.floor (since * RATE)
24
+ end
25
+
26
+ -- The remainder follows the divisor, so a negative count lands inside the field, not below it.
27
+ function Clock.stamp (elapsed: number): number return elapsed % SPAN end
28
+
29
+ --[[
30
+ The instant carrying this stamp nearest the estimate. At exactly half a space the two candidates
31
+ tie and the rounding takes the one further from the stamp, which is arbitrary and pinned.
32
+ ]]
33
+ function Clock.unwrap (stamp: number, elapsed: number): number
34
+ return stamp + math.round ((elapsed - stamp) / SPAN) * SPAN
35
+ end
36
+
37
+ return table.freeze (Clock)
@@ -0,0 +1,110 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- The one home of every wire constant. Nothing else in the repository may state one.
4
+
5
+ local Protocol = {}
6
+
7
+ -- What both machines have to agree on before either spends a byte on the other's schema.
8
+ Protocol.VERSION = 4
9
+
10
+ --[[
11
+ The handshake lane's whole grammar: what each of the two messages weighs, where a verdict keeps
12
+ its one field, what a verdict says first, and the whole of what one can say.
13
+ ]]
14
+ Protocol.HELLO_BYTES = 8
15
+ Protocol.VERDICT_BYTES = 9
16
+ Protocol.VERDICT_FIELD = 1
17
+ Protocol.VERDICT_REJECT = 0
18
+ Protocol.VERDICT_ACCEPT = 1
19
+
20
+ -- How a bit is addressed, which is the whole of what a byte means to this format.
21
+ Protocol.BYTE_BITS = 8
22
+
23
+ --[[
24
+ The number domain. A signed varint folds its sign into the value it carries, so it reaches half
25
+ as far in each direction and its edge sits a bit below the one a double counts exactly to.
26
+ ]]
27
+ Protocol.EXACT = 9007199254740992
28
+ Protocol.VLI_EDGE = 4503599627370495
29
+ Protocol.VARINT_GROUPS = 8
30
+ Protocol.BIT_CEILING = 24
31
+
32
+ --[[
33
+ A varint group: the bit that says another follows, the seven under it, and half of those.
34
+
35
+ The format's own and not the encoder's, since a reader who has the bytes and not the source
36
+ has to be able to take one apart, and half a group is where a signed value's sign folds.
37
+ ]]
38
+ Protocol.VARINT_BITS = 7
39
+ Protocol.VARINT_MORE = 0x80
40
+ Protocol.VARINT_GROUP = 0x7F
41
+ Protocol.VARINT_HALF = 0x40
42
+
43
+ -- Schema legality.
44
+ Protocol.MAX_FIELDS = 64
45
+
46
+ --[[
47
+ The unreliable lane. The margin is not measured and carries no date, because nothing has
48
+ measured it: zero is the documented engine threshold taken at its word, and a margin above it
49
+ is a number somebody would have to put a real network behind before writing down.
50
+ ]]
51
+ Protocol.UNRELIABLE_CEILING = 1000
52
+ Protocol.UNRELIABLE_MARGIN = 0
53
+ Protocol.UNRELIABLE_CAP = Protocol.UNRELIABLE_CEILING - Protocol.UNRELIABLE_MARGIN
54
+ Protocol.MAX_FIRE = 1000000
55
+
56
+ -- Budgets, in bytes, and the detector window in seconds.
57
+ Protocol.BUDGET_RATE = 32768
58
+ Protocol.BUDGET_FLOOR = 1024
59
+ Protocol.SECTION_BYTES = Protocol.BUDGET_FLOOR
60
+ Protocol.DETECTOR_WINDOW = 1
61
+
62
+ -- Queries, the timeout in seconds.
63
+ Protocol.QUERY_TIMEOUT = 10
64
+ Protocol.QUERY_CAP = 32768
65
+
66
+ -- Sequences and stamps.
67
+ Protocol.NEWEST_WINDOW = 32768
68
+ Protocol.NEWEST_GENS = 4
69
+ Protocol.STAMP_BITS = 32
70
+ Protocol.STAMP_RATE = 1000
71
+
72
+ -- A packed colour's channel widths, least significant first.
73
+ Protocol.RGB565_RED = 5
74
+ Protocol.RGB565_GREEN = 6
75
+ Protocol.RGB565_BLUE = 5
76
+
77
+ --[[
78
+ Which component a turn left behind, in the order they are counted. The tag a frame carries is
79
+ one of these four, which is also why it is two bits wide.
80
+ ]]
81
+ Protocol.QUAT_X = 0
82
+ Protocol.QUAT_Y = 1
83
+ Protocol.QUAT_Z = 2
84
+ Protocol.QUAT_W = 3
85
+
86
+ --[[
87
+ How far one component of the octahedral fold runs, in degrees, which is what a precision stated
88
+ for one is read against.
89
+ ]]
90
+ Protocol.QUARTER_TURN = 90
91
+
92
+ --[[
93
+ How far the three that were kept can reach, which is the root of a half. The tag names the one
94
+ left out and it is the largest, so a kept component is no larger than that one and the two of
95
+ them squared cannot pass one, which puts both at this exactly where they are equal.
96
+ ]]
97
+ Protocol.QUAT_BOUND = 0.7071067811865476
98
+ -- The response header's outcome, which is one bit and decides whether a payload follows it.
99
+
100
+ Protocol.OUTCOME_BITS = 1
101
+
102
+ -- What a section header says it is, and how it names the fields it carries.
103
+ Protocol.SECTION_KEYFRAME = 0
104
+ Protocol.SECTION_DELTA = 1
105
+ Protocol.SECTION_REMOVAL = 2
106
+ Protocol.SECTION_CLEAR = 3
107
+ Protocol.FIELDSET_LIST = 0
108
+ Protocol.FIELDSET_MASK = 1
109
+
110
+ return table.freeze (Protocol)
@@ -0,0 +1,40 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- The u16 ring an unreliable stream is ordered by, and the rate gate over it.
4
+
5
+ local Protocol = require (script.Parent.Protocol)
6
+
7
+ local Sequence = {}
8
+
9
+ -- Constants -----------------------------------------------------------
10
+
11
+ const WINDOW = Protocol.NEWEST_WINDOW
12
+
13
+ -- The ring a sequence counts round, which is the window doubled.
14
+ const SPACE = WINDOW * 2
15
+
16
+ -- Public --------------------------------------------------------------
17
+
18
+ function Sequence.next (n: number): number return (n + 1) % SPACE end
19
+
20
+ --[[
21
+ Newer is a distance under the window, so exactly half the space apart ranks neither way and a
22
+ sequence is never newer than itself. The subtraction goes negative and the remainder follows the
23
+ divisor, which is what carries it round the ring.
24
+ ]]
25
+ function Sequence.isNewer (a: number, b: number): boolean
26
+ local apart = (a - b) % SPACE
27
+ return apart > 0 and apart < WINDOW
28
+ end
29
+
30
+ --[[
31
+ The interval runs from the last transmission, never from a division of the clock: a gate reading
32
+ the clock in buckets delivers the same rate and lets two flushes a bucket apart both through.
33
+ Two in one instant are one transmission.
34
+ ]]
35
+ function Sequence.opened (now: number, last: number?, hz: number?): boolean
36
+ if last == nil or hz == nil then return true end
37
+ return now - last >= 1 / hz
38
+ end
39
+
40
+ return table.freeze (Sequence)
@@ -0,0 +1,124 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- The two variable-length forms, `vlq` and `vli`.
4
+
5
+ local Log = require (script.Parent.Parent.kernel.Log)
6
+ local Protocol = require (script.Parent.Protocol)
7
+
8
+ local Varint = {}
9
+
10
+ -- Constants -----------------------------------------------------------
11
+
12
+ -- The continuation bit, the seven bits under it, and half a group, which the format owns.
13
+ const MORE = Protocol.VARINT_MORE
14
+ const GROUP = Protocol.VARINT_GROUP
15
+ const HALF = Protocol.VARINT_HALF
16
+
17
+ const EXACT = Protocol.EXACT
18
+ const GROUPS = Protocol.VARINT_GROUPS
19
+
20
+ -- Private -------------------------------------------------------------
21
+
22
+ --[[
23
+ A value is carried as a head group and the rest, never as one number: the zigzag of the widest
24
+ signed value wants fifty-four bits and a double holds fifty-three, and neither part wants more
25
+ than fifty-three. That is why nothing here reaches the integer domain.
26
+ ]]
27
+ @native
28
+ local function laid (out: buffer, at: number, head: number, tail: number): number
29
+ while tail > 0 do
30
+ buffer.writeu8 (out, at, head + MORE)
31
+ at += 1
32
+ head, tail = tail % MORE, tail // MORE
33
+ end
34
+
35
+ buffer.writeu8 (out, at, head)
36
+ return at + 1
37
+ end
38
+
39
+ @native
40
+ local function taken (b: buffer, at: number): (number, number, number)
41
+ local head = buffer.readu8 (b, at)
42
+ at += 1
43
+ if head < MORE then return head, 0, at end
44
+ head -= MORE
45
+
46
+ local tail, shift = 0, 1
47
+ for _ = 2, GROUPS do
48
+ local byte = buffer.readu8 (b, at)
49
+ at += 1
50
+ if byte < MORE then return head, tail + byte * shift, at end
51
+
52
+ tail += (byte - MORE) * shift
53
+ shift *= MORE
54
+ end
55
+
56
+ -- Raised bare: this answers three numbers, where a call answering `never` reads as a fall thro
57
+ error (`a varint ran past {GROUPS} groups`, 0)
58
+ end
59
+
60
+ -- Public --------------------------------------------------------------
61
+
62
+ --[[
63
+ Answers the offset past what it wrote, and refuses a value the exact domain has no place for.
64
+ A varint carries a whole number and the domain is what a double holds exactly, so what is
65
+ turned away here is a caller's own value rather than anything a frame could have carried.
66
+ ]]
67
+ @native
68
+ function Varint.write (out: buffer, at: number, value: number): number
69
+ if value < 0 or value >= EXACT then
70
+ Log.refuse (`a varint carries none to {EXACT - 1}, not {value}`)
71
+ end
72
+ return laid (out, at, value % MORE, value // MORE)
73
+ end
74
+
75
+ --[[
76
+ Answers the value and the offset past it, and refuses bytes that spell a number past the exact
77
+ domain. Refused rather than answered, because a value a double cannot hold exactly is a value
78
+ the two machines would disagree about the moment either did arithmetic on it.
79
+ ]]
80
+ @native
81
+ function Varint.read (b: buffer, at: number): (number, number)
82
+ local head, tail, after = taken (b, at)
83
+
84
+ local value = head + tail * MORE
85
+ if value >= EXACT then Log.refuse (`a varint read {value}, past the exact ceiling`) end
86
+ return value, after
87
+ end
88
+
89
+ --[[
90
+ Taken off the magnitude rather than the doubled value. A negative one sitting on a group
91
+ boundary has nothing left in its head, so the head carries the whole group and the rest gives
92
+ one up, which is the one place the two branches differ.
93
+ ]]
94
+ @native
95
+ function Varint.writeSigned (out: buffer, at: number, value: number): number
96
+ if value <= -EXACT or value >= EXACT then
97
+ Log.refuse (`a signed varint carries {1 - EXACT} to {EXACT - 1}, not {value}`)
98
+ end
99
+ if value >= 0 then return laid (out, at, (value % HALF) * 2, value // HALF) end
100
+
101
+ local magnitude = -value
102
+ local head = magnitude % HALF
103
+ if head == 0 then return laid (out, at, GROUP, magnitude // HALF - 1) end
104
+ return laid (out, at, head * 2 - 1, magnitude // HALF)
105
+ end
106
+
107
+ --[[
108
+ The same pair for the signed form, refused at both ends of the domain rather than at one. A
109
+ reader that checked only the top would take a magnitude one past the bottom and answer a number
110
+ no encoder could have written.
111
+ ]]
112
+ @native
113
+ function Varint.readSigned (b: buffer, at: number): (number, number)
114
+ local head, tail, after = taken (b, at)
115
+
116
+ local rest = tail * HALF
117
+ local value = if head % 2 == 0 then head / 2 + rest else -((head + 1) / 2 + rest)
118
+ if value <= -EXACT or value >= EXACT then
119
+ Log.refuse (`a signed varint read {value}, past the exact ceiling`)
120
+ end
121
+ return value, after
122
+ end
123
+
124
+ return table.freeze (Varint)
package/src/Types.luau DELETED
@@ -1,180 +0,0 @@
1
- --!strict
2
- -- Shared type definitions for the Lync networking library.
3
-
4
- export type ChannelState = {
5
- buff: buffer,
6
- cursor: number,
7
- size: number,
8
- refs: { Instance },
9
- refCount: number,
10
- lastId: number,
11
- countPos: number,
12
- itemCount: number,
13
- singleMode: boolean,
14
- singlePos: number,
15
- --[[
16
- Per-codec write-side delta state, keyed by deltaId. Shape is opaque
17
- and codec-internal: deltaStruct stores `{raw, len, segOff, segLen}`,
18
- deltaArray stores `{perIdx, length}`, deltaMap stores `{perKey}`,
19
- delta scalars store quantized previous values.
20
- ]]
21
- deltas: { [number]: any },
22
- prevDump: buffer?,
23
- prevDumpLen: number,
24
- currentPacket: string?,
25
- }
26
-
27
- export type Codec<T> = {
28
- write: (ch: ChannelState, value: T) -> (),
29
- read: (src: buffer, pos: number, refs: { Instance }?) -> (T, number),
30
- }
31
-
32
- --[[
33
- Optional metadata used by Gate (validation), Reader (max-item bound),
34
- Auto (type dispatch), and composite codecs (direct write/read fast path).
35
- ]]
36
- export type InternalCodec<T> = {
37
- write: (ch: ChannelState, value: T) -> (),
38
- read: (src: buffer, pos: number, refs: { Instance }?) -> (T, number),
39
- _size: number?,
40
- _directWrite: ((b: buffer, offset: number, value: T) -> ())?,
41
- _directRead: ((b: buffer, offset: number) -> T)?,
42
- _isDelta: boolean?,
43
- --[[
44
- True if any nested codec is delta. Lets the broadcast hot path skip
45
- encode-once when delta state would diverge per-receiver.
46
- ]]
47
- _hasDelta: boolean?,
48
- _isBool: boolean?,
49
- _hasUnknown: boolean?,
50
- _min: number?,
51
- _max: number?,
52
- _isInteger: boolean?,
53
- _schema: { [string]: InternalCodec<T> }?,
54
- _typeCheck: string?,
55
- --[[
56
- Composite metadata: lets Gate recurse element/variant validation
57
- instead of falling through to the generic NaN/inf scan.
58
- ]]
59
- _isOptional: boolean?,
60
- _inner: InternalCodec<T>?,
61
- _isTagged: boolean?,
62
- _variants: { [string]: InternalCodec<T> }?,
63
- _tagField: string?,
64
- _isArray: boolean?,
65
- _element: InternalCodec<T>?,
66
- _maxCount: number?,
67
- _isMap: boolean?,
68
- _keyCodec: InternalCodec<T>?,
69
- _valueCodec: InternalCodec<T>?,
70
- _isTuple: boolean?,
71
- _elements: { InternalCodec<T> }?,
72
- _isEnum: boolean?,
73
- _enumValues: { [string]: number }?,
74
- _maxStringLength: number?,
75
- }
76
-
77
- export type RateLimitState = {
78
- tokens: number,
79
- lastRefill: number,
80
- lastAccepted: number,
81
- }
82
-
83
- --[[
84
- Token-bucket (maxPerSecond + optional burst) or cooldown (cooldown
85
- seconds between accepts). Mixing both forms is undefined behavior.
86
- ]]
87
- export type RateLimitConfig = {
88
- maxPerSecond: number?,
89
- burst: number?,
90
- cooldown: number?,
91
- }
92
-
93
- --[[
94
- User-supplied per-packet validator. Returns (true, nil) on accept;
95
- (false, reason) on reject — the reason is forwarded to onDrop hooks.
96
- ]]
97
- export type ValidateFn = (data: any, player: Player) -> (boolean, string?)
98
-
99
- export type PacketOptions = {
100
- unreliable: boolean?,
101
- rateLimit: RateLimitConfig?,
102
- validate: ValidateFn?,
103
- maxPayloadBytes: number?,
104
- timestamp: ("frame" | "offset" | "full")?,
105
- }
106
-
107
- export type QueryOptions = {
108
- timeout: number?,
109
- rateLimit: RateLimitConfig?,
110
- validate: ValidateFn?,
111
- }
112
-
113
- export type Registration = {
114
- id: number,
115
- name: string,
116
- kind: number,
117
- codec: InternalCodec<any>,
118
- isUnreliable: boolean,
119
- -- Response registration id; set on REQUEST regs only.
120
- partner: number?,
121
- signal: SignalLike,
122
- rateLimit: RateLimitConfig?,
123
- validate: ValidateFn?,
124
- needsGate: boolean,
125
- maxPayloadBytes: number?,
126
- timestampMode: number,
127
- headerSize: number,
128
- _openFn: (ch: ChannelState, id: number) -> (),
129
- bytesSent: number,
130
- bytesReceived: number,
131
- fires: number,
132
- recvFires: number,
133
- drops: number,
134
- }
135
-
136
- export type SignalLike = {
137
- fire: (self: SignalLike, ...any) -> (),
138
- fireSync: (self: SignalLike, ...any) -> (),
139
- connect: (self: SignalLike, callback: (...any) -> ()) -> Connection,
140
- once: (self: SignalLike, callback: (...any) -> ()) -> Connection,
141
- wait: (self: SignalLike) -> ...any,
142
- count: (self: SignalLike) -> number,
143
- hasListeners: (self: SignalLike) -> boolean,
144
- }
145
-
146
- export type Connection = {
147
- connected: boolean,
148
- disconnect: (self: Connection) -> (),
149
- }
150
-
151
- export type ConfigureOptions = {
152
- channelMaxSize: number?,
153
- validationDepth: number?,
154
- poolSize: number?,
155
- bandwidthLimit: { softLimit: number, maxStrikes: number }?,
156
- globalRateLimit: { maxPerSecond: number }?,
157
- stats: boolean?,
158
- }
159
-
160
- export type PacketStats = {
161
- bytesSent: number,
162
- bytesReceived: number,
163
- fires: number,
164
- recvFires: number,
165
- drops: number,
166
- }
167
-
168
- export type PlayerStats = {
169
- bytesSent: number,
170
- bytesReceived: number,
171
- }
172
-
173
- --[[
174
- Server keys baselines per Player; client uses `false` since booleans are
175
- valid table keys but Players never collide with that.
176
- ]]
177
- export type BaselineKey = Player | false
178
-
179
- -- Type-only module: runtime table is empty so re-requires are cheap.
180
- return table.freeze({})