@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,379 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!optimize 2
|
|
3
|
+
-- One frame taken apart: which definition each block is, and where that definition sends it.
|
|
4
|
+
|
|
5
|
+
local Boundary = require (script.Parent.Boundary)
|
|
6
|
+
local Catalog = require (script.Parent.Parent.kernel.Catalog)
|
|
7
|
+
local Clock = require (script.Parent.Parent.wire.Clock)
|
|
8
|
+
local Compile = require (script.Parent.Parent.shape.Compile)
|
|
9
|
+
local Dispatch = require (script.Parent.Dispatch)
|
|
10
|
+
local Frames = require (script.Parent.Parent.shape.Frames)
|
|
11
|
+
local Ir = require (script.Parent.Parent.shape.Ir)
|
|
12
|
+
local Pending = require (script.Parent.Pending)
|
|
13
|
+
local Protocol = require (script.Parent.Parent.wire.Protocol)
|
|
14
|
+
local Sequence = require (script.Parent.Parent.wire.Sequence)
|
|
15
|
+
local Serial = require (script.Parent.Parent.shape.Serial)
|
|
16
|
+
local Tally = require (script.Parent.Parent.kernel.Tally)
|
|
17
|
+
local Transport = require (script.Parent.Parent.channel.Transport)
|
|
18
|
+
local Types = require (script.Parent.Parent.Types)
|
|
19
|
+
|
|
20
|
+
local Router = {}
|
|
21
|
+
|
|
22
|
+
-- Constants -----------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
-- Where a header's fields land in the one array every form is read into.
|
|
25
|
+
const WHOSE = 1
|
|
26
|
+
const SECOND = 2
|
|
27
|
+
|
|
28
|
+
-- What a response says about itself, which is a bit and is the only thing a failed one carries.
|
|
29
|
+
const ANSWERED = 0
|
|
30
|
+
|
|
31
|
+
-- What a run's continuation byte costs, which is the byte alignment gives one bit.
|
|
32
|
+
const AFTER = 1
|
|
33
|
+
|
|
34
|
+
-- The delivery a definition declares that puts it on the lane which may reorder and may lose.
|
|
35
|
+
const NEWEST: Serial.Delivery = "newest"
|
|
36
|
+
|
|
37
|
+
-- What a stamp counts in, which is what turns one back into seconds.
|
|
38
|
+
const RATE = Protocol.STAMP_RATE
|
|
39
|
+
|
|
40
|
+
--[[
|
|
41
|
+
Why a request that reached nobody resolves the way it does.
|
|
42
|
+
|
|
43
|
+
A responder that threw is the one case the wire has a bit for, and what the asking machine knows
|
|
44
|
+
is that it will not be answered. It is not a timeout, since the answer arrived.
|
|
45
|
+
]]
|
|
46
|
+
const THREW: Types.OutcomeCode = "unanswered"
|
|
47
|
+
|
|
48
|
+
-- Types ---------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
-- One payload's reader, as everything this module refuses to know about it.
|
|
51
|
+
export type Take = (b: buffer, pos: number, ctx: Types.ValidateContext) -> (number, any)
|
|
52
|
+
|
|
53
|
+
-- The one definition this file names three times, and the two blocks it is.
|
|
54
|
+
type Query = Compile.Query
|
|
55
|
+
|
|
56
|
+
-- A responder's answer, handed over the moment the responder returned.
|
|
57
|
+
export type Answers = (def: Query, asked: number, player: Player?, ok: boolean, value: any) -> ()
|
|
58
|
+
|
|
59
|
+
-- Everything a frame is walked with, which is one namespace's worth and lasts as long as it does.
|
|
60
|
+
export type Wiring = {
|
|
61
|
+
read space: Compile.Compiled,
|
|
62
|
+
read tally: Tally.Tally,
|
|
63
|
+
read naming: Frames.Head,
|
|
64
|
+
read into: { number },
|
|
65
|
+
read head: { number },
|
|
66
|
+
read boundary: Boundary.Boundary,
|
|
67
|
+
read heard: Dispatch.Wiring,
|
|
68
|
+
read pending: Pending.Pending,
|
|
69
|
+
read sections: { [number]: Take },
|
|
70
|
+
read streams: { [number]: Take },
|
|
71
|
+
read latest: { [Player]: { [number]: number } },
|
|
72
|
+
read heardSeq: { [number]: number },
|
|
73
|
+
--[[
|
|
74
|
+
Where a responder's answer goes, written after this is made because whatever queues one
|
|
75
|
+
holds this and this holds it. The one field here that is not settled at construction, and it
|
|
76
|
+
is settled before a frame can arrive: a namespace opens its lanes at start.
|
|
77
|
+
]]
|
|
78
|
+
answered: Answers,
|
|
79
|
+
|
|
80
|
+
-- The instant this namespace counts from, which every stamp on the wire is measured against.
|
|
81
|
+
epoch: number,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
-- Private -------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
-- The instances this block carries, moved where its reader looks them up.
|
|
87
|
+
local function paired (side: Ir.Sidecar, refs: Transport.Sidecar?, taken: number): number
|
|
88
|
+
if not side.bears then return taken end
|
|
89
|
+
|
|
90
|
+
local at = taken + 1
|
|
91
|
+
local held = if refs == nil then nil else refs[at]
|
|
92
|
+
|
|
93
|
+
table.clear (side.refs)
|
|
94
|
+
if held ~= nil then table.move (held, 1, #held, 1, side.refs) end
|
|
95
|
+
|
|
96
|
+
return at
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
-- Whether the frame still holds the header this block says it has.
|
|
100
|
+
local function holds (of: Wiring, head: Frames.Head, at: number, len: number, said: string): boolean
|
|
101
|
+
if len - at >= head.bytes then return true end
|
|
102
|
+
|
|
103
|
+
Boundary.lost (
|
|
104
|
+
of.boundary,
|
|
105
|
+
Catalog.BOUNDS,
|
|
106
|
+
{ said = `{said} wants {head.bytes} and has {len - at}` }
|
|
107
|
+
)
|
|
108
|
+
return false
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
-- Where one sender's newest packets have reached, made the first time one arrives from them.
|
|
112
|
+
local function latest (of: Wiring, from: Player): { [number]: number }
|
|
113
|
+
local held = of.latest[from]
|
|
114
|
+
if held ~= nil then return held end
|
|
115
|
+
|
|
116
|
+
held = {}
|
|
117
|
+
of.latest[from] = held
|
|
118
|
+
return held
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
-- A stamp off the wire as the instant it was sent, on the clock both machines share.
|
|
122
|
+
local function stamped (of: Wiring, stamp: number): number
|
|
123
|
+
local elapsed = Clock.elapsed (of.boundary.ctx.now, of.epoch)
|
|
124
|
+
return of.epoch + Clock.unwrap (stamp, elapsed) / RATE
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
-- A packet block: one payload, or a run of them under one header.
|
|
128
|
+
local function packets (
|
|
129
|
+
of: Wiring,
|
|
130
|
+
def: Compile.Packet,
|
|
131
|
+
from: Player?,
|
|
132
|
+
b: buffer,
|
|
133
|
+
at: number,
|
|
134
|
+
len: number
|
|
135
|
+
): number?
|
|
136
|
+
local head = def.head
|
|
137
|
+
if not holds (of, head, at, len, def.name) then return nil end
|
|
138
|
+
|
|
139
|
+
head.read (b, at, of.head)
|
|
140
|
+
|
|
141
|
+
--[[
|
|
142
|
+
Read once for the block rather than once a payload, since a run shares one header. The stamp
|
|
143
|
+
is the send instant a caller compares across clients, and it reaches a listener beside the
|
|
144
|
+
value because that is what the surface declares a listener takes.
|
|
145
|
+
]]
|
|
146
|
+
local sent: number? = if def.timestamped then stamped (of, of.head[SECOND]) else nil
|
|
147
|
+
|
|
148
|
+
--[[
|
|
149
|
+
A block on the lane that reorders says where it is in the ring, and one that lost the race
|
|
150
|
+
says nothing at all rather than something older than what this machine already has. The
|
|
151
|
+
whole block goes, since a newest definition coalesces to one value before it is sequenced
|
|
152
|
+
and a stale one is superseded whole.
|
|
153
|
+
]]
|
|
154
|
+
local stale = false
|
|
155
|
+
if def.delivery == NEWEST then
|
|
156
|
+
local ring = of.head[head.fields]
|
|
157
|
+
local seen = if from == nil then of.heardSeq else latest (of, from)
|
|
158
|
+
local was = seen[def.id]
|
|
159
|
+
|
|
160
|
+
stale = was ~= nil and not Sequence.isNewer (ring, was)
|
|
161
|
+
if not stale then seen[def.id] = ring end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
local pos = at + head.bytes
|
|
165
|
+
local built = def.built
|
|
166
|
+
|
|
167
|
+
while true do
|
|
168
|
+
local ends, value = Boundary.ran (of.boundary, def, built, built.read, b, pos)
|
|
169
|
+
if ends == nil then return nil end
|
|
170
|
+
|
|
171
|
+
if not stale and of.boundary.took then
|
|
172
|
+
if from == nil then
|
|
173
|
+
Dispatch.packet (of.heard, def.id, def.name, value, sent)
|
|
174
|
+
else
|
|
175
|
+
Dispatch.packet (of.heard, def.id, def.name, value, from, sent)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
--[[
|
|
180
|
+
The bit saying another payload follows is written after one, and only where the form has
|
|
181
|
+
a place for it. A newest block carries exactly one payload, so a byte read here would be
|
|
182
|
+
the first byte of whatever block came next.
|
|
183
|
+
]]
|
|
184
|
+
if head.trailer == 0 then return ends end
|
|
185
|
+
if ends >= len then return ends end
|
|
186
|
+
|
|
187
|
+
local more = Frames.continues (b, ends)
|
|
188
|
+
pos = ends + AFTER
|
|
189
|
+
|
|
190
|
+
if not more then return pos end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
-- A request block: one payload, and the answer it is owed put by for the next flush.
|
|
195
|
+
local function asked (
|
|
196
|
+
of: Wiring,
|
|
197
|
+
def: Query,
|
|
198
|
+
from: Player?,
|
|
199
|
+
b: buffer,
|
|
200
|
+
at: number,
|
|
201
|
+
len: number
|
|
202
|
+
): number?
|
|
203
|
+
local head = def.asks
|
|
204
|
+
if not holds (of, head, at, len, def.name) then return nil end
|
|
205
|
+
|
|
206
|
+
head.read (b, at, of.head)
|
|
207
|
+
|
|
208
|
+
local id = of.head[SECOND]
|
|
209
|
+
local ends, value =
|
|
210
|
+
Boundary.ran (of.boundary, def, def.request, def.request.read, b, at + head.bytes)
|
|
211
|
+
if ends == nil then return nil end
|
|
212
|
+
if not of.boundary.took then return ends end
|
|
213
|
+
|
|
214
|
+
--[[
|
|
215
|
+
The value first and who asked after it, and nothing after that on a client, which is what
|
|
216
|
+
the surface declares a responder takes. A responder on a server is told who asked and one on
|
|
217
|
+
a client has only ever been asked by the server, so there is nobody to name.
|
|
218
|
+
]]
|
|
219
|
+
local ok, answer
|
|
220
|
+
if from == nil then
|
|
221
|
+
ok, answer = Dispatch.request (of.heard, def.id, value)
|
|
222
|
+
else
|
|
223
|
+
ok, answer = Dispatch.request (of.heard, def.id, value, from)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
--[[
|
|
227
|
+
Composed at once, so a responder answering something its own codec refuses raises on the
|
|
228
|
+
line that returned it. A flush is as far from the responder as this machine can put that
|
|
229
|
+
raise, and on one that never flushes again it lands nowhere at all.
|
|
230
|
+
]]
|
|
231
|
+
of.answered (def, id, from, ok, answer)
|
|
232
|
+
|
|
233
|
+
return ends
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
-- A response block: the id it answers, whether it was answered at all, and the payload if it was.
|
|
237
|
+
local function answered (
|
|
238
|
+
of: Wiring,
|
|
239
|
+
def: Query,
|
|
240
|
+
b: buffer,
|
|
241
|
+
at: number,
|
|
242
|
+
len: number,
|
|
243
|
+
now: number
|
|
244
|
+
): number?
|
|
245
|
+
local head = def.answers
|
|
246
|
+
if not holds (of, head, at, len, def.name) then return nil end
|
|
247
|
+
|
|
248
|
+
head.read (b, at, of.head)
|
|
249
|
+
|
|
250
|
+
local id = of.head[SECOND]
|
|
251
|
+
local pos = at + head.bytes
|
|
252
|
+
|
|
253
|
+
if of.head[head.fields] ~= ANSWERED then
|
|
254
|
+
of.pending:fail (id, THREW, now)
|
|
255
|
+
return pos
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
local ends, value = Boundary.ran (of.boundary, def, def.response, def.response.read, b, pos)
|
|
259
|
+
if ends == nil then return nil end
|
|
260
|
+
if of.boundary.took then of.pending:answer (id, value) end
|
|
261
|
+
|
|
262
|
+
return ends
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
-- A state block, on whichever lane it arrived.
|
|
266
|
+
local function stated (of: Wiring, def: Compile.Set, lossy: boolean, b: buffer, at: number): number?
|
|
267
|
+
local take = if lossy then of.streams[def.id] else of.sections[def.id]
|
|
268
|
+
if take == nil then
|
|
269
|
+
Boundary.lost (of.boundary, Catalog.DEFID, {
|
|
270
|
+
expected = "a definition this endpoint holds a set for",
|
|
271
|
+
got = def.name,
|
|
272
|
+
})
|
|
273
|
+
return nil
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
local ends = Boundary.ran (of.boundary, def, def.site, take, b, at)
|
|
277
|
+
return ends
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
-- Public --------------------------------------------------------------
|
|
281
|
+
|
|
282
|
+
-- Everything one namespace's frames are walked with.
|
|
283
|
+
function Router.wiring (
|
|
284
|
+
space: Compile.Compiled,
|
|
285
|
+
boundary: Boundary.Boundary,
|
|
286
|
+
heard: Dispatch.Wiring,
|
|
287
|
+
pending: Pending.Pending,
|
|
288
|
+
tally: Tally.Tally
|
|
289
|
+
): Wiring
|
|
290
|
+
return {
|
|
291
|
+
space = space,
|
|
292
|
+
tally = tally,
|
|
293
|
+
answered = function () end,
|
|
294
|
+
naming = Frames.naming (space.count),
|
|
295
|
+
into = { 0 },
|
|
296
|
+
head = { 0, 0, 0 },
|
|
297
|
+
boundary = boundary,
|
|
298
|
+
heard = heard,
|
|
299
|
+
pending = pending,
|
|
300
|
+
sections = {},
|
|
301
|
+
streams = {},
|
|
302
|
+
latest = {},
|
|
303
|
+
heardSeq = {},
|
|
304
|
+
epoch = 0,
|
|
305
|
+
}
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
-- One frame, taken apart into the blocks it is and each of them handed where it goes.
|
|
309
|
+
function Router.frame (
|
|
310
|
+
of: Wiring,
|
|
311
|
+
from: Player?,
|
|
312
|
+
lossy: boolean,
|
|
313
|
+
b: buffer,
|
|
314
|
+
refs: Transport.Sidecar?,
|
|
315
|
+
now: number
|
|
316
|
+
)
|
|
317
|
+
local boundary = of.boundary
|
|
318
|
+
Boundary.opened (boundary, from, now)
|
|
319
|
+
|
|
320
|
+
local len = buffer.len (b)
|
|
321
|
+
local naming = of.naming
|
|
322
|
+
|
|
323
|
+
local at = 0
|
|
324
|
+
local taken = 0
|
|
325
|
+
|
|
326
|
+
while boundary.live and at < len do
|
|
327
|
+
if len - at < naming.bytes then
|
|
328
|
+
Boundary.lost (boundary, Catalog.DEFID, {
|
|
329
|
+
expected = `a block of at least {naming.bytes} bytes`,
|
|
330
|
+
got = `{len - at} left`,
|
|
331
|
+
})
|
|
332
|
+
return
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
naming.read (b, at, of.into)
|
|
336
|
+
|
|
337
|
+
local id = of.into[WHOSE]
|
|
338
|
+
local def = of.space.byId[id]
|
|
339
|
+
|
|
340
|
+
if def == nil then
|
|
341
|
+
Boundary.lost (boundary, Catalog.DEFID, {
|
|
342
|
+
expected = `a definition of {of.space.space}`,
|
|
343
|
+
got = tostring (id),
|
|
344
|
+
})
|
|
345
|
+
return
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
Boundary.stamped (boundary, from, id, now)
|
|
349
|
+
|
|
350
|
+
local ends: number?
|
|
351
|
+
if def.kind == "packet" then
|
|
352
|
+
taken = paired (def.built.sidecar, refs, taken)
|
|
353
|
+
ends = packets (of, def, from, b, at, len)
|
|
354
|
+
elseif def.kind == "set" then
|
|
355
|
+
taken = paired (def.site.sidecar, refs, taken)
|
|
356
|
+
ends = stated (of, def, lossy, b, at)
|
|
357
|
+
elseif id == def.id then
|
|
358
|
+
taken = paired (def.request.sidecar, refs, taken)
|
|
359
|
+
ends = asked (of, def, from, b, at, len)
|
|
360
|
+
else
|
|
361
|
+
taken = paired (def.response.sidecar, refs, taken)
|
|
362
|
+
ends = answered (of, def, b, at, len, now)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
if ends == nil then return end
|
|
366
|
+
if ends <= at then
|
|
367
|
+
Boundary.lost (boundary, Catalog.DEFID, {
|
|
368
|
+
expected = "a block that reads forward",
|
|
369
|
+
got = def.name,
|
|
370
|
+
})
|
|
371
|
+
return
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
Tally.received (of.tally, def.name, ends - at)
|
|
375
|
+
at = ends
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
return table.freeze (Router)
|