@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.
- package/LICENSE +21 -0
- package/README.md +302 -299
- package/Types.luau +215 -0
- package/api/Define.luau +154 -0
- package/api/Lifecycle.luau +119 -0
- package/api/Packet.luau +108 -0
- package/api/Query.luau +149 -0
- package/api/Set.luau +189 -0
- package/channel/Blocks.luau +124 -0
- package/channel/Group.luau +118 -0
- package/channel/Link.luau +135 -0
- package/channel/Outbox.luau +261 -0
- package/channel/Recipients.luau +129 -0
- package/channel/Transport.luau +138 -0
- package/codec/Base.luau +236 -0
- package/codec/Composites.luau +128 -0
- package/codec/Datatypes.luau +162 -0
- package/codec/Legality.luau +61 -0
- package/codec/Scalars.luau +72 -0
- package/codec/Text.luau +89 -0
- package/codec/init.luau +39 -0
- package/index.d.ts +285 -0
- package/init.luau +91 -0
- package/kernel/Bits.luau +16 -0
- package/kernel/Catalog.luau +121 -0
- package/kernel/Heap.luau +80 -0
- package/kernel/Listeners.luau +95 -0
- package/kernel/Log.luau +197 -0
- package/kernel/Tally.luau +128 -0
- package/kernel/Threads.luau +44 -0
- package/kernel/Wide.luau +267 -0
- package/package.json +15 -32
- package/runtime/Boundary.luau +180 -0
- package/runtime/Dispatch.luau +91 -0
- package/runtime/Handles.luau +114 -0
- package/runtime/Handshake.luau +90 -0
- package/runtime/Pending.luau +196 -0
- package/runtime/Router.luau +379 -0
- package/runtime/Session.luau +731 -0
- package/shape/Compile.luau +340 -0
- package/shape/Folds.luau +332 -0
- package/shape/Frames.luau +170 -0
- package/shape/Grid.luau +169 -0
- package/shape/Ir.luau +540 -0
- package/shape/Joins.luau +125 -0
- package/shape/Legality.luau +273 -0
- package/shape/Lower.luau +419 -0
- package/shape/Order.luau +64 -0
- package/shape/Regions.luau +113 -0
- package/shape/Rotation.luau +472 -0
- package/shape/Serial.luau +258 -0
- package/shape/Words.luau +89 -0
- package/shape/emit/Block.luau +453 -0
- package/shape/emit/Column.luau +338 -0
- package/shape/emit/Leaf.luau +462 -0
- package/shape/emit/Word.luau +234 -0
- package/shape/emit/init.luau +222 -0
- package/shape/init.luau +78 -0
- package/state/Apply.luau +330 -0
- package/state/Audience.luau +126 -0
- package/state/Catchup.luau +218 -0
- package/state/Coalesce.luau +43 -0
- package/state/Fieldset.luau +177 -0
- package/state/Newest.luau +339 -0
- package/state/Plan.luau +441 -0
- package/state/Sections.luau +468 -0
- package/state/Store.luau +188 -0
- package/state/Sync.luau +762 -0
- package/wire/Bytes.luau +118 -0
- package/wire/Clock.luau +37 -0
- package/wire/Protocol.luau +110 -0
- package/wire/Sequence.luau +40 -0
- package/wire/Varint.luau +124 -0
- package/src/Types.luau +0 -180
- package/src/api/Group.luau +0 -156
- package/src/api/Packet.luau +0 -317
- package/src/api/Query.luau +0 -338
- package/src/api/Scope.luau +0 -90
- package/src/api/Signal.luau +0 -193
- package/src/codec/Base.luau +0 -136
- package/src/codec/composite/Array.luau +0 -473
- package/src/codec/composite/Map.luau +0 -485
- package/src/codec/composite/Optional.luau +0 -54
- package/src/codec/composite/Shared.luau +0 -311
- package/src/codec/composite/Struct.luau +0 -494
- package/src/codec/composite/Tagged.luau +0 -103
- package/src/codec/composite/Tuple.luau +0 -143
- package/src/codec/datatype/Buffer.luau +0 -66
- package/src/codec/datatype/CFrame.luau +0 -109
- package/src/codec/datatype/Color.luau +0 -32
- package/src/codec/datatype/Instance.luau +0 -52
- package/src/codec/datatype/IntVector.luau +0 -39
- package/src/codec/datatype/NumberRange.luau +0 -39
- package/src/codec/datatype/Ray.luau +0 -36
- package/src/codec/datatype/Rect.luau +0 -31
- package/src/codec/datatype/Region.luau +0 -62
- package/src/codec/datatype/Sequence.luau +0 -184
- package/src/codec/datatype/String.luau +0 -94
- package/src/codec/datatype/UDim.luau +0 -46
- package/src/codec/datatype/Vector.luau +0 -130
- package/src/codec/meta/Auto.luau +0 -318
- package/src/codec/meta/Bitfield.luau +0 -160
- package/src/codec/meta/Custom.luau +0 -33
- package/src/codec/meta/DeltaScalar.luau +0 -390
- package/src/codec/meta/Enum.luau +0 -50
- package/src/codec/meta/Float.luau +0 -38
- package/src/codec/meta/Nothing.luau +0 -13
- package/src/codec/meta/Unknown.luau +0 -41
- package/src/codec/primitive/Bool.luau +0 -26
- package/src/codec/primitive/Float16.luau +0 -99
- package/src/codec/primitive/Int.luau +0 -59
- package/src/codec/primitive/Number.luau +0 -24
- package/src/codec/primitive/Signed.luau +0 -32
- package/src/codec/primitive/Varint.luau +0 -165
- package/src/codec/primitive/Zint.luau +0 -99
- package/src/index.d.ts +0 -423
- package/src/init.luau +0 -362
- package/src/internal/Baseline.luau +0 -57
- package/src/internal/Channel.luau +0 -484
- package/src/internal/Middleware.luau +0 -100
- package/src/internal/Pool.luau +0 -66
- package/src/internal/Registry.luau +0 -119
- package/src/internal/Transport.luau +0 -28
- package/src/transport/Bridge.luau +0 -110
- package/src/transport/Client.luau +0 -97
- package/src/transport/Gate.luau +0 -488
- package/src/transport/Reader.luau +0 -331
- package/src/transport/Server.luau +0 -233
- package/src/util/Array.luau +0 -18
- package/src/util/Buffer.luau +0 -90
- package/src/util/Constants.luau +0 -30
- package/src/util/Log.luau +0 -68
- package/src/util/Player.luau +0 -14
- package/src/util/Quantize.luau +0 -84
- package/src/util/Quat.luau +0 -124
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!optimize 2
|
|
3
|
+
-- The descriptor: a schema as text, and the sixty-four bits a handshake carries it as.
|
|
4
|
+
|
|
5
|
+
local Base = require (script.Parent.Parent.codec.Base)
|
|
6
|
+
local Order = require (script.Parent.Order)
|
|
7
|
+
local Protocol = require (script.Parent.Parent.wire.Protocol)
|
|
8
|
+
local Wide = require (script.Parent.Parent.kernel.Wide)
|
|
9
|
+
|
|
10
|
+
local Serial = {}
|
|
11
|
+
|
|
12
|
+
-- Constants -----------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
--[[
|
|
15
|
+
Built from hex rather than written as literals, because the basis is past the range a signed
|
|
16
|
+
literal covers and the string form is the one whose value is not parser-dependent.
|
|
17
|
+
]]
|
|
18
|
+
const BASIS = Wide.parse ("CBF29CE484222325")
|
|
19
|
+
const PRIME = Wide.parse ("00000100000001B3")
|
|
20
|
+
|
|
21
|
+
-- Types ---------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
--[[
|
|
24
|
+
What a build carries that a descriptor is written from. A build holds the declaration it was
|
|
25
|
+
made from beside the closures it compiled, and only the declaration is read here, so whatever
|
|
26
|
+
else a build grows never moves the text.
|
|
27
|
+
]]
|
|
28
|
+
export type Described = { read cell: Base.Cell }
|
|
29
|
+
|
|
30
|
+
-- The three ways a frame of a definition travels, and the one a caller gets free.
|
|
31
|
+
export type Delivery = "reliable" | "unreliable" | "newest"
|
|
32
|
+
|
|
33
|
+
--[[
|
|
34
|
+
A definition as the descriptor writes it, which is its codecs and every declaration that decides
|
|
35
|
+
how a frame of it travels.
|
|
36
|
+
]]
|
|
37
|
+
export type Packet = {
|
|
38
|
+
read kind: "packet",
|
|
39
|
+
read of: Described,
|
|
40
|
+
read delivery: Delivery,
|
|
41
|
+
read hz: number?,
|
|
42
|
+
read timestamped: boolean,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type Query = {
|
|
46
|
+
read kind: "query",
|
|
47
|
+
read of: Described,
|
|
48
|
+
read reply: Described,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type Set = {
|
|
52
|
+
read kind: "set",
|
|
53
|
+
read of: Described,
|
|
54
|
+
read keyField: string?,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type Frame = Packet | Query | Set
|
|
58
|
+
|
|
59
|
+
--[[
|
|
60
|
+
Every text one vocabulary reached, and the number each was first seen under. A rejection carries
|
|
61
|
+
the numbers rather than the words, because composing prose on a decode would pay for it at
|
|
62
|
+
whatever rate the other machine chooses, and the reader that catches one has this to read them
|
|
63
|
+
back out of.
|
|
64
|
+
]]
|
|
65
|
+
export type Interner = {
|
|
66
|
+
at: { [string]: number },
|
|
67
|
+
texts: { string },
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
-- Private -------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
--[[
|
|
73
|
+
A number as text it reads back from. Fourteen digits is what a double usually needs and what
|
|
74
|
+
looks like the number a caller wrote, seventeen is what one always needs, and the round trip
|
|
75
|
+
decides which. Two parameters that differ have to differ here or two schemas share one hash.
|
|
76
|
+
]]
|
|
77
|
+
local function decimal (value: number): string
|
|
78
|
+
if value == 0 then return "0" end
|
|
79
|
+
|
|
80
|
+
local short = string.format ("%.14g", value)
|
|
81
|
+
if tonumber (short) == value then return short end
|
|
82
|
+
return string.format ("%.17g", value)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
--[[
|
|
86
|
+
A caller's string, quoted and escaped, because a symbol set holds any byte a caller likes and a
|
|
87
|
+
name any character. Left bare, a name holding a comma reads as two names and a field name
|
|
88
|
+
spelling `x=bool();y` reads as two fields, and either way two schemas write one text.
|
|
89
|
+
]]
|
|
90
|
+
local function quoted (text: string): string
|
|
91
|
+
local slashed = string.gsub (text, "\\", "\\\\")
|
|
92
|
+
local marked = string.gsub (slashed, '"', '\\"')
|
|
93
|
+
return `"{marked}"`
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
-- A parameter holding several values is one slot still, so what it holds is bracketed inside it.
|
|
97
|
+
local function listed (parts: { string }): string return `[{table.concat (parts, ",")}]` end
|
|
98
|
+
|
|
99
|
+
local function vector (of: Vector3): string
|
|
100
|
+
return listed ({ decimal (of.X), decimal (of.Y), decimal (of.Z) })
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
local function colour (of: Color3): string
|
|
104
|
+
return listed ({ decimal (of.R), decimal (of.G), decimal (of.B) })
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
local function labelled (of: { string }): string
|
|
108
|
+
local parts = table.create (#of) :: { string }
|
|
109
|
+
for _, name in of do
|
|
110
|
+
table.insert (parts, quoted (name))
|
|
111
|
+
end
|
|
112
|
+
return listed (parts)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
local function palette (of: { Color3 }): string
|
|
116
|
+
local parts = table.create (#of) :: { string }
|
|
117
|
+
for _, one in of do
|
|
118
|
+
table.insert (parts, colour (one))
|
|
119
|
+
end
|
|
120
|
+
return listed (parts)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
--[[
|
|
124
|
+
Every parameter in one order, and the order is the one the surface takes them in, so each kind
|
|
125
|
+
comes out spelled the way a caller wrote it: `int(0,100)`, `str("abc",0,6)`, `vec3(unit,1)`,
|
|
126
|
+
`rotation(axis,[0,1,0],1)`. One list rather than a rule per kind, and it holds for all of them.
|
|
127
|
+
]]
|
|
128
|
+
const ORDER: { { at: string, write: (any) -> string } } = {
|
|
129
|
+
{ at = "form", write = function (of: any): string return of end },
|
|
130
|
+
{ at = "symbols", write = quoted },
|
|
131
|
+
{ at = "axis", write = vector },
|
|
132
|
+
{ at = "min", write = decimal },
|
|
133
|
+
{ at = "max", write = decimal },
|
|
134
|
+
{ at = "step", write = decimal },
|
|
135
|
+
{ at = "field", write = quoted },
|
|
136
|
+
{ at = "class", write = quoted },
|
|
137
|
+
{ at = "names", write = labelled },
|
|
138
|
+
{ at = "colors", write = palette },
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
--[[
|
|
142
|
+
One node's own words: the kind, its parameters, and the marks. Every part comes off the
|
|
143
|
+
declaration and none off what was compiled from it, because two schemas that lower to the same
|
|
144
|
+
bytes are still two schemas.
|
|
145
|
+
]]
|
|
146
|
+
local function spelled (cell: Base.Cell): string
|
|
147
|
+
local parts = {}
|
|
148
|
+
for _, slot in ORDER do
|
|
149
|
+
local held = (cell.params :: any)[slot.at]
|
|
150
|
+
if held ~= nil then table.insert (parts, slot.write (held)) end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
local out = { cell.kind, "(", table.concat (parts, ","), ")" }
|
|
154
|
+
|
|
155
|
+
if cell.marker ~= "none" then
|
|
156
|
+
local rate = if cell.newestHz == nil then "" else `({decimal (cell.newestHz)})`
|
|
157
|
+
table.insert (out, `:{cell.marker}{rate}`)
|
|
158
|
+
end
|
|
159
|
+
for _ = 1, #cell.validates do
|
|
160
|
+
table.insert (out, ":validate")
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
return table.concat (out)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
-- A whole codec as text, which is a node's own words and then its children under theirs.
|
|
167
|
+
local function written (cell: Base.Cell): string
|
|
168
|
+
local children = cell.children
|
|
169
|
+
if children == nil then return spelled (cell) end
|
|
170
|
+
|
|
171
|
+
local out = { spelled (cell), "{" }
|
|
172
|
+
for _, name in Order.names (children) do
|
|
173
|
+
table.insert (out, `{quoted (name)}={written (children[name])}`)
|
|
174
|
+
table.insert (out, ";")
|
|
175
|
+
end
|
|
176
|
+
table.insert (out, "}")
|
|
177
|
+
|
|
178
|
+
return table.concat (out)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
-- Public --------------------------------------------------------------
|
|
182
|
+
|
|
183
|
+
function Serial.describe (of: Described): string return written (of.cell) end
|
|
184
|
+
|
|
185
|
+
-- A definition as its own text, which is what a handle prints and what a namespace carries it as.
|
|
186
|
+
function Serial.frame (of: Frame): string
|
|
187
|
+
if of.kind == "packet" then
|
|
188
|
+
local rate = decimal (if of.hz == nil then 0 else of.hz)
|
|
189
|
+
return `packet[{of.delivery},{rate},{of.timestamped}]({written (of.of.cell)})`
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
if of.kind == "query" then return `query({written (of.of.cell)})({written (of.reply.cell)})` end
|
|
193
|
+
|
|
194
|
+
local key = if of.keyField == nil then "" else quoted (of.keyField)
|
|
195
|
+
return `set[{key}]({written (of.of.cell)})`
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
--[[
|
|
199
|
+
A namespace as the one text two machines compare: the version, the name, and every definition
|
|
200
|
+
under the name it is reached by, in the order both of them sort those names into. The version
|
|
201
|
+
leads, so the hash binds the protocol version for free and a bump fails every handshake with no
|
|
202
|
+
bytes spent saying so.
|
|
203
|
+
]]
|
|
204
|
+
function Serial.namespace (name: string, of: { [string]: Frame }): string
|
|
205
|
+
local out = { `{Protocol.VERSION}:{name}` }
|
|
206
|
+
for _, held in Order.names (of) do
|
|
207
|
+
table.insert (out, ";")
|
|
208
|
+
table.insert (out, `{held}={Serial.frame (of[held])}`)
|
|
209
|
+
end
|
|
210
|
+
return table.concat (out)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
function Serial.interner (): Interner return { at = {}, texts = {} } end
|
|
214
|
+
|
|
215
|
+
--[[
|
|
216
|
+
A text, under the number it is reached by. The same text twice is the same number: a schema
|
|
217
|
+
names one expectation at a hundred fields and a table holding a hundred copies of it would be a
|
|
218
|
+
hundred strings a place keeps for the life of the session.
|
|
219
|
+
]]
|
|
220
|
+
function Serial.intern (of: Interner, text: string): number
|
|
221
|
+
local held = of.at[text]
|
|
222
|
+
if held ~= nil then return held end
|
|
223
|
+
|
|
224
|
+
local id = #of.texts + 1
|
|
225
|
+
of.texts[id] = text
|
|
226
|
+
of.at[text] = id
|
|
227
|
+
return id
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
-- Where a child is, spelled from where its parent is.
|
|
231
|
+
function Serial.under (at: string, name: string): string return `{at}.{name}` end
|
|
232
|
+
|
|
233
|
+
-- Where a node is and what it wanted, as the two numbers a rejection carries.
|
|
234
|
+
function Serial.tagged (
|
|
235
|
+
paths: Interner,
|
|
236
|
+
expected: Interner,
|
|
237
|
+
at: string,
|
|
238
|
+
cell: Base.Cell
|
|
239
|
+
): (number, number)
|
|
240
|
+
return Serial.intern (paths, at), Serial.intern (expected, spelled (cell))
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
--[[
|
|
244
|
+
A byte crosses into the carrier's domain before it is folded, because the exclusive or and the
|
|
245
|
+
multiply both refuse a bare number rather than lifting one. It is taken into a local first
|
|
246
|
+
because `string.byte` is typed as answering a variadic, and the crossing takes one number.
|
|
247
|
+
]]
|
|
248
|
+
function Serial.hash (text: string): Wide.Word
|
|
249
|
+
local h = BASIS
|
|
250
|
+
|
|
251
|
+
for index = 1, #text do
|
|
252
|
+
local byte = string.byte (text, index)
|
|
253
|
+
h = Wide.mul (Wide.bxor (h, Wide.of (byte)), PRIME)
|
|
254
|
+
end
|
|
255
|
+
return h
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
return table.freeze (Serial)
|
package/shape/Words.luau
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!optimize 2
|
|
3
|
+
-- The windows a run of bit fields is cut into, and where each field sits in them.
|
|
4
|
+
|
|
5
|
+
local Protocol = require (script.Parent.Parent.wire.Protocol)
|
|
6
|
+
|
|
7
|
+
local Words = {}
|
|
8
|
+
|
|
9
|
+
-- Constants -----------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
const BYTE = Protocol.BYTE_BITS
|
|
12
|
+
|
|
13
|
+
-- The windows a run is cut into, widest first, in bytes.
|
|
14
|
+
const WIDE = 4
|
|
15
|
+
const PAIR = 2
|
|
16
|
+
const ONE = 1
|
|
17
|
+
|
|
18
|
+
-- Types ---------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
--[[
|
|
21
|
+
A part carries its shift, which is how far up its field it starts, because the emitter places
|
|
22
|
+
each piece of a straddling field independently and deriving the shift would make every piece
|
|
23
|
+
depend on the one before it.
|
|
24
|
+
]]
|
|
25
|
+
export type Part = {
|
|
26
|
+
read field: number,
|
|
27
|
+
read offset: number,
|
|
28
|
+
read width: number,
|
|
29
|
+
read shift: number,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type Word = {
|
|
33
|
+
read bytes: number,
|
|
34
|
+
read at: number,
|
|
35
|
+
read parts: { Part },
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
-- Public --------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
-- The same three widths, named for whoever else lays a run down.
|
|
41
|
+
Words.WIDE = WIDE
|
|
42
|
+
Words.PAIR = PAIR
|
|
43
|
+
Words.ONE = ONE
|
|
44
|
+
|
|
45
|
+
-- The widest window the bits still fill, then the next, and a single byte for the remainder.
|
|
46
|
+
function Words.plan (widths: { number }): { Word }
|
|
47
|
+
local count = #widths
|
|
48
|
+
|
|
49
|
+
local left = 0
|
|
50
|
+
for _, width in widths do
|
|
51
|
+
left += width
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
local plan: { Word } = {}
|
|
55
|
+
local field, placed, at = 1, 0, 0
|
|
56
|
+
|
|
57
|
+
while left > 0 do
|
|
58
|
+
local bytes = if left >= WIDE * BYTE then WIDE elseif left >= PAIR * BYTE then PAIR else ONE
|
|
59
|
+
local room = bytes * BYTE
|
|
60
|
+
|
|
61
|
+
local parts: { Part } = {}
|
|
62
|
+
local offset = 0
|
|
63
|
+
|
|
64
|
+
while offset < room and field <= count do
|
|
65
|
+
local rest = widths[field] - placed
|
|
66
|
+
if rest == 0 then
|
|
67
|
+
field, placed = field + 1, 0
|
|
68
|
+
continue
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
local width = math.min (rest, room - offset)
|
|
72
|
+
table.insert (parts, { field = field, offset = offset, width = width, shift = placed })
|
|
73
|
+
|
|
74
|
+
offset += width
|
|
75
|
+
placed += width
|
|
76
|
+
if placed == widths[field] then
|
|
77
|
+
field, placed = field + 1, 0
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
table.insert (plan, { bytes = bytes, at = at, parts = parts })
|
|
82
|
+
at += bytes
|
|
83
|
+
left -= room
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
return plan
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
return table.freeze (Words)
|