1#[cfg(stageleft_runtime)]
7use std::marker::PhantomData;
8
9use super::Slicable;
10#[cfg(stageleft_runtime)]
11use crate::forward_handle::{CycleCollection, CycleCollectionWithInitial};
12use crate::forward_handle::{TickCycle, TickCycleHandle};
13use crate::live_collections::boundedness::{Bounded, Boundedness, Unbounded};
14use crate::live_collections::keyed_singleton::{BoundedValue, KeyedSingletonBound};
15use crate::live_collections::singleton::SingletonBound;
16use crate::live_collections::stream::{Ordering, Retries};
17use crate::location::Location;
18use crate::location::tick::{DeferTick, Tick};
19use crate::nondet::NonDet;
20
21pub struct Default<T> {
26 pub(crate) collection: T,
27 pub(crate) nondet: NonDet,
28}
29
30impl<T> Default<T> {
31 pub fn new(collection: T, nondet: NonDet) -> Self {
33 Self { collection, nondet }
34 }
35}
36
37#[doc(hidden)]
39#[deprecated(
40 note = "use `use::batch(...)` for stream-like collections or `use::snapshot(...)` for singleton-like collections instead"
41)]
42pub fn default<T>(t: T, nondet: NonDet) -> Default<T> {
43 Default::new(t, nondet)
44}
45
46pub struct Batch<T> {
50 pub(crate) collection: T,
51 pub(crate) nondet: NonDet,
52}
53
54impl<T> Batch<T> {
55 pub fn new(collection: T, nondet: NonDet) -> Self {
57 Self { collection, nondet }
58 }
59}
60
61pub fn batch<T>(t: T, nondet: NonDet) -> Batch<T> {
66 Batch::new(t, nondet)
67}
68
69pub struct Snapshot<T> {
73 pub(crate) collection: T,
74 pub(crate) nondet: NonDet,
75}
76
77impl<T> Snapshot<T> {
78 pub fn new(collection: T, nondet: NonDet) -> Self {
80 Self { collection, nondet }
81 }
82}
83
84pub fn snapshot<T>(t: T, nondet: NonDet) -> Snapshot<T> {
90 Snapshot::new(t, nondet)
91}
92
93pub struct Atomic<T> {
97 pub(crate) collection: T,
98 pub(crate) nondet: NonDet,
99}
100
101impl<T> Atomic<T> {
102 pub fn new(collection: T, nondet: NonDet) -> Self {
104 Self { collection, nondet }
105 }
106}
107
108pub fn atomic<T>(t: T, nondet: NonDet) -> Atomic<T> {
110 Atomic::new(t, nondet)
111}
112
113#[cfg(stageleft_runtime)]
126pub fn state<'t, S, L>(tick: &'t Tick<L>) -> StateBuilder<'t, S, L> {
127 StateBuilder {
128 tick,
129 _phantom: PhantomData,
130 }
131}
132
133#[cfg(stageleft_runtime)]
135pub struct StateBuilder<'t, S, L> {
136 tick: &'t Tick<L>,
137 _phantom: PhantomData<S>,
138}
139
140#[cfg(stageleft_runtime)]
141impl<'t, 'a, S, L: Location<'a>> StateBuilder<'t, S, L> {
142 #[expect(
150 private_bounds,
151 reason = "only Hydro collections can implement CycleCollectionWithInitial"
152 )]
153 pub fn build(self, initial_fn: impl FnOnce(&'t Tick<L>) -> S) -> (TickCycleHandle<'a, S>, S)
154 where
155 S: CycleCollectionWithInitial<'a, TickCycle, Location = Tick<L::DropConsistency>>,
156 {
157 let initial = initial_fn(self.tick);
158 initial.location().clone().cycle_with_initial(initial)
159 }
160}
161
162#[cfg(stageleft_runtime)]
170pub fn state_null<'t, S, L>(tick: &'t Tick<L>) -> StateNullBuilder<'t, S, L> {
171 StateNullBuilder {
172 tick,
173 _phantom: PhantomData,
174 }
175}
176
177#[cfg(stageleft_runtime)]
179pub struct StateNullBuilder<'t, S, L> {
180 tick: &'t Tick<L>,
181 _phantom: PhantomData<S>,
182}
183
184#[cfg(stageleft_runtime)]
185impl<'t, 'a, S, L: Location<'a>> StateNullBuilder<'t, S, L> {
186 #[expect(
188 private_bounds,
189 reason = "only Hydro collections can implement CycleCollection"
190 )]
191 pub fn build(self) -> (TickCycleHandle<'a, S>, S)
192 where
193 S: CycleCollection<'a, TickCycle, Location = Tick<L::DropConsistency>> + DeferTick,
194 {
195 self.tick.cycle::<S, _>()
196 }
197}
198
199impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
207 Slicable<'a, L::DropConsistency> for Default<crate::live_collections::Stream<T, L, B, O, R>>
208{
209 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
210 type Backtrace = crate::compile::ir::backtrace::Backtrace;
211
212 fn get_location(&self) -> L::DropConsistency {
213 self.collection.location().drop_consistency()
214 }
215 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
216 let out = self.collection.batch(tick, self.nondet);
217 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
218 out
219 }
220}
221
222impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
223 for Default<crate::live_collections::Singleton<T, L, B>>
224{
225 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
226 type Backtrace = crate::compile::ir::backtrace::Backtrace;
227
228 fn get_location(&self) -> L::DropConsistency {
229 self.collection.location().drop_consistency()
230 }
231 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
232 let out = self.collection.snapshot(tick, self.nondet);
233 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
234 out
235 }
236}
237
238impl<'a, T, L: Location<'a>, B: Boundedness> Slicable<'a, L::DropConsistency>
239 for Default<crate::live_collections::Optional<T, L, B>>
240{
241 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
242 type Backtrace = crate::compile::ir::backtrace::Backtrace;
243
244 fn get_location(&self) -> L::DropConsistency {
245 self.collection.location().drop_consistency()
246 }
247 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
248 let out = self.collection.snapshot(tick, self.nondet);
249 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
250 out
251 }
252}
253
254impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
255 Slicable<'a, L::DropConsistency>
256 for Default<crate::live_collections::KeyedStream<K, V, L, B, O, R>>
257{
258 type Slice =
259 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
260 type Backtrace = crate::compile::ir::backtrace::Backtrace;
261
262 fn get_location(&self) -> L::DropConsistency {
263 self.collection.location().drop_consistency()
264 }
265 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
266 let out = self.collection.batch(tick, self.nondet);
267 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
268 out
269 }
270}
271
272impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Unbounded>>
273 Slicable<'a, L::DropConsistency>
274 for Default<crate::live_collections::KeyedSingleton<K, V, L, B>>
275{
276 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
277 type Backtrace = crate::compile::ir::backtrace::Backtrace;
278
279 fn get_location(&self) -> L::DropConsistency {
280 self.collection.location().drop_consistency()
281 }
282 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
283 let out = self.collection.snapshot(tick, self.nondet);
284 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
285 out
286 }
287}
288
289impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
290 for Default<crate::live_collections::KeyedSingleton<K, V, L, BoundedValue>>
291{
292 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
293 type Backtrace = crate::compile::ir::backtrace::Backtrace;
294
295 fn get_location(&self) -> L::DropConsistency {
296 self.collection.location().drop_consistency()
297 }
298 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
299 let out = self.collection.batch(tick, self.nondet);
300 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
301 out
302 }
303}
304
305impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
313 Slicable<'a, L::DropConsistency> for Batch<crate::live_collections::Stream<T, L, B, O, R>>
314{
315 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
316 type Backtrace = crate::compile::ir::backtrace::Backtrace;
317
318 fn get_location(&self) -> L::DropConsistency {
319 self.collection.location().drop_consistency()
320 }
321 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
322 let out = self.collection.batch(tick, self.nondet);
323 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
324 out
325 }
326}
327
328impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
329 Slicable<'a, L::DropConsistency>
330 for Batch<crate::live_collections::KeyedStream<K, V, L, B, O, R>>
331{
332 type Slice =
333 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
334 type Backtrace = crate::compile::ir::backtrace::Backtrace;
335
336 fn get_location(&self) -> L::DropConsistency {
337 self.collection.location().drop_consistency()
338 }
339 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
340 let out = self.collection.batch(tick, self.nondet);
341 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
342 out
343 }
344}
345
346impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
347 for Batch<crate::live_collections::KeyedSingleton<K, V, L, BoundedValue>>
348{
349 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
350 type Backtrace = crate::compile::ir::backtrace::Backtrace;
351
352 fn get_location(&self) -> L::DropConsistency {
353 self.collection.location().drop_consistency()
354 }
355 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
356 let out = self.collection.batch(tick, self.nondet);
357 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
358 out
359 }
360}
361
362impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
370 for Snapshot<crate::live_collections::Singleton<T, L, B>>
371{
372 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
373 type Backtrace = crate::compile::ir::backtrace::Backtrace;
374
375 fn get_location(&self) -> L::DropConsistency {
376 self.collection.location().drop_consistency()
377 }
378 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
379 let out = self.collection.snapshot(tick, self.nondet);
380 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
381 out
382 }
383}
384
385impl<'a, T, L: Location<'a>, B: Boundedness> Slicable<'a, L::DropConsistency>
386 for Snapshot<crate::live_collections::Optional<T, L, B>>
387{
388 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
389 type Backtrace = crate::compile::ir::backtrace::Backtrace;
390
391 fn get_location(&self) -> L::DropConsistency {
392 self.collection.location().drop_consistency()
393 }
394 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
395 let out = self.collection.snapshot(tick, self.nondet);
396 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
397 out
398 }
399}
400
401impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Unbounded>>
402 Slicable<'a, L::DropConsistency>
403 for Snapshot<crate::live_collections::KeyedSingleton<K, V, L, B>>
404{
405 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
406 type Backtrace = crate::compile::ir::backtrace::Backtrace;
407
408 fn get_location(&self) -> L::DropConsistency {
409 self.collection.location().drop_consistency()
410 }
411 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
412 let out = self.collection.snapshot(tick, self.nondet);
413 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
414 out
415 }
416}
417
418impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
423 Slicable<'a, L::DropConsistency>
424 for Atomic<crate::live_collections::Stream<T, crate::location::Atomic<L>, B, O, R>>
425{
426 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
427 type Backtrace = crate::compile::ir::backtrace::Backtrace;
428 fn get_location(&self) -> L::DropConsistency {
429 self.collection.location().tick.l.drop_consistency()
430 }
431
432 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
433 let out = self.collection.batch_atomic(tick, self.nondet);
434 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
435 out
436 }
437}
438
439impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
440 for Atomic<crate::live_collections::Singleton<T, crate::location::Atomic<L>, B>>
441{
442 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
443 type Backtrace = crate::compile::ir::backtrace::Backtrace;
444 fn get_location(&self) -> L::DropConsistency {
445 self.collection.location().tick.l.drop_consistency()
446 }
447
448 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
449 let out = self.collection.snapshot_atomic(tick, self.nondet);
450 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
451 out
452 }
453}
454
455impl<'a, T, L: Location<'a>, B: Boundedness> Slicable<'a, L::DropConsistency>
456 for Atomic<crate::live_collections::Optional<T, crate::location::Atomic<L>, B>>
457{
458 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
459 type Backtrace = crate::compile::ir::backtrace::Backtrace;
460 fn get_location(&self) -> L::DropConsistency {
461 self.collection.location().tick.l.drop_consistency()
462 }
463
464 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
465 let out = self.collection.snapshot_atomic(tick, self.nondet);
466 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
467 out
468 }
469}
470
471impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
472 Slicable<'a, L::DropConsistency>
473 for Atomic<crate::live_collections::KeyedStream<K, V, crate::location::Atomic<L>, B, O, R>>
474{
475 type Slice =
476 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
477 type Backtrace = crate::compile::ir::backtrace::Backtrace;
478 fn get_location(&self) -> L::DropConsistency {
479 self.collection.location().tick.l.drop_consistency()
480 }
481
482 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
483 let out = self.collection.batch_atomic(tick, self.nondet);
484 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
485 out
486 }
487}
488
489impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Unbounded>>
490 Slicable<'a, L::DropConsistency>
491 for Atomic<crate::live_collections::KeyedSingleton<K, V, crate::location::Atomic<L>, B>>
492{
493 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
494 type Backtrace = crate::compile::ir::backtrace::Backtrace;
495 fn get_location(&self) -> L::DropConsistency {
496 self.collection.location().tick.l.drop_consistency()
497 }
498
499 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
500 let out = self.collection.snapshot_atomic(tick, self.nondet);
501 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
502 out
503 }
504}
505
506impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
507 for Atomic<
508 crate::live_collections::KeyedSingleton<K, V, crate::location::Atomic<L>, BoundedValue>,
509 >
510{
511 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
512 type Backtrace = crate::compile::ir::backtrace::Backtrace;
513 fn get_location(&self) -> L::DropConsistency {
514 self.collection.location().tick.l.drop_consistency()
515 }
516
517 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
518 let out = self.collection.batch_atomic(tick, self.nondet);
519 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
520 out
521 }
522}