@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.
- 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 -319
- package/src/api/Query.luau +0 -338
- package/src/api/Scope.luau +0 -90
- package/src/api/Signal.luau +0 -188
- package/src/codec/Base.luau +0 -136
- package/src/codec/composite/Array.luau +0 -456
- package/src/codec/composite/Map.luau +0 -469
- package/src/codec/composite/Optional.luau +0 -54
- package/src/codec/composite/Shared.luau +0 -291
- 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 -147
- 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 -390
- package/src/internal/Middleware.luau +0 -100
- package/src/internal/Pool.luau +0 -65
- 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 -211
- 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,453 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!native
|
|
3
|
+
--!optimize 2
|
|
4
|
+
-- The nodes made of other nodes, as the pair of closures that puts each one's children in order.
|
|
5
|
+
|
|
6
|
+
local Bits = require (script.Parent.Parent.Parent.kernel.Bits)
|
|
7
|
+
local Bytes = require (script.Parent.Parent.Parent.wire.Bytes)
|
|
8
|
+
local Catalog = require (script.Parent.Parent.Parent.kernel.Catalog)
|
|
9
|
+
local Ir = require (script.Parent.Parent.Ir)
|
|
10
|
+
local Log = require (script.Parent.Parent.Parent.kernel.Log)
|
|
11
|
+
local Serial = require (script.Parent.Parent.Serial)
|
|
12
|
+
local Types = require (script.Parent.Parent.Parent.Types)
|
|
13
|
+
local Word = require (script.Parent.Word)
|
|
14
|
+
|
|
15
|
+
local Block = {}
|
|
16
|
+
|
|
17
|
+
-- Constants -----------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
-- The whole-byte widths a tag or a count is written at, and where a three-byte one splits.
|
|
20
|
+
const PAIR = 2
|
|
21
|
+
const TRIO = PAIR + 1
|
|
22
|
+
const HALF = 65536
|
|
23
|
+
-- Private -------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
--[[
|
|
26
|
+
A tag or a count, as the whole bytes it occupies. Narrower than the leaf writer's, because
|
|
27
|
+
nothing composed here is wider than a count, and a bound past four bytes is more elements than a
|
|
28
|
+
caller could hold the values for.
|
|
29
|
+
]]
|
|
30
|
+
|
|
31
|
+
local function laid (b: buffer, at: number, bytes: number, value: number)
|
|
32
|
+
if bytes == 0 then return end
|
|
33
|
+
if bytes == 1 then return buffer.writeu8 (b, at, value) end
|
|
34
|
+
if bytes == PAIR then return buffer.writeu16 (b, at, value) end
|
|
35
|
+
if bytes == TRIO then
|
|
36
|
+
buffer.writeu16 (b, at, value % HALF)
|
|
37
|
+
return buffer.writeu8 (b, at + PAIR, value // HALF)
|
|
38
|
+
end
|
|
39
|
+
buffer.writeu32 (b, at, value)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
local function taken (b: buffer, at: number, bytes: number): number
|
|
43
|
+
if bytes == 0 then return 0 end
|
|
44
|
+
if bytes == 1 then return buffer.readu8 (b, at) end
|
|
45
|
+
if bytes == PAIR then return buffer.readu16 (b, at) end
|
|
46
|
+
if bytes == TRIO then return buffer.readu16 (b, at) + buffer.readu8 (b, at + PAIR) * HALF end
|
|
47
|
+
return buffer.readu32 (b, at)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
-- Public --------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
--[[
|
|
53
|
+
A region and then everything after it, which is what a record is. The two arrays a call meets
|
|
54
|
+
its own state in are made once here and neither survives a call, and a group cannot appear
|
|
55
|
+
inside itself, so two calls through the pair never overlap. A dissolved record is resolved once
|
|
56
|
+
before either region and filled from both, which keeps two tables of one name from being built.
|
|
57
|
+
]]
|
|
58
|
+
function Block.group (
|
|
59
|
+
of: Ir.Group,
|
|
60
|
+
pack: Word.Pack?,
|
|
61
|
+
unpack: Word.Unpack?,
|
|
62
|
+
writes: { Ir.Write },
|
|
63
|
+
reads: { Ir.Read },
|
|
64
|
+
paths: Serial.Interner,
|
|
65
|
+
said: Serial.Interner
|
|
66
|
+
): (Ir.Write, Ir.Read)
|
|
67
|
+
local slots: { number } = {}
|
|
68
|
+
local held: { any } = {}
|
|
69
|
+
local region = if of.word == nil then 0 else of.word.maxBytes
|
|
70
|
+
|
|
71
|
+
local deep = #of.nests
|
|
72
|
+
local names = table.create (deep) :: { string }
|
|
73
|
+
local unders = table.create (deep, 0)
|
|
74
|
+
local nested = table.create (deep) :: { Ir.Tag }
|
|
75
|
+
local slack = table.create (deep) :: { { [string]: boolean } }
|
|
76
|
+
|
|
77
|
+
for index, nest in of.nests do
|
|
78
|
+
names[index] = nest.key
|
|
79
|
+
unders[index] = nest.under or 0
|
|
80
|
+
nested[index] = nest.tag
|
|
81
|
+
slack[index] = nest.allow
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
local reach = #of.parts
|
|
85
|
+
local keys = table.create (reach) :: { string? }
|
|
86
|
+
local inside = table.create (reach, 0)
|
|
87
|
+
local bits = table.create (reach, 0)
|
|
88
|
+
|
|
89
|
+
local keyed = true
|
|
90
|
+
|
|
91
|
+
for index, part in of.parts do
|
|
92
|
+
local shape = part.of
|
|
93
|
+
keys[index] = part.key
|
|
94
|
+
inside[index] = part.nest or 0
|
|
95
|
+
bits[index] = if shape.op == "opt" then shape.bit else 0
|
|
96
|
+
if part.key == nil then keyed = false end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
if of.word ~= nil then
|
|
100
|
+
for _, join in of.word.joins do
|
|
101
|
+
if join.key == nil then keyed = false end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
-- A record carries the names it declares and no others, at every depth it dissolved through.
|
|
106
|
+
local function only (of: { [string]: boolean }, tag: Ir.Tag, record: any)
|
|
107
|
+
if type (record) ~= "table" then Word.refusedAt (tag, paths, said, record) end
|
|
108
|
+
|
|
109
|
+
for key in record do
|
|
110
|
+
if of[key] ~= nil then continue end
|
|
111
|
+
Word.refusedAt (tag, paths, said, key)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
local allow = of.allow
|
|
116
|
+
|
|
117
|
+
local function write (b: buffer, pos: number, value: any): number
|
|
118
|
+
if allow ~= nil then only (allow, of.tag, value) end
|
|
119
|
+
|
|
120
|
+
for index = 1, deep do
|
|
121
|
+
local under = unders[index]
|
|
122
|
+
local one = (if under == 0 then value else held[under])[names[index] ]
|
|
123
|
+
only (slack[index], nested[index], one)
|
|
124
|
+
|
|
125
|
+
held[index] = one
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
if pack ~= nil then pack (b, pos, value, slots, held) end
|
|
129
|
+
|
|
130
|
+
local at = pos + region
|
|
131
|
+
for index = 1, reach do
|
|
132
|
+
local key = keys[index]
|
|
133
|
+
local within = inside[index]
|
|
134
|
+
local from = if within == 0 then value else held[within]
|
|
135
|
+
local one = if key == nil then from else from[key]
|
|
136
|
+
|
|
137
|
+
local bit = bits[index]
|
|
138
|
+
if bit ~= 0 and slots[bit] == 0 then continue end
|
|
139
|
+
|
|
140
|
+
at = writes[index] (b, at, one)
|
|
141
|
+
end
|
|
142
|
+
return at
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
local function read (b: buffer, pos: number, ctx: Types.ValidateContext): (number, any)
|
|
146
|
+
local into: any = if keyed then {} else nil
|
|
147
|
+
local bare: any = nil
|
|
148
|
+
|
|
149
|
+
for index = 1, deep do
|
|
150
|
+
local under = unders[index]
|
|
151
|
+
local up = if under == 0 then into else held[under]
|
|
152
|
+
|
|
153
|
+
local one = {}
|
|
154
|
+
up[names[index] ] = one
|
|
155
|
+
held[index] = one
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
if unpack ~= nil then bare = unpack (b, pos, into, slots, held) end
|
|
159
|
+
|
|
160
|
+
local at = pos + region
|
|
161
|
+
for index = 1, reach do
|
|
162
|
+
local bit = bits[index]
|
|
163
|
+
if bit ~= 0 and slots[bit] == 0 then continue end
|
|
164
|
+
|
|
165
|
+
local one: any
|
|
166
|
+
at, one = reads[index] (b, at, ctx)
|
|
167
|
+
|
|
168
|
+
local key = keys[index]
|
|
169
|
+
if key == nil then
|
|
170
|
+
bare = one
|
|
171
|
+
continue
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
local within = inside[index]
|
|
175
|
+
local up = if within == 0 then into else held[within]
|
|
176
|
+
up[key] = one
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
return at, (if keyed then into else bare)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
return write, read
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
-- A value laid down as its parts and built back out of them.
|
|
186
|
+
function Block.apart (
|
|
187
|
+
of: Ir.Apart,
|
|
188
|
+
writes: { Ir.Write },
|
|
189
|
+
reads: { Ir.Read },
|
|
190
|
+
paths: Serial.Interner,
|
|
191
|
+
expected: Serial.Interner
|
|
192
|
+
): (Ir.Write, Ir.Read)
|
|
193
|
+
local tag = of.tag
|
|
194
|
+
local engine = of.engine
|
|
195
|
+
local keys = of.keys
|
|
196
|
+
local push = of.push
|
|
197
|
+
local reach = #of.parts
|
|
198
|
+
|
|
199
|
+
local held = table.create (reach) :: { any }
|
|
200
|
+
|
|
201
|
+
local function write (b: buffer, pos: number, value: any): number
|
|
202
|
+
if typeof (value) ~= engine then Word.refusedAt (tag, paths, expected, value) end
|
|
203
|
+
|
|
204
|
+
local at = pos
|
|
205
|
+
for index = 1, reach do
|
|
206
|
+
at = writes[index] (b, at, value[keys[index] ])
|
|
207
|
+
end
|
|
208
|
+
return at
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
local function read (b: buffer, pos: number, ctx: Types.ValidateContext): (number, any)
|
|
212
|
+
local at = pos
|
|
213
|
+
for index = 1, reach do
|
|
214
|
+
at, held[index] = reads[index] (b, at, ctx)
|
|
215
|
+
end
|
|
216
|
+
return at, push (held)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
return write, read
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
--[[
|
|
223
|
+
A tag and the arm it chooses, and nothing to choose it by but the field the variant names itself
|
|
224
|
+
in.
|
|
225
|
+
]]
|
|
226
|
+
function Block.branch (
|
|
227
|
+
of: Ir.Branch,
|
|
228
|
+
writes: { Ir.Write },
|
|
229
|
+
reads: { Ir.Read },
|
|
230
|
+
paths: Serial.Interner,
|
|
231
|
+
said: Serial.Interner
|
|
232
|
+
): (Ir.Write, Ir.Read)
|
|
233
|
+
local tag = of.tag
|
|
234
|
+
local field = of.field
|
|
235
|
+
local bytes = Bytes.whole (of.tagWidth)
|
|
236
|
+
local reach = #of.arms
|
|
237
|
+
|
|
238
|
+
local index: { [string]: number } = {}
|
|
239
|
+
local names = table.create (reach) :: { string }
|
|
240
|
+
|
|
241
|
+
for place, name in of.names do
|
|
242
|
+
index[name] = place
|
|
243
|
+
names[place] = name
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
local function write (b: buffer, pos: number, value: any): number
|
|
247
|
+
local place = index[value[field] ]
|
|
248
|
+
if place == nil then Word.refusedAt (tag, paths, said, value[field]) end
|
|
249
|
+
|
|
250
|
+
laid (b, pos, bytes, (place :: number) - 1)
|
|
251
|
+
return writes[place :: number] (b, pos + bytes, value)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
local function read (b: buffer, pos: number, ctx: Types.ValidateContext): (number, any)
|
|
255
|
+
local place = taken (b, pos, bytes) + 1
|
|
256
|
+
if place > reach then
|
|
257
|
+
Log.reject (Catalog.TAG, {
|
|
258
|
+
pathId = tag.pathId,
|
|
259
|
+
expectId = tag.expectId,
|
|
260
|
+
got = place - 1,
|
|
261
|
+
})
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
local at, one = reads[place] (b, pos + bytes, ctx)
|
|
265
|
+
one[field] = names[place]
|
|
266
|
+
return at, one
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
return write, read
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
--[[
|
|
273
|
+
A count and then that many of one thing, each starting on a byte because the thing before it
|
|
274
|
+
ended on one.
|
|
275
|
+
]]
|
|
276
|
+
function Block.list (
|
|
277
|
+
of: Ir.List,
|
|
278
|
+
writeElem: Ir.Write,
|
|
279
|
+
readElem: Ir.Read,
|
|
280
|
+
paths: Serial.Interner,
|
|
281
|
+
said: Serial.Interner
|
|
282
|
+
): (Ir.Write, Ir.Read)
|
|
283
|
+
local tag = of.tag
|
|
284
|
+
local low, high = of.count.min, of.count.max
|
|
285
|
+
local span = high - low
|
|
286
|
+
local held = Bytes.whole (Bits.width (span))
|
|
287
|
+
|
|
288
|
+
local function write (b: buffer, pos: number, value: any): number
|
|
289
|
+
local count = #value
|
|
290
|
+
if count < low or count > high then Word.refusedAt (tag, paths, said, count) end
|
|
291
|
+
|
|
292
|
+
laid (b, pos, held, count - low)
|
|
293
|
+
|
|
294
|
+
local at = pos + held
|
|
295
|
+
for index = 1, count do
|
|
296
|
+
at = writeElem (b, at, value[index])
|
|
297
|
+
end
|
|
298
|
+
return at
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
local function read (b: buffer, pos: number, ctx: Types.ValidateContext): (number, any)
|
|
302
|
+
local counted = taken (b, pos, held)
|
|
303
|
+
if counted > span then
|
|
304
|
+
Log.reject (
|
|
305
|
+
Catalog.COUNT,
|
|
306
|
+
{ pathId = tag.pathId, expectId = tag.expectId, got = counted }
|
|
307
|
+
)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
local count = counted + low
|
|
311
|
+
local out = table.create (count) :: { any }
|
|
312
|
+
local at = pos + held
|
|
313
|
+
|
|
314
|
+
for index = 1, count do
|
|
315
|
+
at, out[index] = readElem (b, at, ctx)
|
|
316
|
+
end
|
|
317
|
+
return at, out
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
return write, read
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
-- A count and then that many pairs, in the order the bytes of their keys read in.
|
|
324
|
+
function Block.pairs (
|
|
325
|
+
of: Ir.Pairs,
|
|
326
|
+
writeKey: Ir.Write,
|
|
327
|
+
readKey: Ir.Read,
|
|
328
|
+
writeValue: Ir.Write,
|
|
329
|
+
readValue: Ir.Read,
|
|
330
|
+
paths: Serial.Interner,
|
|
331
|
+
said: Serial.Interner
|
|
332
|
+
): (Ir.Write, Ir.Read)
|
|
333
|
+
local tag = of.tag
|
|
334
|
+
local low, high = of.count.min, of.count.max
|
|
335
|
+
local span = high - low
|
|
336
|
+
local held = Bytes.whole (Bits.width (span))
|
|
337
|
+
|
|
338
|
+
local where = paths.texts[tag.pathId]
|
|
339
|
+
|
|
340
|
+
local room = buffer.create (high * of.key.maxBytes)
|
|
341
|
+
local keys: { any } = {}
|
|
342
|
+
local starts: { number } = {}
|
|
343
|
+
local widths: { number } = {}
|
|
344
|
+
local order: { number } = {}
|
|
345
|
+
|
|
346
|
+
local function before (a: number, b: number): boolean
|
|
347
|
+
return Bytes.rangeLess (room, starts[a], widths[a], starts[b], widths[b])
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
local function write (b: buffer, pos: number, value: any): number
|
|
351
|
+
table.clear (order)
|
|
352
|
+
|
|
353
|
+
local count = 0
|
|
354
|
+
local at = 0
|
|
355
|
+
|
|
356
|
+
for key in value do
|
|
357
|
+
count += 1
|
|
358
|
+
if count > high then Word.refusedAt (tag, paths, said, count) end
|
|
359
|
+
|
|
360
|
+
keys[count] = key
|
|
361
|
+
starts[count] = at
|
|
362
|
+
at = writeKey (room, at, key)
|
|
363
|
+
|
|
364
|
+
widths[count] = at - starts[count]
|
|
365
|
+
order[count] = count
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
if count < low then Word.refusedAt (tag, paths, said, count) end
|
|
369
|
+
table.sort (order, before)
|
|
370
|
+
|
|
371
|
+
laid (b, pos, held, count - low)
|
|
372
|
+
|
|
373
|
+
local out = pos + held
|
|
374
|
+
for index = 1, count do
|
|
375
|
+
local place = order[index]
|
|
376
|
+
if index > 1 and not before (order[index - 1], place) then
|
|
377
|
+
local last = keys[order[index - 1] ]
|
|
378
|
+
Log.refuse (Log.line (Catalog.MAP_ORDER, {
|
|
379
|
+
path = where,
|
|
380
|
+
expected = tostring (last),
|
|
381
|
+
got = tostring (keys[place]),
|
|
382
|
+
}))
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
buffer.copy (b, out, room, starts[place], widths[place])
|
|
386
|
+
out = writeValue (b, out + widths[place], value[keys[place] ])
|
|
387
|
+
end
|
|
388
|
+
return out
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
local function read (b: buffer, pos: number, ctx: Types.ValidateContext): (number, any)
|
|
392
|
+
local counted = taken (b, pos, held)
|
|
393
|
+
if counted > span then
|
|
394
|
+
Log.reject (
|
|
395
|
+
Catalog.COUNT,
|
|
396
|
+
{ pathId = tag.pathId, expectId = tag.expectId, got = counted }
|
|
397
|
+
)
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
local count = counted + low
|
|
401
|
+
local out: any = {}
|
|
402
|
+
local at = pos + held
|
|
403
|
+
|
|
404
|
+
local was, wide, last = 0, 0, nil :: any
|
|
405
|
+
for index = 1, count do
|
|
406
|
+
local from = at
|
|
407
|
+
|
|
408
|
+
local key: any
|
|
409
|
+
at, key = readKey (b, at, ctx)
|
|
410
|
+
|
|
411
|
+
if index > 1 and not Bytes.rangeLess (b, was, wide, from, at - from) then
|
|
412
|
+
Log.reject (Catalog.MAP_ORDER, {
|
|
413
|
+
pathId = tag.pathId,
|
|
414
|
+
expected = tostring (last),
|
|
415
|
+
got = tostring (key),
|
|
416
|
+
})
|
|
417
|
+
end
|
|
418
|
+
-- A key this map already holds, which is a pair that would take the place of another.
|
|
419
|
+
if out[key] ~= nil then
|
|
420
|
+
Log.reject (Catalog.MAP_ORDER, {
|
|
421
|
+
pathId = tag.pathId,
|
|
422
|
+
expected = tostring (last),
|
|
423
|
+
got = tostring (key),
|
|
424
|
+
})
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
was, wide, last = from, at - from, key
|
|
428
|
+
|
|
429
|
+
at, out[key] = readValue (b, at, ctx)
|
|
430
|
+
end
|
|
431
|
+
return at, out
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
return write, read
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
-- A value on its way to and from the one the wire carries, which is the same bytes either way.
|
|
438
|
+
function Block.xform (of: Ir.Xform, writeInner: Ir.Write, readInner: Ir.Read): (Ir.Write, Ir.Read)
|
|
439
|
+
local lift, lower = of.lift, of.lower
|
|
440
|
+
|
|
441
|
+
local function write (b: buffer, pos: number, value: any): number
|
|
442
|
+
return writeInner (b, pos, lower (value))
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
local function read (b: buffer, pos: number, ctx: Types.ValidateContext): (number, any)
|
|
446
|
+
local at, one = readInner (b, pos, ctx)
|
|
447
|
+
return at, lift (one)
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
return write, read
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
return table.freeze (Block)
|