@oasys/oecs 0.3.1 → 0.4.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 (204) hide show
  1. package/README.md +196 -267
  2. package/dist/array-CxbPyiHO.cjs +1 -0
  3. package/dist/array-uFR7Q8fU.js +132 -0
  4. package/dist/core/ecs/access_check.d.ts +77 -0
  5. package/dist/core/ecs/access_check.d.ts.map +1 -0
  6. package/dist/core/ecs/archetype.d.ts +474 -0
  7. package/dist/core/ecs/archetype.d.ts.map +1 -0
  8. package/dist/core/ecs/builtin_relations.d.ts +43 -0
  9. package/dist/core/ecs/builtin_relations.d.ts.map +1 -0
  10. package/dist/core/ecs/command_log.d.ts +113 -0
  11. package/dist/core/ecs/command_log.d.ts.map +1 -0
  12. package/dist/core/ecs/component.d.ts +106 -0
  13. package/dist/core/ecs/component.d.ts.map +1 -0
  14. package/dist/core/ecs/compute_backend.d.ts +37 -0
  15. package/dist/core/ecs/compute_backend.d.ts.map +1 -0
  16. package/dist/core/ecs/dispatch_trace.d.ts +93 -0
  17. package/dist/core/ecs/dispatch_trace.d.ts.map +1 -0
  18. package/dist/core/ecs/ecs.d.ts +533 -0
  19. package/dist/core/ecs/ecs.d.ts.map +1 -0
  20. package/dist/core/ecs/ecs_memory.d.ts +179 -0
  21. package/dist/core/ecs/ecs_memory.d.ts.map +1 -0
  22. package/dist/core/ecs/entity.d.ts +28 -0
  23. package/dist/core/ecs/entity.d.ts.map +1 -0
  24. package/dist/core/ecs/event.d.ts +54 -0
  25. package/dist/core/ecs/event.d.ts.map +1 -0
  26. package/dist/core/ecs/frame_trace.d.ts +133 -0
  27. package/dist/core/ecs/frame_trace.d.ts.map +1 -0
  28. package/dist/core/ecs/host_commands.d.ts +252 -0
  29. package/dist/core/ecs/host_commands.d.ts.map +1 -0
  30. package/dist/core/ecs/index.d.ts +41 -0
  31. package/dist/core/ecs/index.d.ts.map +1 -0
  32. package/dist/core/ecs/observer.d.ts +142 -0
  33. package/dist/core/ecs/observer.d.ts.map +1 -0
  34. package/dist/core/ecs/query.d.ts +557 -0
  35. package/dist/core/ecs/query.d.ts.map +1 -0
  36. package/dist/core/ecs/ref.d.ts +31 -0
  37. package/dist/core/ecs/ref.d.ts.map +1 -0
  38. package/dist/core/ecs/relation.d.ts +231 -0
  39. package/dist/core/ecs/relation.d.ts.map +1 -0
  40. package/dist/core/ecs/resource.d.ts +33 -0
  41. package/dist/core/ecs/resource.d.ts.map +1 -0
  42. package/dist/core/ecs/resume.d.ts +85 -0
  43. package/dist/core/ecs/resume.d.ts.map +1 -0
  44. package/dist/core/ecs/run_condition.d.ts +75 -0
  45. package/dist/core/ecs/run_condition.d.ts.map +1 -0
  46. package/dist/core/ecs/schedule.d.ts +133 -0
  47. package/dist/core/ecs/schedule.d.ts.map +1 -0
  48. package/dist/core/ecs/sparse_store.d.ts +107 -0
  49. package/dist/core/ecs/sparse_store.d.ts.map +1 -0
  50. package/dist/core/ecs/store.d.ts +1149 -0
  51. package/dist/core/ecs/store.d.ts.map +1 -0
  52. package/dist/core/ecs/store_layout_listener.d.ts +23 -0
  53. package/dist/core/ecs/store_layout_listener.d.ts.map +1 -0
  54. package/dist/core/ecs/system.d.ts +134 -0
  55. package/dist/core/ecs/system.d.ts.map +1 -0
  56. package/dist/core/ecs/utils/arrays.d.ts +7 -0
  57. package/dist/core/ecs/utils/arrays.d.ts.map +1 -0
  58. package/dist/core/ecs/utils/constants.d.ts +12 -0
  59. package/dist/core/ecs/utils/constants.d.ts.map +1 -0
  60. package/dist/core/ecs/utils/error.d.ts +51 -0
  61. package/dist/core/ecs/utils/error.d.ts.map +1 -0
  62. package/dist/core/reactive/array.d.ts +24 -0
  63. package/dist/core/reactive/array.d.ts.map +1 -0
  64. package/dist/core/reactive/index.cjs +1 -0
  65. package/dist/core/reactive/index.d.ts +10 -0
  66. package/dist/core/reactive/index.d.ts.map +1 -0
  67. package/dist/core/reactive/index.js +17 -0
  68. package/dist/core/reactive/interop.d.ts +19 -0
  69. package/dist/core/reactive/interop.d.ts.map +1 -0
  70. package/dist/core/reactive/kernel.d.ts +71 -0
  71. package/dist/core/reactive/kernel.d.ts.map +1 -0
  72. package/dist/core/reactive/map.d.ts +16 -0
  73. package/dist/core/reactive/map.d.ts.map +1 -0
  74. package/dist/core/reactive/struct.d.ts +10 -0
  75. package/dist/core/reactive/struct.d.ts.map +1 -0
  76. package/dist/core/store/__generated__/abi.d.ts +43 -0
  77. package/dist/core/store/__generated__/abi.d.ts.map +1 -0
  78. package/dist/core/store/action_ring.d.ts +136 -0
  79. package/dist/core/store/action_ring.d.ts.map +1 -0
  80. package/dist/core/store/allocator.d.ts +238 -0
  81. package/dist/core/store/allocator.d.ts.map +1 -0
  82. package/dist/core/store/buffer_backed_column.d.ts +69 -0
  83. package/dist/core/store/buffer_backed_column.d.ts.map +1 -0
  84. package/dist/core/store/column_store.d.ts +265 -0
  85. package/dist/core/store/column_store.d.ts.map +1 -0
  86. package/dist/core/store/command_dispatch.d.ts +52 -0
  87. package/dist/core/store/command_dispatch.d.ts.map +1 -0
  88. package/dist/core/store/command_ring.d.ts +107 -0
  89. package/dist/core/store/command_ring.d.ts.map +1 -0
  90. package/dist/core/store/descriptor.d.ts +80 -0
  91. package/dist/core/store/descriptor.d.ts.map +1 -0
  92. package/dist/core/store/entity_index.d.ts +108 -0
  93. package/dist/core/store/entity_index.d.ts.map +1 -0
  94. package/dist/core/store/event_ring.d.ts +95 -0
  95. package/dist/core/store/event_ring.d.ts.map +1 -0
  96. package/dist/core/store/extend.d.ts +109 -0
  97. package/dist/core/store/extend.d.ts.map +1 -0
  98. package/dist/core/store/grow.d.ts +39 -0
  99. package/dist/core/store/grow.d.ts.map +1 -0
  100. package/dist/core/store/header.d.ts +64 -0
  101. package/dist/core/store/header.d.ts.map +1 -0
  102. package/dist/core/store/index.d.ts +16 -0
  103. package/dist/core/store/index.d.ts.map +1 -0
  104. package/dist/core/store/region_table.d.ts +74 -0
  105. package/dist/core/store/region_table.d.ts.map +1 -0
  106. package/dist/core/store/snapshot.d.ts +43 -0
  107. package/dist/core/store/snapshot.d.ts.map +1 -0
  108. package/dist/core/store/state_hash.d.ts +38 -0
  109. package/dist/core/store/state_hash.d.ts.map +1 -0
  110. package/dist/core/store/store_regions.d.ts +38 -0
  111. package/dist/core/store/store_regions.d.ts.map +1 -0
  112. package/dist/extensions/editor/editor.d.ts +149 -0
  113. package/dist/extensions/editor/editor.d.ts.map +1 -0
  114. package/dist/extensions/editor/field_handle.d.ts +35 -0
  115. package/dist/extensions/editor/field_handle.d.ts.map +1 -0
  116. package/dist/extensions/editor/index.cjs +1 -0
  117. package/dist/extensions/editor/index.d.ts +21 -0
  118. package/dist/extensions/editor/index.d.ts.map +1 -0
  119. package/dist/extensions/editor/index.js +209 -0
  120. package/dist/extensions/reactive/ecs_sync.d.ts +210 -0
  121. package/dist/extensions/reactive/ecs_sync.d.ts.map +1 -0
  122. package/dist/extensions/reactive/index.cjs +1 -0
  123. package/dist/extensions/reactive/index.d.ts +23 -0
  124. package/dist/extensions/reactive/index.d.ts.map +1 -0
  125. package/dist/extensions/reactive/index.js +225 -0
  126. package/dist/extensions/solid/index.cjs +1 -0
  127. package/dist/extensions/solid/index.d.ts +6 -0
  128. package/dist/extensions/solid/index.d.ts.map +1 -0
  129. package/dist/extensions/solid/index.js +32 -0
  130. package/dist/extensions/solid/kernel_solid.d.ts +42 -0
  131. package/dist/extensions/solid/kernel_solid.d.ts.map +1 -0
  132. package/dist/index.cjs +2 -1
  133. package/dist/index.d.ts +16 -12
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +8565 -1310
  136. package/dist/interop-CT-REx0W.cjs +1 -0
  137. package/dist/interop-CcY6ASQc.js +18 -0
  138. package/dist/kernel-DgyrLFjW.js +227 -0
  139. package/dist/kernel-yWV3XnAb.cjs +1 -0
  140. package/dist/log/console_sink.d.ts +4 -0
  141. package/dist/log/console_sink.d.ts.map +1 -0
  142. package/dist/log/index.d.ts +3 -0
  143. package/dist/log/index.d.ts.map +1 -0
  144. package/dist/log/logger.d.ts +27 -0
  145. package/dist/log/logger.d.ts.map +1 -0
  146. package/dist/primitives.cjs +1 -0
  147. package/dist/primitives.d.ts +18 -0
  148. package/dist/primitives.d.ts.map +1 -0
  149. package/dist/primitives.js +44 -0
  150. package/dist/shared-BXSZnxx4.cjs +1 -0
  151. package/dist/shared-C678TAPY.js +99 -0
  152. package/dist/shared.cjs +1 -0
  153. package/dist/shared.d.ts +22 -0
  154. package/dist/shared.d.ts.map +1 -0
  155. package/dist/shared.js +7 -0
  156. package/dist/topological_sort-DlRpSrxu.js +391 -0
  157. package/dist/topological_sort-WAT-VHb-.cjs +1 -0
  158. package/dist/type_primitives/assertions.d.ts +12 -8
  159. package/dist/type_primitives/assertions.d.ts.map +1 -1
  160. package/dist/type_primitives/binary_heap/binary_heap.d.ts +6 -2
  161. package/dist/type_primitives/binary_heap/binary_heap.d.ts.map +1 -1
  162. package/dist/type_primitives/bitset/bitset.d.ts +16 -4
  163. package/dist/type_primitives/bitset/bitset.d.ts.map +1 -1
  164. package/dist/type_primitives/brand.d.ts +6 -1
  165. package/dist/type_primitives/brand.d.ts.map +1 -1
  166. package/dist/type_primitives/error.d.ts +4 -0
  167. package/dist/type_primitives/error.d.ts.map +1 -1
  168. package/dist/type_primitives/index.d.ts +3 -0
  169. package/dist/type_primitives/index.d.ts.map +1 -1
  170. package/dist/type_primitives/sparse_map/sparse_map.d.ts +7 -3
  171. package/dist/type_primitives/sparse_map/sparse_map.d.ts.map +1 -1
  172. package/dist/type_primitives/sparse_set/sparse_set.d.ts +4 -0
  173. package/dist/type_primitives/sparse_set/sparse_set.d.ts.map +1 -1
  174. package/dist/type_primitives/topological_sort/topological_sort.d.ts +7 -3
  175. package/dist/type_primitives/topological_sort/topological_sort.d.ts.map +1 -1
  176. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts +53 -16
  177. package/dist/type_primitives/typed_arrays/typed_arrays.d.ts.map +1 -1
  178. package/dist/utils/arrays.d.ts +1 -1
  179. package/dist/utils/arrays.d.ts.map +1 -1
  180. package/dist/utils/error.d.ts +2 -20
  181. package/dist/utils/error.d.ts.map +1 -1
  182. package/package.json +36 -9
  183. package/dist/archetype.d.ts +0 -108
  184. package/dist/archetype.d.ts.map +0 -1
  185. package/dist/component.d.ts +0 -45
  186. package/dist/component.d.ts.map +0 -1
  187. package/dist/ecs.d.ts +0 -104
  188. package/dist/ecs.d.ts.map +0 -1
  189. package/dist/entity.d.ts +0 -11
  190. package/dist/entity.d.ts.map +0 -1
  191. package/dist/event.d.ts +0 -30
  192. package/dist/event.d.ts.map +0 -1
  193. package/dist/query.d.ts +0 -94
  194. package/dist/query.d.ts.map +0 -1
  195. package/dist/ref.d.ts +0 -23
  196. package/dist/ref.d.ts.map +0 -1
  197. package/dist/resource.d.ts +0 -23
  198. package/dist/resource.d.ts.map +0 -1
  199. package/dist/schedule.d.ts +0 -45
  200. package/dist/schedule.d.ts.map +0 -1
  201. package/dist/store.d.ts +0 -118
  202. package/dist/store.d.ts.map +0 -1
  203. package/dist/system.d.ts +0 -16
  204. package/dist/system.d.ts.map +0 -1
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Action ring — main-thread producer / worker-thread consumer SPSC ring
3
+ * for client input intents (`send_action`-shaped bytes). Plan §6.5 task
4
+ * 3 / `docs/ideas/buffer-wasm-sim-plan-2026-05-14T1600.md`.
5
+ *
6
+ * Same on-the-wire shape as `command_ring.ts`, but with two practical
7
+ * differences:
8
+ *
9
+ * 1. Producer/consumer roles flip — the action ring is main → worker,
10
+ * whereas the command ring is sim → host.
11
+ * 2. Slot payload carries a `length` prefix because client actions are
12
+ * variable-width (the encoded bytes that would normally go straight
13
+ * to the WebSocket). `payload[0]` is the length in bytes; bytes
14
+ * `[1..1+length)` are the action payload itself.
15
+ *
16
+ * Layout (identical to command ring header):
17
+ *
18
+ * [ write_head: u32 ] monotonic; modulo `capacity_slots` for slot
19
+ * [ read_head: u32 ] monotonic
20
+ * [ capacity: u32 ] slot count, power-of-two
21
+ * [ overflow: u32 ] 0 = OK; 1 = ring exhausted (producer side)
22
+ * [ slot 0: 16 B ] length: u8, payload: [15]u8
23
+ * [ slot 1: 16 B ] ...
24
+ *
25
+ * SPSC contract:
26
+ * - Producer: main thread, from `GameNetworkClient.send_action`. Pushes
27
+ * one entry per user action; `Atomics.store`s `write_head` after each.
28
+ * - Consumer: sim worker, drained on each `apply_diff` / `apply_snapshot`
29
+ * boundary. `Atomics.store`s `read_head` after each pop.
30
+ * - Today's consumer is a no-op observer (logs / counts in DEV) — the
31
+ * wire path still goes main → WebSocket → server. PR 5N migrates the
32
+ * `PredictionReconciler` into the worker so the action ring becomes
33
+ * load-bearing for client-side prediction.
34
+ *
35
+ * Overflow:
36
+ * - If main writes a slot when `(write_head - read_head) === capacity`,
37
+ * it sets `overflow = 1` and the push returns `false`. The server
38
+ * send path is independent (`_transport.send(...)` ran first), so an
39
+ * overflow doesn't drop the action — it only drops worker
40
+ * observability for that one entry.
41
+ *
42
+ * Atomics: the head fields (`write_head` / `read_head`) are the
43
+ * cross-thread synchronization edge — the producer runs on the main
44
+ * thread, the consumer in the sim worker, and both alias the same
45
+ * `SharedArrayBuffer`. The producer writes the slot bytes, then
46
+ * `Atomics.store`s `write_head`; the consumer `Atomics.load`s
47
+ * `write_head` before touching the slot, reads it, then `Atomics.store`s
48
+ * `read_head`. These SeqCst ops establish the happens-before that a
49
+ * plain `DataView` write does not under the JS memory model (#374):
50
+ * without them the worker could observe a bumped `write_head` before the
51
+ * producer's `setUint8(len)` + payload `set()` are visible and read a
52
+ * torn/stale slot, and the producer could read a stale `read_head`
53
+ * (false overflow, or overwrite a slot mid-read). Slot payload bytes
54
+ * stay on plain `DataView` / `Uint8Array` ops — the head Atomics fence
55
+ * them, so no per-byte atomic is needed. A future PR may still add an
56
+ * `Atomics.wait/notify` pair so the worker can block between actions
57
+ * instead of polling — additive change, no layout shift.
58
+ */
59
+ /** Total bytes for the ring header. Identical to `command_ring`. */
60
+ export declare const ACTION_RING_HEADER_BYTES = 16;
61
+ /** Fixed slot size — 1-byte length + 15-byte payload. */
62
+ export declare const ACTION_RING_SLOT_BYTES = 16;
63
+ /** Default ring capacity in slots. Sized for ~250 ms of click-spam at 60
64
+ * Hz on the high end of human input rates; 256 × 16 B = 4 KiB + 16 B
65
+ * header. */
66
+ export declare const ACTION_RING_DEFAULT_CAPACITY_SLOTS = 256;
67
+ /** Max payload bytes per slot (slot size minus the length prefix). All
68
+ * actions defined in `packages/protocol/src/actions.ts` encode to under
69
+ * 8 bytes, so this is comfortably above today's max. */
70
+ export declare const ACTION_RING_MAX_PAYLOAD_BYTES: number;
71
+ /** Byte offsets within the ring header. Matches `command_ring` so a
72
+ * future shared helper can normalise across both rings without per-ring
73
+ * arithmetic. */
74
+ export declare const ACTION_RING_HEADER_OFFSETS: {
75
+ readonly write_head: 0;
76
+ readonly read_head: 4;
77
+ readonly capacity_slots: 8;
78
+ readonly overflow_flag: 12;
79
+ };
80
+ /** Total bytes the ring occupies for `capacity_slots` slots. */
81
+ export declare function actionRingBytes(capacitySlots: number): number;
82
+ export declare class ActionRingError extends Error {
83
+ constructor(message: string);
84
+ }
85
+ /** Initialise the ring header at `ringOff` in the SAB. Zeroes heads
86
+ * and the overflow flag; sets `capacity_slots`. Slot bytes are left
87
+ * as-is (callers normally allocate the ring on a zero-initialised SAB). */
88
+ export declare function initActionRing(view: DataView, ringOff: number, capacitySlots: number): void;
89
+ /** Read live ring-header fields. Heads are stored signed but returned
90
+ * unsigned (`>>> 0`) so the monotonic-counter arithmetic below is
91
+ * identical to the prior `getUint32` behaviour. */
92
+ export declare function actionRingWriteHead(view: DataView, ringOff: number): number;
93
+ export declare function actionRingReadHead(view: DataView, ringOff: number): number;
94
+ export declare function actionRingCapacitySlots(view: DataView, ringOff: number): number;
95
+ export declare function actionRingOverflow(view: DataView, ringOff: number): boolean;
96
+ /** Pending entry count = `(write_head - read_head) mod 2^32`. */
97
+ export declare function pendingActionCount(view: DataView, ringOff: number): number;
98
+ /** Push an action into the ring. `payload` must be in
99
+ * `[1, ACTION_RING_MAX_PAYLOAD_BYTES]`; longer payloads — and **empty**
100
+ * ones — are an `ActionRingError` (the producer is the only caller and it
101
+ * can size its inputs ahead of time). The zero-length rejection closes the
102
+ * lower-bound footgun: a 0-byte slot is indistinguishable from
103
+ * `popAction`'s empty-ring sentinel (`0`), so admitting one would let it
104
+ * masquerade as "ring empty". No encoder produces a 0-byte payload, so this
105
+ * only ever rejects the ABI-skew bug case (#430). Returns `false` on
106
+ * overflow and sets the overflow flag. */
107
+ export declare function pushAction(view: DataView, ringOff: number, payload: Uint8Array): boolean;
108
+ /** Pop one action from the ring. Returns the byte length written into
109
+ * `outPayload`, or `0` if the ring was empty. `outPayload` must be at
110
+ * least `ACTION_RING_MAX_PAYLOAD_BYTES`; only the first `length` bytes
111
+ * are meaningful after a non-zero return.
112
+ *
113
+ * NOTE: a `0` return is ambiguous — it means "ring empty" OR "a 0-byte
114
+ * slot" (the latter only reachable via ABI-skew, since `pushAction`
115
+ * rejects empty payloads). Callers that loop must decide emptiness from
116
+ * the heads (`pendingActionCount` / `write_head === read_head`), not
117
+ * from this return value; see `drainActionRing` and #430. */
118
+ export declare function popAction(view: DataView, ringOff: number, outPayload: Uint8Array): number;
119
+ /** Drain every pending action, invoking `handler(payload)` per entry.
120
+ * The `payload` passed to the handler is a freshly-copied
121
+ * `Uint8Array(length)` so handlers can hold it past the next pop without
122
+ * aliasing the scratch buffer. Returns the number of actions drained.
123
+ *
124
+ * Termination is decided from the heads (`pendingActionCount`), NOT from
125
+ * `popAction`'s return value. A genuine 0-byte slot returns `0` — the same
126
+ * value `popAction` yields on an empty ring — so terminating on `len === 0`
127
+ * would silently consume the zero-length entry and strand everything queued
128
+ * behind it for a tick (#430). The heads check is SPSC-safe: this consumer
129
+ * is the sole reader, so a non-zero pending count cannot race to empty before
130
+ * the `popAction` below. */
131
+ export declare function drainActionRing(view: DataView, ringOff: number, handler: (payload: Uint8Array) => void): number;
132
+ /** Clear the overflow flag. The producer sets it on a failed push; the
133
+ * consumer can reset it once it has observed and logged the condition,
134
+ * so a single overflow doesn't keep firing dev assertions. */
135
+ export declare function clearActionRingOverflow(view: DataView, ringOff: number): void;
136
+ //# sourceMappingURL=action_ring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action_ring.d.ts","sourceRoot":"","sources":["../../../src/core/store/action_ring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAEH,oEAAoE;AACpE,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAE3C,yDAAyD;AACzD,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;aAEa;AACb,eAAO,MAAM,kCAAkC,MAAM,CAAC;AAEtD;;wDAEwD;AACxD,eAAO,MAAM,6BAA6B,QAA6B,CAAC;AAExE;;iBAEiB;AACjB,eAAO,MAAM,0BAA0B;;;;;CAK7B,CAAC;AAwBX,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE7D;AAMD,qBAAa,eAAgB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI3B;AAED;;2EAE2E;AAC3E,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAiB3F;AAED;;mDAEmD;AACnD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3E;AACD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1E;AACD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/E;AACD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3E;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED;;;;;;;;0CAQ0C;AAC1C,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAoCxF;AAED;;;;;;;;;6DAS6D;AAC7D,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,CAwBzF;AAED;;;;;;;;;;;4BAW4B;AAC5B,wBAAgB,eAAe,CAC9B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,GACpC,MAAM,CAUR;AAED;;8DAE8D;AAC9D,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7E"}
@@ -0,0 +1,238 @@
1
+ /**
2
+ * BufferAllocator — pluggable buffer source for the SAB layer (#234 / PR 3D).
3
+ *
4
+ * The engine has historically allocated its SAB as a fresh
5
+ * `new SharedArrayBuffer(totalBytes)` inside `createColumnStore`.
6
+ * Phase 3D requires the SAB to optionally be backed by a
7
+ * `WebAssembly.Memory.buffer` so the WASM sim can read/write the live
8
+ * ECS columns through its own memory handle. This module abstracts the
9
+ * "where does the buffer come from" decision behind a single function
10
+ * type.
11
+ *
12
+ * Contract for every `BufferAllocator`:
13
+ * - Returns a `SharedArrayBuffer` of byteLength >= `bytes`.
14
+ * - MAY detach any prior buffer the implementation has handed out
15
+ * (e.g., `WebAssembly.Memory.grow` detaches existing typed-array
16
+ * views into the previous buffer). Callers MUST snapshot any data
17
+ * they need to preserve BEFORE invoking the allocator.
18
+ * - Returned buffers MAY be larger than `bytes` (e.g., wasm-memory
19
+ * rounds up to 64 KiB page boundaries). Callers must rely on the
20
+ * SAB header / descriptor for the canonical layout, not on
21
+ * `buffer.byteLength`.
22
+ *
23
+ * The default `DEFAULT_SAB_ALLOCATOR` does `new SharedArrayBuffer(bytes)`
24
+ * — fast, allocation-per-call, prior buffers untouched. Production code
25
+ * paths that don't care about wasm interop stay on this.
26
+ *
27
+ * `wasmMemoryAllocator(memory)` returns an allocator that grows the
28
+ * given `WebAssembly.Memory` (in 64 KiB page increments) as needed and
29
+ * returns its current buffer. Used by a host so the
30
+ * engine's SAB IS the sim's memory.
31
+ */
32
+ /**
33
+ * Source of `SharedArrayBuffer`s for the SAB layer. See the file header
34
+ * for the contract — in particular, the detachment caveat for in-place
35
+ * implementations.
36
+ *
37
+ * The optional `isInPlace` marker tells the SAB layer that
38
+ * **TypedArray and DataView views built over a returned buffer remain
39
+ * valid after a subsequent allocator call** — reads and writes through
40
+ * the old views land on the same underlying memory the new buffer
41
+ * exposes. The `extendColumnStore` fast path uses this hint to skip the
42
+ * snapshot+restore + view-rebuild work that's only necessary when the
43
+ * memory actually moves.
44
+ *
45
+ * Note: `isInPlace` does NOT promise the SAB *reference* stays
46
+ * identical. `growableSabAllocator` happens to return the same SAB
47
+ * instance every time (`SharedArrayBuffer.prototype.grow` resizes in
48
+ * place); `wasmMemoryAllocator` on shared `WebAssembly.Memory`
49
+ * returns a *new* SAB ref after `memory.grow()`, but old views built
50
+ * over the previous ref keep working — V8 keeps the underlying linear
51
+ * memory mapped at the same address. Verified empirically (this branch,
52
+ * Bun + V8): writes via an old `Int32Array(old_ref, off, len)` after
53
+ * `memory.grow()` are visible through a fresh view over the new ref,
54
+ * and vice versa. Default allocator omits the marker;
55
+ * `growableSabAllocator` and `wasmMemoryAllocator` set it.
56
+ */
57
+ export interface BufferAllocator {
58
+ /** Returns a buffer of byteLength >= `bytes`. The historical name is
59
+ * "SAB", but the return is `ArrayBufferLike`: `growableSabAllocator` /
60
+ * `wasmMemoryAllocator` produce a `SharedArrayBuffer` (the SAB profile),
61
+ * while `heapArraybufferAllocator` produces a plain resizable
62
+ * `ArrayBuffer` (the pure-TS heap profile — no cross-origin isolation
63
+ * required). The store layer treats the backing uniformly; only the
64
+ * WASM/worker boundary narrows back to `SharedArrayBuffer`. */
65
+ (bytes: number): ArrayBufferLike;
66
+ readonly isInPlace?: boolean;
67
+ }
68
+ /**
69
+ * The only allocator shape a **live `Store`** accepts (#682). ADR-0008 makes
70
+ * "a live Store is backed by an in-place allocator" a correctness invariant —
71
+ * the flush loops hoist entity-index views across grows. This brand moves
72
+ * that invariant from runtime convention to the type/construction boundary:
73
+ * `growableSabAllocator` / `wasmMemoryAllocator` / `heapArraybufferAllocator`
74
+ * return it; `DEFAULT_SAB_ALLOCATOR` keeps the wide `BufferAllocator` type and
75
+ * therefore cannot typecheck where a live-Store backing is required. Non-in-place
76
+ * allocators remain valid for snapshot/test sizing only. The brand says nothing
77
+ * about *shared* vs *heap* backing — `heapArraybufferAllocator`'s resizable
78
+ * `ArrayBuffer` is just as in-place as a growable SAB (`.resize()` preserves
79
+ * existing views exactly like `SharedArrayBuffer.prototype.grow`).
80
+ */
81
+ export type InPlaceBufferAllocator = BufferAllocator & {
82
+ readonly isInPlace: true;
83
+ };
84
+ /**
85
+ * Thrown when an allocator cannot satisfy a request because its by-design
86
+ * byte ceiling is reached (#380: the cap is a runaway-growth signal, not a
87
+ * limit to paper over — there is deliberately no grow-beyond-cap fallback).
88
+ * Typed so `Store`'s grow handler can recognise the cap case and re-throw
89
+ * with the caller's declared sizing intent attached (#682) without ever
90
+ * catching-to-recover.
91
+ */
92
+ export declare class StoreCapExceededError extends Error {
93
+ readonly requestedBytes: number;
94
+ /** `null` when the ceiling isn't knowable from JS (a shared
95
+ * `WebAssembly.Memory` doesn't expose its `maximum`). */
96
+ readonly capBytes: number | null;
97
+ constructor(message: string, requestedBytes: number,
98
+ /** `null` when the ceiling isn't knowable from JS (a shared
99
+ * `WebAssembly.Memory` doesn't expose its `maximum`). */
100
+ capBytes: number | null, options?: ErrorOptions);
101
+ }
102
+ /** Thrown when a **SAB-producing** allocator runs in an environment that
103
+ * doesn't expose `SharedArrayBuffer`. The fix is environment-level (the host
104
+ * must serve the page cross-origin isolated, or be a runtime like Bun that
105
+ * exposes SAB unconditionally) — OR choose the pure-TS heap profile
106
+ * (`memory: { heap: {} }` / `heapArraybufferAllocator`), which needs no SAB
107
+ * and no cross-origin isolation. Lives on the allocator (not the store)
108
+ * because the allocator is the only thing that constructs a SAB. */
109
+ export declare class SabUnavailableError extends Error {
110
+ constructor();
111
+ }
112
+ /**
113
+ * Allocate a fresh `SharedArrayBuffer` per call. Prior buffers are
114
+ * untouched and remain valid for as long as the caller holds references.
115
+ * This is the default used by `createColumnStore` when no allocator is
116
+ * provided. Throws `SabUnavailableError` in a runtime without SAB — the
117
+ * availability check lives here (the SAB-producing seam), not in
118
+ * `createColumnStore`, so a heap allocator never trips it.
119
+ */
120
+ export declare const DEFAULT_SAB_ALLOCATOR: BufferAllocator;
121
+ /**
122
+ * Allocator that backs the SAB by a single growable `SharedArrayBuffer`
123
+ * (created with `{ maxByteLength: maxBytes }`). First call allocates;
124
+ * subsequent calls `.grow(bytes)` the existing buffer and return it.
125
+ *
126
+ * The `isInPlace` marker is set so `extendColumnStore` knows it can
127
+ * reuse the buffer rather than allocating fresh and copying data —
128
+ * existing typed-array views built with explicit `(byteOffset, length)`
129
+ * stay valid after `.grow()` in Bun + V8 (the underlying mapping extends
130
+ * in place rather than relocating).
131
+ *
132
+ * Sizing: `maxBytes` is committed *virtual* memory, not resident RAM —
133
+ * physical pages fault in lazily as the SAB actually grows. Larger caps
134
+ * cost more per allocation than smaller ones — Bun benchmark
135
+ * `alloc(64,max=1GB)+grow(65568)` measures ~32 µs vs ~21 µs at 256 MB
136
+ * and ~12 µs at 1 MB (V8 per-byte bookkeeping at construction).
137
+ * Production callers with bigger worlds can pass a larger cap; the bench
138
+ * gains are ~10 µs/Store-construction by staying under 256 MB.
139
+ *
140
+ * THE 256 MiB DEFAULT IS A HARD DESIGN CEILING, NOT A SOFT TARGET — and
141
+ * exceeding it is INTENDED to be fatal. There is deliberately no
142
+ * grow-beyond-cap fallback or compaction pass (see #380, and the loud
143
+ * note at the `bytes > maxBytes` throw below). If you are here because
144
+ * a workload died at the cap and you are tempted to add a fresh-allocator
145
+ * realloc fallback: don't, unless the numbers below have changed. They
146
+ * say the cap is structurally unreachable for a real workload.
147
+ *
148
+ * Measured footprint of a real 2-party workload (instrumented, 2026-05;
149
+ * do NOT trust the old "~500 archetypes × 64-capacity ≈ 2 MiB" figure
150
+ * that used to live here — it was wrong on every term):
151
+ * - Total SAB capacity ≈ 16.2 MiB — ~6% of the cap.
152
+ * - ~12 MiB of that is the entity-index region's *virtual* reservation
153
+ * (`ENTITY_INDEX_DEFAULT_CAPACITY = 1<<20` slots × 12 B); only ~12 KiB
154
+ * of it is physically resident for a 1000-entity workload.
155
+ * - Only ~5 archetypes are prewarmed (no lazy archetypes), each at
156
+ * `DEFAULT_COLUMN_CAPACITY = 1024` rows — NOT 64. Live column data is
157
+ * ~0.1 MiB; a fully-populated entity row is ~49 B.
158
+ * - Columns never trigger a grow: 1024 initial capacity already covers the
159
+ * ~1000-row budget, so the doubling + in-place hole tax never fires on
160
+ * the hot path.
161
+ * The entity-ID space itself caps total live entities at `1<<20` ≈ 1M
162
+ * (20-bit index in `EntityID`). Even at that absolute ceiling — ~1M rows
163
+ * × 49 B × ~3 (post-double capacity + abandoned holes) ≈ ~150 MiB columns
164
+ * + 12 MiB index — the workload still lands under 256 MiB. You cannot reach
165
+ * the cap without first exhausting the entity-ID space. Hitting it
166
+ * therefore signals a real defect upstream (runaway entity creation), not
167
+ * a sizing shortfall to paper over.
168
+ *
169
+ * Cited verification (#237 audit, this branch): Bun runtime check
170
+ * confirms `new Int32Array(buffer, off, len)` retains identical byteOffset,
171
+ * length, and stored values after `.grow()`; DataView byteLength
172
+ * auto-tracks the grown buffer.
173
+ *
174
+ * Used by the `extendColumnStore` fast path during lazy archetype
175
+ * registration (#237 Option A) — keeps existing column views valid so
176
+ * `refreshViews` is a no-op for old archetypes.
177
+ */
178
+ export declare function growableSabAllocator(maxBytes?: number): InPlaceBufferAllocator;
179
+ /**
180
+ * Allocator that backs the store by a single growable **plain `ArrayBuffer`**
181
+ * (created with `{ maxByteLength: maxBytes }`, grown via `.resize()`). This is
182
+ * the pure-TS **heap profile** — the oecs default and the answer to ADR-0018's
183
+ * deferred §1B: no `SharedArrayBuffer`, hence no cross-origin isolation
184
+ * (COOP/COEP) requirement, and no worker/WASM transfer (single-process worlds
185
+ * only). Otherwise identical to `growableSabAllocator`:
186
+ *
187
+ * - `isInPlace: true`. A resizable `ArrayBuffer`'s `.resize()` keeps the
188
+ * same buffer object and preserves existing TypedArray/DataView views, so
189
+ * the store's `extend`/`grow` fast path carries column views forward
190
+ * unchanged — exactly as `SharedArrayBuffer.prototype.grow` does. ADR-0008's
191
+ * entity-index-hoist-across-grow invariant holds identically.
192
+ * - same 256 MiB default cap with hard-ceiling semantics (#380): reaching it
193
+ * signals runaway growth upstream, not a limit to route around.
194
+ *
195
+ * Why a non-shared buffer suffices: `Atomics` live only on the cross-thread
196
+ * command/event/action rings, never on the core store path, so a single-process
197
+ * world needs no sharing. `stateHash` determinism works here too — FNV1a over
198
+ * column bytes is backing-agnostic.
199
+ */
200
+ export declare function heapArraybufferAllocator(maxBytes?: number): InPlaceBufferAllocator;
201
+ /**
202
+ * Allocator that backs the SAB by `memory.buffer` — i.e. makes the engine's
203
+ * live SAB *be* a WASM module's `WebAssembly.Memory`. Grows the memory in
204
+ * 64 KiB page increments when `bytes` exceeds the current buffer.
205
+ *
206
+ * This is the **opt-in storage backing for the WASM path** (#625). A consumer
207
+ * that attaches a WASM `ComputeBackend` passes
208
+ * `bufferAllocator: wasmMemoryAllocator(memory)` so the Zig systems read/write
209
+ * the same bytes the host's columns live in — zero-copy across the FFI boundary.
210
+ * It is NOT a match-context assumption: a pure-TS game omits `bufferAllocator` and
211
+ * gets the default (`DEFAULT_SAB_ALLOCATOR` — a fresh `SharedArrayBuffer` per
212
+ * alloc) or opts into `growableSabAllocator` for the in-place fast path
213
+ * without any WASM module. "The SAB is the WebAssembly.Memory" is thus a
214
+ * property the WASM backend opts into, paid for only when WASM is in use.
215
+ *
216
+ * After `memory.grow()` on a *shared* memory, `memory.buffer` returns a
217
+ * new `SharedArrayBuffer` reference, but **TypedArrays and DataViews
218
+ * built over the previous reference remain valid** — V8 keeps the
219
+ * underlying linear memory mapped at the same address, so reads and
220
+ * writes through old views land on the same bytes the new buffer
221
+ * exposes. This is why `isInPlace: true` is safe here (verified
222
+ * empirically against Bun + V8): the SAB layer's fast path can carry
223
+ * forward existing column views across an `extend` without paying for
224
+ * snapshot+restore. Old DataViews' `byteLength` is frozen at the
225
+ * pre-grow size, so callers needing to write past that boundary must
226
+ * construct a fresh DataView over the post-grow buffer (the SAB-layer
227
+ * extend path does this).
228
+ *
229
+ * Throws if `memory` was not constructed with `shared: true` — the SAB
230
+ * contract requires `SharedArrayBuffer`-backed memory. Throws a contextual
231
+ * error if a needed grow fails (cap reached or host refusal): the JS API's
232
+ * `memory.grow` throws a RangeError on cap overrun rather than returning the
233
+ * core wasm instruction's `-1`, and both are normalised into that error. The
234
+ * caller should construct memory with a `maximum` large enough for the
235
+ * workload's worst-case capacity.
236
+ */
237
+ export declare function wasmMemoryAllocator(memory: WebAssembly.Memory): InPlaceBufferAllocator;
238
+ //# sourceMappingURL=allocator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allocator.d.ts","sourceRoot":"","sources":["../../../src/core/store/allocator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;;;mEAM+D;IAC/D,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,sBAAsB,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;CAAE,CAAC;AAEpF;;;;;;;GAOG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;aAG9B,cAAc,EAAE,MAAM;IACtC;6DACyD;aACzC,QAAQ,EAAE,MAAM,GAAG,IAAI;gBAJvC,OAAO,EAAE,MAAM,EACC,cAAc,EAAE,MAAM;IACtC;6DACyD;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvC,OAAO,CAAC,EAAE,YAAY;CAKvB;AAED;;;;;;oEAMoE;AACpE,qBAAa,mBAAoB,SAAQ,KAAK;;CAe7C;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,EAAE,eAGnC,CAAC;AAKF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,MAA0B,GAAG,sBAAsB,CAsDjG;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,wBAAwB,CACvC,QAAQ,GAAE,MAA0B,GAClC,sBAAsB,CAwCxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,GAAG,sBAAsB,CA6DtF"}
@@ -0,0 +1,69 @@
1
+ import { ColumnBacking } from '../../type_primitives';
2
+ import { AnyTypedArray } from './column_store';
3
+ /** Thrown when an operation would grow a fixed-capacity SAB column. The
4
+ * grow path (re-allocate the SAB, bump `view_stamp`, rebuild views) is a
5
+ * separate sub-task; until it lands, hitting capacity is a hard error so
6
+ * the symptom surfaces immediately rather than silently corrupting state. */
7
+ export declare class StoreColumnOverflowError extends Error {
8
+ readonly capacity: number;
9
+ readonly requested: number;
10
+ constructor(capacity: number, requested: number);
11
+ }
12
+ export declare class BufferBackedColumn<T extends AnyTypedArray> implements ColumnBacking<T> {
13
+ private _buf;
14
+ private _capacity;
15
+ private _len;
16
+ /** `view` MUST be a TypedArray constructed over a SAB at the correct
17
+ * stride alignment (see `createColumnStore`). The column treats
18
+ * `view.length` as the immutable capacity for the lifetime of this view —
19
+ * call `refreshView` after a SAB realloc to point at the new view. */
20
+ constructor(view: T);
21
+ /** Swap the backing view to one over a freshly-grown SAB. The caller is
22
+ * responsible for having copied the first `length` elements into
23
+ * `newView` already (`growColumnStore` does this). The logical length is
24
+ * preserved across the swap; capacity becomes `newView.length`.
25
+ *
26
+ * Used to honour the `view_stamp` invariant after a host-side SAB realloc
27
+ * (#171 §6.1.4 / §8.1): every cached column view must be rebuilt before
28
+ * the next read/write. */
29
+ refreshView(newView: T): void;
30
+ get length(): number;
31
+ get capacity(): number;
32
+ push(value: number): void;
33
+ pop(): number;
34
+ get(i: number): number;
35
+ setAt(i: number, value: number): void;
36
+ /** Move the last element into slot `i`, decrement length. Returns the
37
+ * value previously at slot `i`. Matches `GrowableTypedArray.swapRemove`. */
38
+ swapRemove(i: number): number;
39
+ clear(): void;
40
+ /** Set the logical length directly, declaring that `[0, len)` of the backing
41
+ * SAB view already holds valid data. The snapshot-mount path
42
+ * (`Archetype.restoreHostRows`, #789) uses this to re-sync the column's
43
+ * logical length with the restored `Archetype.length` — the bytes come from
44
+ * the restored SAB, but `_len` is host state. Throws on overrun (cannot grow
45
+ * a fixed SAB view here — the mount already adopted the restored capacity). */
46
+ setLength(len: number): void;
47
+ /** Raw backing view. Stable for the lifetime of the SAB; views over a
48
+ * SAB do not invalidate the way a `GrowableTypedArray`'s `buf` does
49
+ * after a grow. (`view_stamp` will signal "underlying SAB swapped"
50
+ * once #171 §6.1.4 lands.) */
51
+ get buf(): T;
52
+ /** Zero-copy subarray of valid data (`0..length-1`). */
53
+ view(): T;
54
+ [Symbol.iterator](): Iterator<number>;
55
+ /** Throw if the backing view cannot hold `capacity` elements. Mirrors
56
+ * `GrowableTypedArray.ensureCapacity` but cannot allocate — a SAB
57
+ * grow requires republishing the underlying buffer and rebuilding views
58
+ * across every archetype, which is the §6.1.4 invariant. */
59
+ ensureCapacity(capacity: number): void;
60
+ /** Append `count` elements from `src[srcOffset..srcOffset+count]`.
61
+ * Throws on overrun. */
62
+ bulkAppend(src: T, srcOffset: number, count: number): void;
63
+ /** Append `count` zeroes. Throws on overrun. */
64
+ bulkAppendZeroes(count: number): void;
65
+ /** Append `count` copies of `value`. Throws on overrun. Single-pass
66
+ * analogue of `bulkAppendZeroes` for a non-zero default. */
67
+ bulkAppendValue(value: number, count: number): void;
68
+ }
69
+ //# sourceMappingURL=buffer_backed_column.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer_backed_column.d.ts","sourceRoot":"","sources":["../../../src/core/store/buffer_backed_column.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;;6EAG6E;AAC7E,qBAAa,wBAAyB,SAAQ,KAAK;IAClD,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,SAAS,EAAE,MAAM,CAAC;gBAEtB,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAM/C;AAED,qBAAa,kBAAkB,CAAC,CAAC,SAAS,aAAa,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;IACnF,OAAO,CAAC,IAAI,CAAI;IAChB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,IAAI,CAAK;IAEjB;;;0EAGsE;gBAC1D,IAAI,EAAE,CAAC;IAKnB;;;;;;;8BAO0B;IACnB,WAAW,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI;IAQpC,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAEM,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOzB,GAAG,IAAI,MAAM;IAIb,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAItB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI5C;gFAC4E;IACrE,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAM7B,KAAK,IAAI,IAAI;IAIpB;;;;;mFAK+E;IACxE,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAOnC;;;kCAG8B;IAC9B,IAAW,GAAG,IAAI,CAAC,CAElB;IAED,wDAAwD;IACjD,IAAI,IAAI,CAAC;IAQhB,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC;IAYrC;;;gEAG4D;IACrD,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAM7C;4BACwB;IACjB,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAQjE,gDAAgD;IACzC,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM5C;gEAC4D;IACrD,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CAK1D"}