@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
package/state/Plan.luau
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
--!strict
|
|
2
|
+
--!optimize 2
|
|
3
|
+
-- One partition's flush: what it owes the wire, in order, cut to what a section holds.
|
|
4
|
+
|
|
5
|
+
local Coalesce = require (script.Parent.Coalesce)
|
|
6
|
+
local Protocol = require (script.Parent.Parent.wire.Protocol)
|
|
7
|
+
local Sections = require (script.Parent.Sections)
|
|
8
|
+
local Store = require (script.Parent.Store)
|
|
9
|
+
local Wide = require (script.Parent.Parent.kernel.Wide)
|
|
10
|
+
|
|
11
|
+
local Plan = {}
|
|
12
|
+
|
|
13
|
+
-- Constants -----------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
const KEYFRAME = Protocol.SECTION_KEYFRAME
|
|
16
|
+
const DELTA = Protocol.SECTION_DELTA
|
|
17
|
+
const REMOVAL = Protocol.SECTION_REMOVAL
|
|
18
|
+
const CLEAR = Protocol.SECTION_CLEAR
|
|
19
|
+
|
|
20
|
+
-- What one section may carry.
|
|
21
|
+
const BOUND = Protocol.SECTION_BYTES
|
|
22
|
+
|
|
23
|
+
--[[
|
|
24
|
+
What the widest varint spends, which is what a slot is bounded by and so what an entry of a
|
|
25
|
+
removal costs and what the slot half of every other entry costs.
|
|
26
|
+
]]
|
|
27
|
+
const WIDEST = Protocol.VARINT_GROUPS
|
|
28
|
+
|
|
29
|
+
const BYTE = Protocol.BYTE_BITS
|
|
30
|
+
|
|
31
|
+
const NONE = Wide.NONE
|
|
32
|
+
|
|
33
|
+
-- The stages a partition goes through, which is the order they are applied in.
|
|
34
|
+
const CLEARING = 1
|
|
35
|
+
const DROPPING = CLEARING + 1
|
|
36
|
+
const MAKING = DROPPING + 1
|
|
37
|
+
const MOVING = MAKING + 1
|
|
38
|
+
const SETTLED = MOVING + 1
|
|
39
|
+
|
|
40
|
+
-- What a field's coverage says: it changed on every slot the section lists, or it did not.
|
|
41
|
+
const COVERS = 1
|
|
42
|
+
const SOME = 0
|
|
43
|
+
|
|
44
|
+
-- What a record's field says about itself in a presence run, which is one bit either way.
|
|
45
|
+
const CARRIES = 1
|
|
46
|
+
const EMPTY = 0
|
|
47
|
+
|
|
48
|
+
-- Types ---------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
-- What one partition owes the wire, as a flush's mutations folded to their net effect.
|
|
51
|
+
export type Dirt = {
|
|
52
|
+
ops: { [number]: Coalesce.Kind },
|
|
53
|
+
masks: { [number]: Wide.Word },
|
|
54
|
+
freed: { [number]: number },
|
|
55
|
+
cleared: boolean,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
-- One partition: which key it is, what it holds, and what it owes.
|
|
59
|
+
export type Partition = {
|
|
60
|
+
read key: any,
|
|
61
|
+
read store: Store.Store,
|
|
62
|
+
read dirt: Dirt,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
-- What a flush may spend on state, and what it has spent.
|
|
66
|
+
export type Budget = {
|
|
67
|
+
read target: number,
|
|
68
|
+
spent: number,
|
|
69
|
+
took: boolean,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
-- One set's planner: what a section of it costs, and the scratch one partition's flush fills.
|
|
73
|
+
export type Plan = {
|
|
74
|
+
read layout: Sections.Layout,
|
|
75
|
+
read bit: { integer },
|
|
76
|
+
read room: number,
|
|
77
|
+
read kinds: { number },
|
|
78
|
+
read cuts: { number },
|
|
79
|
+
read counts: { number },
|
|
80
|
+
read dropped: { number },
|
|
81
|
+
read made: { number },
|
|
82
|
+
read moved: { number },
|
|
83
|
+
read masks: { integer },
|
|
84
|
+
stage: number,
|
|
85
|
+
stop: number,
|
|
86
|
+
at: number,
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
-- Private -------------------------------------------------------------
|
|
90
|
+
|
|
91
|
+
-- A scratch list holding exactly what was put in it, which is what a sort reads its length from.
|
|
92
|
+
local function trimmed (of: { number }, count: number, was: number)
|
|
93
|
+
for index = count + 1, was do
|
|
94
|
+
of[index] = nil
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
-- How many entries of a delta fit one section, worked out per partition from the fields it moved.
|
|
99
|
+
local function fitted (of: Plan, whole: Wide.Word): number
|
|
100
|
+
local gained = of.layout.gained
|
|
101
|
+
|
|
102
|
+
local spent = 0
|
|
103
|
+
local selected = 0
|
|
104
|
+
|
|
105
|
+
local mask = whole
|
|
106
|
+
while Wide.any (mask) do
|
|
107
|
+
spent += gained[Wide.lowest (mask)]
|
|
108
|
+
selected += 1
|
|
109
|
+
mask = Wide.without (mask)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
return of.room // (BYTE * (WIDEST + spent) + selected)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
-- A removal's slots, which is the whole of what one carries.
|
|
116
|
+
local function removing (of: Plan, from: number, count: number)
|
|
117
|
+
local frame = of.layout.frame
|
|
118
|
+
|
|
119
|
+
frame.count = count
|
|
120
|
+
table.move (of.dropped, from, from + count - 1, 1, frame.slots)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
-- A keyframe's slots, the records bound to them, and the generations those bindings stand at.
|
|
124
|
+
local function making (of: Plan, store: Store.Store, from: number, count: number)
|
|
125
|
+
local frame = of.layout.frame
|
|
126
|
+
local gens = store.gens
|
|
127
|
+
local ids = store.ids
|
|
128
|
+
|
|
129
|
+
frame.count = count
|
|
130
|
+
for index = 1, count do
|
|
131
|
+
local slot = of.made[from + index - 1]
|
|
132
|
+
|
|
133
|
+
frame.slots[index] = slot
|
|
134
|
+
frame.ids[index] = ids[slot]
|
|
135
|
+
if gens ~= nil then frame.gens[index] = gens[slot] end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
-- A delta's slots, the fields they moved between them, and which of them each field reached.
|
|
140
|
+
local function moving (of: Plan, from: number, count: number)
|
|
141
|
+
local frame = of.layout.frame
|
|
142
|
+
local chosen = frame.chosen
|
|
143
|
+
local masks = of.masks
|
|
144
|
+
|
|
145
|
+
frame.count = count
|
|
146
|
+
|
|
147
|
+
local union = NONE
|
|
148
|
+
for index = 1, count do
|
|
149
|
+
local place = from + index - 1
|
|
150
|
+
|
|
151
|
+
frame.slots[index] = of.moved[place]
|
|
152
|
+
union = Wide.union (union, masks[place])
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
local reached = 0
|
|
156
|
+
local mask = union
|
|
157
|
+
while Wide.any (mask) do
|
|
158
|
+
local field = Wide.lowest (mask)
|
|
159
|
+
mask = Wide.without (mask)
|
|
160
|
+
|
|
161
|
+
reached += 1
|
|
162
|
+
chosen.fields[reached] = field
|
|
163
|
+
|
|
164
|
+
local one = of.bit[field]
|
|
165
|
+
local present = frame.present[reached]
|
|
166
|
+
local covered = 0
|
|
167
|
+
|
|
168
|
+
for index = 1, count do
|
|
169
|
+
local on = if Wide.meets (masks[from + index - 1], one) then CARRIES else EMPTY
|
|
170
|
+
present[index] = on
|
|
171
|
+
covered += on
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
chosen.full[reached] = if covered == count then COVERS else SOME
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
chosen.count = reached
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
-- The frame filled for whichever kind is next, which a clear does not have and the rest do.
|
|
181
|
+
local function filled (of: Plan, store: Store.Store, kind: number, from: number, count: number)
|
|
182
|
+
if kind == KEYFRAME then
|
|
183
|
+
making (of, store, from, count)
|
|
184
|
+
elseif kind == DELTA then
|
|
185
|
+
moving (of, from, count)
|
|
186
|
+
elseif kind == REMOVAL then
|
|
187
|
+
removing (of, from, count)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
-- Whichever section the frame is filled for, laid down at the cursor it was handed.
|
|
192
|
+
local function laid (of: Plan, store: Store.Store, b: buffer, pos: number, kind: number): number
|
|
193
|
+
local layout = of.layout
|
|
194
|
+
|
|
195
|
+
if kind == KEYFRAME then return Sections.keyframe (layout, b, pos, store.columns) end
|
|
196
|
+
if kind == DELTA then return Sections.delta (layout, b, pos, store.columns, store.prev) end
|
|
197
|
+
if kind == REMOVAL then return Sections.removal (layout, b, pos) end
|
|
198
|
+
|
|
199
|
+
return Sections.clear (layout, b, pos)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
-- The records a removal carried, taken off what the flush still owes.
|
|
203
|
+
local function released (of: Plan, dirt: Dirt, from: number, count: number)
|
|
204
|
+
for index = from, from + count - 1 do
|
|
205
|
+
local slot = of.dropped[index]
|
|
206
|
+
local id = dirt.freed[slot]
|
|
207
|
+
local op = dirt.ops[id]
|
|
208
|
+
|
|
209
|
+
dirt.freed[slot] = nil
|
|
210
|
+
if op == "replace" then
|
|
211
|
+
dirt.ops[id] = "add"
|
|
212
|
+
continue
|
|
213
|
+
end
|
|
214
|
+
if op == "add" then continue end
|
|
215
|
+
|
|
216
|
+
dirt.ops[id] = nil
|
|
217
|
+
dirt.masks[id] = nil
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
-- The records a keyframe or a delta carried, taken off what the flush still owes.
|
|
222
|
+
local function forgotten (
|
|
223
|
+
store: Store.Store,
|
|
224
|
+
dirt: Dirt,
|
|
225
|
+
slots: { number },
|
|
226
|
+
from: number,
|
|
227
|
+
count: number
|
|
228
|
+
)
|
|
229
|
+
for index = from, from + count - 1 do
|
|
230
|
+
local id = store.ids[slots[index] ]
|
|
231
|
+
|
|
232
|
+
dirt.ops[id] = nil
|
|
233
|
+
dirt.masks[id] = nil
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
local function retired (of: Plan, part: Partition, kind: number, from: number, count: number)
|
|
238
|
+
local dirt = part.dirt
|
|
239
|
+
|
|
240
|
+
if kind == CLEAR then
|
|
241
|
+
dirt.cleared = false
|
|
242
|
+
return
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
if kind == REMOVAL then
|
|
246
|
+
released (of, dirt, from, count)
|
|
247
|
+
return
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
forgotten (part.store, dirt, if kind == KEYFRAME then of.made else of.moved, from, count)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
-- Which section is next and which of the gathered entries it takes, and the cursor moved past it.
|
|
254
|
+
local function staged (of: Plan, dirt: Dirt): (number, number, number)
|
|
255
|
+
if of.stage == CLEARING then
|
|
256
|
+
of.stage = DROPPING
|
|
257
|
+
of.at = 1
|
|
258
|
+
|
|
259
|
+
if dirt.cleared then return CLEAR, 0, 0 end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
while of.stage <= of.stop do
|
|
263
|
+
local stage = of.stage
|
|
264
|
+
local left = of.counts[stage] - of.at + 1
|
|
265
|
+
|
|
266
|
+
if left > 0 then
|
|
267
|
+
local count = math.min (left, math.max (1, of.cuts[stage]))
|
|
268
|
+
local from = of.at
|
|
269
|
+
|
|
270
|
+
of.at += count
|
|
271
|
+
return of.kinds[stage], from, count
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
of.stage = stage + 1
|
|
275
|
+
of.at = 1
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
return SETTLED, 0, 0
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
-- Public --------------------------------------------------------------
|
|
282
|
+
|
|
283
|
+
-- How many whole records a keyframe of this set fits in the bytes it is handed.
|
|
284
|
+
function Plan.keyframes (of: Sections.Layout, bytes: number): number
|
|
285
|
+
return (math.min (bytes, BOUND) - of.opening) // of.entry
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
-- A set's planner, as the costs a section of it comes to and the scratch a partition fills.
|
|
289
|
+
function Plan.of (layout: Sections.Layout): Plan
|
|
290
|
+
local reach = layout.def.fieldCount
|
|
291
|
+
local bit = table.create (reach) :: { integer }
|
|
292
|
+
|
|
293
|
+
for field = 1, reach do
|
|
294
|
+
bit[field] = Coalesce.touched (NONE, field)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
local spare = BOUND - layout.opening
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
layout = layout,
|
|
301
|
+
bit = table.freeze (bit),
|
|
302
|
+
room = (spare - layout.set.widest) * BYTE,
|
|
303
|
+
kinds = table.freeze ({ [DROPPING] = REMOVAL, [MAKING] = KEYFRAME, [MOVING] = DELTA }),
|
|
304
|
+
cuts = {
|
|
305
|
+
[DROPPING] = spare // WIDEST,
|
|
306
|
+
[MAKING] = Plan.keyframes (layout, BOUND),
|
|
307
|
+
[MOVING] = 1,
|
|
308
|
+
},
|
|
309
|
+
counts = { [DROPPING] = 0, [MAKING] = 0, [MOVING] = 0 },
|
|
310
|
+
dropped = {},
|
|
311
|
+
made = {},
|
|
312
|
+
moved = {},
|
|
313
|
+
masks = {},
|
|
314
|
+
stage = SETTLED,
|
|
315
|
+
stop = SETTLED,
|
|
316
|
+
at = 1,
|
|
317
|
+
}
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
-- What a partition owes, empty, which a partition holds one of for as long as it exists.
|
|
321
|
+
function Plan.dirt (): Dirt return { ops = {}, masks = {}, freed = {}, cleared = false } end
|
|
322
|
+
|
|
323
|
+
-- What one flush of one namespace may spend on state, and what it has spent.
|
|
324
|
+
function Plan.budget (bytes: number): Budget return { target = bytes, spent = 0, took = false } end
|
|
325
|
+
|
|
326
|
+
-- The same one again, ready for another flush, for a caller that keeps one rather than making one.
|
|
327
|
+
function Plan.reset (of: Budget, bytes: number): Budget
|
|
328
|
+
local held = of :: { target: number, spent: number, took: boolean }
|
|
329
|
+
held.target, held.spent, held.took = bytes, 0, false
|
|
330
|
+
|
|
331
|
+
return of
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
--[[
|
|
335
|
+
Whether a flush has already spent what it was given, which both openers ask first.
|
|
336
|
+
|
|
337
|
+
What it keeps a full flush from doing is writing sections it is about to throw away, and it is
|
|
338
|
+
exact: the target is spent, so nothing further can fit whatever it costs.
|
|
339
|
+
]]
|
|
340
|
+
local function spent (of: Budget): boolean return of.took and of.spent >= of.target end
|
|
341
|
+
|
|
342
|
+
-- A plan opened on one partition and one half of the order, which is what both halves share.
|
|
343
|
+
local function opening (of: Plan, part: Partition, from: number, to: number)
|
|
344
|
+
of.layout.frame.key = part.key
|
|
345
|
+
of.stage = from
|
|
346
|
+
of.stop = to
|
|
347
|
+
of.at = 1
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
-- What one partition takes away, gathered and put in order, and whether it takes anything.
|
|
351
|
+
function Plan.dropping (of: Plan, budget: Budget, part: Partition): boolean
|
|
352
|
+
if spent (budget) then return false end
|
|
353
|
+
|
|
354
|
+
local dirt = part.dirt
|
|
355
|
+
|
|
356
|
+
local fell = 0
|
|
357
|
+
for slot in dirt.freed do
|
|
358
|
+
fell += 1
|
|
359
|
+
of.dropped[fell] = slot
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
trimmed (of.dropped, fell, of.counts[DROPPING])
|
|
363
|
+
table.sort (of.dropped)
|
|
364
|
+
|
|
365
|
+
of.counts[DROPPING] = fell
|
|
366
|
+
opening (of, part, CLEARING, DROPPING)
|
|
367
|
+
|
|
368
|
+
return dirt.cleared or fell > 0
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
-- What one partition puts down, gathered and put in order, and whether it puts anything.
|
|
372
|
+
function Plan.making (of: Plan, budget: Budget, part: Partition): boolean
|
|
373
|
+
if spent (budget) then return false end
|
|
374
|
+
|
|
375
|
+
local store = part.store
|
|
376
|
+
local dirt = part.dirt
|
|
377
|
+
local counts = of.counts
|
|
378
|
+
|
|
379
|
+
local builds, shifts = 0, 0
|
|
380
|
+
local whole = NONE
|
|
381
|
+
|
|
382
|
+
for id, op in dirt.ops do
|
|
383
|
+
if op == "remove" then continue end
|
|
384
|
+
|
|
385
|
+
if op == "update" then
|
|
386
|
+
shifts += 1
|
|
387
|
+
of.moved[shifts] = store.slotOf[id]
|
|
388
|
+
whole = Wide.union (whole, dirt.masks[id])
|
|
389
|
+
continue
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
builds += 1
|
|
393
|
+
of.made[builds] = store.slotOf[id]
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
trimmed (of.made, builds, counts[MAKING])
|
|
397
|
+
trimmed (of.moved, shifts, counts[MOVING])
|
|
398
|
+
|
|
399
|
+
table.sort (of.made)
|
|
400
|
+
table.sort (of.moved)
|
|
401
|
+
|
|
402
|
+
for index = 1, shifts do
|
|
403
|
+
of.masks[index] = dirt.masks[store.ids[of.moved[index] ] ]
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
counts[MAKING], counts[MOVING] = builds, shifts
|
|
407
|
+
of.cuts[MOVING] = fitted (of, whole)
|
|
408
|
+
opening (of, part, MAKING, MOVING)
|
|
409
|
+
|
|
410
|
+
return builds + shifts > 0
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
-- The next section of the partition this was opened on, written at the cursor it was handed.
|
|
414
|
+
function Plan.next (
|
|
415
|
+
of: Plan,
|
|
416
|
+
budget: Budget,
|
|
417
|
+
part: Partition,
|
|
418
|
+
b: buffer,
|
|
419
|
+
pos: number
|
|
420
|
+
): (number?, number)
|
|
421
|
+
local store = part.store
|
|
422
|
+
local kind, from, count = staged (of, part.dirt)
|
|
423
|
+
if kind == SETTLED then return nil, pos end
|
|
424
|
+
|
|
425
|
+
filled (of, store, kind, from, count)
|
|
426
|
+
local ends = laid (of, store, b, pos, kind)
|
|
427
|
+
|
|
428
|
+
local spent = ends - pos
|
|
429
|
+
if budget.took and budget.spent + spent > budget.target then
|
|
430
|
+
of.stage = SETTLED
|
|
431
|
+
return nil, pos
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
budget.spent += spent
|
|
435
|
+
budget.took = true
|
|
436
|
+
|
|
437
|
+
retired (of, part, kind, from, count)
|
|
438
|
+
return kind, ends
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
return table.freeze (Plan)
|