@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
@@ -0,0 +1,114 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- What a handle is bound to, and what it was asked to do before there was anything to bind it to.
4
+
5
+ local Types = require (script.Parent.Parent.Types)
6
+
7
+ local Handles = {}
8
+
9
+ -- Types ---------------------------------------------------------------
10
+
11
+ -- What a handle knows about where it ended up, which is nothing until it is told.
12
+ export type Live = {
13
+ space: string?,
14
+ name: string?,
15
+ id: number?,
16
+ def: any,
17
+ session: any,
18
+ isServer: boolean,
19
+ waiting: { (any) -> () },
20
+ }
21
+
22
+ -- An attachment made before there was anything to attach to.
23
+ export type Waiting = {
24
+ connected: boolean,
25
+ held: Types.Connection?,
26
+ }
27
+
28
+ -- Private -------------------------------------------------------------
29
+
30
+ --[[
31
+ A connection to something that does not exist yet, ended the same way as one that does.
32
+
33
+ A metatable rather than a closure per attachment, because a handle may be listened to as often
34
+ as a caller likes and the pair of fields is the whole of what one of these is.
35
+ ]]
36
+ local Attached = {}
37
+ Attached.__index = Attached
38
+
39
+ function Attached.disconnect (self: Waiting)
40
+ self.connected = false
41
+
42
+ local held = self.held
43
+ if held ~= nil then held:disconnect () end
44
+ end
45
+
46
+ -- Public --------------------------------------------------------------
47
+
48
+ --[[
49
+ A fresh binding, which every handle is made holding one of.
50
+
51
+ Made by the handle rather than here, and typed here, because what fills it is the calls below
52
+ and nothing a caller can reach.
53
+ ]]
54
+ function Handles.live (): Live
55
+ return {
56
+ space = nil,
57
+ name = nil,
58
+ id = nil,
59
+ def = nil,
60
+ session = nil,
61
+ isServer = false,
62
+ waiting = {},
63
+ }
64
+ end
65
+
66
+ --[[
67
+ Something to do to this handle once there is a session to do it with.
68
+
69
+ Run now where there is one and held where there is not, so a caller who attaches before a
70
+ namespace opens and one who attaches after are asking for the same thing and get it.
71
+ ]]
72
+ function Handles.waiting (of: Live, run: (any) -> ())
73
+ local session = of.session
74
+ if session ~= nil then
75
+ run (session)
76
+ return
77
+ end
78
+
79
+ table.insert (of.waiting, run)
80
+ end
81
+
82
+ -- A listener attached whenever the caller liked, and the connection that ends it either way.
83
+ function Handles.later (of: Live, bind: (any) -> Types.Connection): Types.Connection
84
+ local session = of.session
85
+ if session ~= nil then return bind (session) end
86
+
87
+ local held: Waiting = setmetatable ({ connected = true, held = nil }, Attached) :: any
88
+ table.insert (of.waiting, function (opened: any)
89
+ if not held.connected then return end
90
+ held.held = bind (opened)
91
+ end)
92
+
93
+ return (held :: any) :: Types.Connection
94
+ end
95
+
96
+ --[[
97
+ A handle, bound to what its namespace compiled it into, and everything it was owed since.
98
+
99
+ The binding is written before anything waiting runs, because what waits is listeners and
100
+ responders and both of them reach back through the handle for the id they attach under.
101
+ ]]
102
+ function Handles.opened (of: Live, def: any, session: any, isServer: boolean)
103
+ of.id = def.id
104
+ of.def = def
105
+ of.session = session
106
+ of.isServer = isServer
107
+
108
+ for _, run in of.waiting do
109
+ run (session)
110
+ end
111
+ table.clear (of.waiting)
112
+ end
113
+
114
+ return table.freeze (Handles)
@@ -0,0 +1,90 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- The two messages the handshake lane carries, and the judgement each one earns.
4
+
5
+ local Catalog = require (script.Parent.Parent.kernel.Catalog)
6
+ local Log = require (script.Parent.Parent.kernel.Log)
7
+ local Protocol = require (script.Parent.Parent.wire.Protocol)
8
+ local Wide = require (script.Parent.Parent.kernel.Wide)
9
+
10
+ local Handshake = {}
11
+
12
+ -- Constants -----------------------------------------------------------
13
+
14
+ -- What each message weighs, which is the whole of what tells the two apart, and where a field sits.
15
+ const HELLO = Protocol.HELLO_BYTES
16
+ const VERDICT = Protocol.VERDICT_BYTES
17
+ const FIELD = Protocol.VERDICT_FIELD
18
+
19
+ -- Private -------------------------------------------------------------
20
+
21
+ --[[
22
+ One code for both sides. A hello reaching a client and a verdict reaching a server are one event
23
+ told from two ends, and neither end has anything to say about the bytes past that.
24
+ ]]
25
+ local function unspoken ()
26
+ local facts: Log.Facts = { code = Catalog.HELLO }
27
+ Log.warn (Log.line (Catalog.HELLO, facts), facts)
28
+ end
29
+
30
+ -- Two builds that cannot speak to one another, as the one sentence both machines read it as.
31
+ local function mismatch (ours: Wide.Word, theirs: Wide.Word): (string, Log.Facts)
32
+ local facts: Log.Facts =
33
+ { code = Catalog.MISMATCH, ours = Wide.text (ours), theirs = Wide.text (theirs) }
34
+ return Log.line (Catalog.MISMATCH, facts), facts
35
+ end
36
+
37
+ -- Public --------------------------------------------------------------
38
+
39
+ function Handshake.hello (ours: Wide.Word): buffer
40
+ local out = buffer.create (HELLO)
41
+ Wide.write (out, 0, ours)
42
+ return out
43
+ end
44
+
45
+ -- The verdict a hello has earned, and whether the machine that sent it may be spoken to.
46
+ function Handshake.verdict (ours: Wide.Word, epoch: number, bytes: buffer): (buffer?, boolean)
47
+ if buffer.len (bytes) ~= HELLO then
48
+ unspoken ()
49
+ return nil, false
50
+ end
51
+
52
+ local theirs = Wide.read (bytes, 0)
53
+ local out = buffer.create (VERDICT)
54
+
55
+ if Wide.same (theirs, ours) then
56
+ buffer.writeu8 (out, 0, Protocol.VERDICT_ACCEPT)
57
+ buffer.writef64 (out, FIELD, epoch)
58
+ return out, true
59
+ end
60
+
61
+ Log.warn (mismatch (ours, theirs))
62
+
63
+ buffer.writeu8 (out, 0, Protocol.VERDICT_REJECT)
64
+ Wide.write (out, FIELD, ours)
65
+ return out, false
66
+ end
67
+
68
+ --[[
69
+ The namespace epoch, or nothing where the lane carried no verdict yet. A refusal is the third
70
+ way out and never comes back: two builds that disagree cannot be made to agree at run time, so
71
+ it raises where a message nobody can read only warns.
72
+ ]]
73
+ function Handshake.judged (ours: Wide.Word, bytes: buffer): number?
74
+ if buffer.len (bytes) ~= VERDICT then
75
+ unspoken ()
76
+ return nil
77
+ end
78
+
79
+ local said = buffer.readu8 (bytes, 0)
80
+ if said == Protocol.VERDICT_ACCEPT then return buffer.readf64 (bytes, FIELD) end
81
+
82
+ if said ~= Protocol.VERDICT_REJECT then
83
+ unspoken ()
84
+ return nil
85
+ end
86
+
87
+ return Log.error (mismatch (ours, Wide.read (bytes, FIELD)))
88
+ end
89
+
90
+ return table.freeze (Handshake)
@@ -0,0 +1,196 @@
1
+ --!strict
2
+ --!optimize 2
3
+ -- Requests in flight: the id each waits under, the deadline it waits to, and every way out.
4
+
5
+ local Heap = require (script.Parent.Parent.kernel.Heap)
6
+ local Log = require (script.Parent.Parent.kernel.Log)
7
+ local Protocol = require (script.Parent.Parent.wire.Protocol)
8
+ local Types = require (script.Parent.Parent.Types)
9
+
10
+ local Pending = {}
11
+ Pending.__index = Pending
12
+
13
+ -- Constants -----------------------------------------------------------
14
+
15
+ -- Twice the live ceiling, so the walk for a free id always has somewhere to go and cannot fail.
16
+ const SPACE = Protocol.QUERY_CAP * 2
17
+
18
+ -- Types ---------------------------------------------------------------
19
+
20
+ --[[
21
+ One request nobody has answered. Its deadline is here as well as in the heap, since a heap entry
22
+ outlives its request: an id comes round a lap later and the entry popping then belongs to the
23
+ one before it.
24
+ ]]
25
+ type Entry = {
26
+ read definition: string,
27
+ read player: Player?,
28
+ read opened: number,
29
+ read at: number,
30
+ read complete: Types.Outcome<any>,
31
+ }
32
+
33
+ export type Pending = {
34
+ read open: (
35
+ self: Pending,
36
+ now: number,
37
+ definition: string,
38
+ player: Player?,
39
+ timeout: number?,
40
+ complete: Types.Outcome<any>
41
+ ) -> number,
42
+ read answer: (self: Pending, id: number, value: any) -> boolean,
43
+ read fail: (self: Pending, id: number, code: Types.OutcomeCode, now: number) -> boolean,
44
+ read sweep: (self: Pending, now: number) -> (),
45
+ read rejectFor: (self: Pending, player: Player, now: number) -> (),
46
+ read rejectAll: (self: Pending, now: number) -> (),
47
+ }
48
+
49
+ type Self = {
50
+ namespace: string,
51
+ live: { [number]: Entry },
52
+ count: number,
53
+ next: number,
54
+ deadlines: Heap.Heap,
55
+ }
56
+
57
+ -- Private -------------------------------------------------------------
58
+
59
+ -- A request lifted out of the live set. Every way out goes through here, so one resolves once.
60
+ local function taken (self: Self, id: number): Entry?
61
+ local entry = self.live[id]
62
+ if entry == nil then return nil end
63
+
64
+ self.live[id] = nil
65
+ self.count -= 1
66
+ return entry
67
+ end
68
+
69
+ -- Public --------------------------------------------------------------
70
+
71
+ function Pending.new (namespace: string): Pending
72
+ local self: Self = {
73
+ namespace = namespace,
74
+ live = {},
75
+ count = 0,
76
+ next = 0,
77
+ deadlines = Heap.new (),
78
+ }
79
+ return (setmetatable (self, Pending) :: any) :: Pending
80
+ end
81
+
82
+ -- A request, under the first id nothing is waiting on.
83
+ function Pending.open (
84
+ self: Self,
85
+ now: number,
86
+ definition: string,
87
+ player: Player?,
88
+ timeout: number?,
89
+ complete: Types.Outcome<any>
90
+ ): number
91
+ if self.count == Protocol.QUERY_CAP then
92
+ Log.refuse (
93
+ `{self.namespace} has {Protocol.QUERY_CAP} requests in flight, which is the ceiling`
94
+ )
95
+ end
96
+
97
+ local id = self.next
98
+ while self.live[id] ~= nil do
99
+ id = (id + 1) % SPACE
100
+ end
101
+ self.next = (id + 1) % SPACE
102
+
103
+ local at = now + (timeout or Protocol.QUERY_TIMEOUT)
104
+ self.live[id] = {
105
+ definition = definition,
106
+ player = player,
107
+ opened = now,
108
+ at = at,
109
+ complete = complete,
110
+ }
111
+ self.count += 1
112
+
113
+ Heap.push (self.deadlines, at, id)
114
+ return id
115
+ end
116
+
117
+ --[[
118
+ The reply arrived. Answers whether anybody was waiting, an id nobody waits on being a reply to a
119
+ request that already ended or a frame nobody here sent for.
120
+ ]]
121
+ function Pending.answer (self: Self, id: number, value: any): boolean
122
+ local entry = taken (self, id)
123
+ if entry == nil then return false end
124
+
125
+ entry.complete (true, value, nil)
126
+ return true
127
+ end
128
+
129
+ --[[
130
+ The request ended as one of the four outcomes. The elapsed time rides on all of them, a caller
131
+ reading how long a leave took being owed the same number as one reading a timeout.
132
+ ]]
133
+ function Pending.fail (self: Self, id: number, code: Types.OutcomeCode, now: number): boolean
134
+ local entry = taken (self, id)
135
+ if entry == nil then return false end
136
+
137
+ entry.complete (
138
+ false,
139
+ code,
140
+ table.freeze ({ definition = entry.definition, elapsed = now - entry.opened })
141
+ )
142
+ return true
143
+ end
144
+
145
+ -- Every deadline that has passed, and only the requests still waiting on one of them.
146
+ function Pending.sweep (self: Self, now: number)
147
+ local heap = self.deadlines
148
+
149
+ while true do
150
+ local at, id = Heap.peek (heap)
151
+ if at == nil or at > now then return end
152
+ Heap.pop (heap)
153
+
154
+ local entry = self.live[id :: number]
155
+ if entry ~= nil and entry.at <= now then
156
+ Pending.fail (self, id :: number, "timeout", now)
157
+ end
158
+ end
159
+ end
160
+
161
+ --[[
162
+ Everything owed by somebody who has gone, named for what happened: a caller branching on a leave
163
+ knows not to retry, where one told it timed out would.
164
+ ]]
165
+ function Pending.rejectFor (self: Self, player: Player, now: number)
166
+ local taking: { number } = {}
167
+ for id, entry in self.live do
168
+ if entry.player == player then table.insert (taking, id) end
169
+ end
170
+
171
+ for _, id in taking do
172
+ Pending.fail (self, id, "leave", now)
173
+ end
174
+ end
175
+
176
+ --[[
177
+ Everything at once, which is a namespace closing. The live set is replaced before anything is
178
+ answered, so a completion opening a request of its own lands in the new one and nothing in the
179
+ old can be answered twice.
180
+ ]]
181
+ function Pending.rejectAll (self: Self, now: number)
182
+ local live = self.live
183
+
184
+ self.live = {}
185
+ self.count = 0
186
+
187
+ for _, entry in live do
188
+ entry.complete (
189
+ false,
190
+ "shutdown",
191
+ table.freeze ({ definition = entry.definition, elapsed = now - entry.opened })
192
+ )
193
+ end
194
+ end
195
+
196
+ return table.freeze (Pending)