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::optional::OptionalBound;
16use crate::live_collections::singleton::SingletonBound;
17use crate::live_collections::stream::{Ordering, Retries};
18use crate::location::Location;
19use crate::location::tick::{DeferTick, Tick};
20use crate::nondet::{NonDet, nondet};
21
22pub struct Default<T> {
27 pub(crate) collection: T,
28 pub(crate) nondet: NonDet,
29}
30
31impl<T> Default<T> {
32 pub fn new(collection: T, nondet: NonDet) -> Self {
34 Self { collection, nondet }
35 }
36}
37
38#[doc(hidden)]
40#[deprecated(
41 note = "use `use::batch(...)` for stream-like collections or `use::snapshot(...)` for singleton-like collections instead"
42)]
43pub fn default<T>(t: T, nondet: NonDet) -> Default<T> {
44 Default::new(t, nondet)
45}
46
47pub struct Batch<T, H = ()> {
51 pub(crate) collection: T,
52 pub(crate) nondet: NonDet<H>,
53}
54
55impl<T, H> Batch<T, H> {
56 pub fn new(collection: T, nondet: NonDet<H>) -> Self {
58 Self { collection, nondet }
59 }
60}
61
62pub fn batch<T, H>(t: T, nondet: NonDet<H>) -> Batch<T, H> {
67 Batch::new(t, nondet)
68}
69
70pub struct Snapshot<T, H = ()> {
74 pub(crate) collection: T,
75 pub(crate) nondet: NonDet<H>,
76}
77
78impl<T, H> Snapshot<T, H> {
79 pub fn new(collection: T, nondet: NonDet<H>) -> Self {
81 Self { collection, nondet }
82 }
83}
84
85pub fn snapshot<T, H>(t: T, nondet: NonDet<H>) -> Snapshot<T, H> {
91 Snapshot::new(t, nondet)
92}
93
94pub struct Atomic<T> {
98 pub(crate) collection: T,
99 pub(crate) nondet: NonDet,
100}
101
102impl<T> Atomic<T> {
103 pub fn new(collection: T, nondet: NonDet) -> Self {
105 Self { collection, nondet }
106 }
107}
108
109pub fn atomic<T>(t: T, nondet: NonDet) -> Atomic<T> {
111 Atomic::new(t, nondet)
112}
113
114#[cfg(stageleft_runtime)]
127pub fn state<'t, S, L>(tick: &'t Tick<L>) -> StateBuilder<'t, S, L> {
128 StateBuilder {
129 tick,
130 _phantom: PhantomData,
131 }
132}
133
134#[cfg(stageleft_runtime)]
136pub struct StateBuilder<'t, S, L> {
137 tick: &'t Tick<L>,
138 _phantom: PhantomData<S>,
139}
140
141#[cfg(stageleft_runtime)]
142impl<'t, 'a, S, L: Location<'a>> StateBuilder<'t, S, L> {
143 #[expect(
151 private_bounds,
152 reason = "only Hydro collections can implement CycleCollectionWithInitial"
153 )]
154 pub fn build(self, initial_fn: impl FnOnce(&'t Tick<L>) -> S) -> (TickCycleHandle<'a, S>, S)
155 where
156 S: CycleCollectionWithInitial<'a, TickCycle, Location = Tick<L::DropConsistency>>,
157 {
158 let initial = initial_fn(self.tick);
159 initial.location().clone().cycle_with_initial(initial)
160 }
161}
162
163#[cfg(stageleft_runtime)]
171pub fn state_null<'t, S, L>(tick: &'t Tick<L>) -> StateNullBuilder<'t, S, L> {
172 StateNullBuilder {
173 tick,
174 _phantom: PhantomData,
175 }
176}
177
178#[cfg(stageleft_runtime)]
180pub struct StateNullBuilder<'t, S, L> {
181 tick: &'t Tick<L>,
182 _phantom: PhantomData<S>,
183}
184
185#[cfg(stageleft_runtime)]
186impl<'t, 'a, S, L: Location<'a>> StateNullBuilder<'t, S, L> {
187 #[expect(
189 private_bounds,
190 reason = "only Hydro collections can implement CycleCollection"
191 )]
192 pub fn build(self) -> (TickCycleHandle<'a, S>, S)
193 where
194 S: CycleCollection<'a, TickCycle, Location = Tick<L::DropConsistency>> + DeferTick,
195 {
196 self.tick.cycle::<S, _>()
197 }
198}
199
200impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
208 Slicable<'a, L::DropConsistency> for Default<crate::live_collections::Stream<T, L, B, O, R>>
209{
210 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
211 type Backtrace = crate::compile::ir::backtrace::Backtrace;
212
213 fn get_location(&self) -> L::DropConsistency {
214 self.collection.location().drop_consistency()
215 }
216 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
217 let _ = self.nondet;
218 let out = self.collection.batch(
219 tick,
220 nondet!(),
221 );
222 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
223 out
224 }
225}
226
227impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
228 for Default<crate::live_collections::Singleton<T, L, B>>
229{
230 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
231 type Backtrace = crate::compile::ir::backtrace::Backtrace;
232
233 fn get_location(&self) -> L::DropConsistency {
234 self.collection.location().drop_consistency()
235 }
236 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
237 let _ = self.nondet;
238 let out = self.collection.snapshot(
239 tick,
240 nondet!(),
241 );
242 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
243 out
244 }
245}
246
247impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
248 for Default<crate::live_collections::Optional<T, L, B>>
249{
250 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
251 type Backtrace = crate::compile::ir::backtrace::Backtrace;
252
253 fn get_location(&self) -> L::DropConsistency {
254 self.collection.location().drop_consistency()
255 }
256 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
257 let out = self.collection.snapshot(tick, self.nondet);
258 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
259 out
260 }
261}
262
263impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
264 Slicable<'a, L::DropConsistency>
265 for Default<crate::live_collections::KeyedStream<K, V, L, B, O, R>>
266{
267 type Slice =
268 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
269 type Backtrace = crate::compile::ir::backtrace::Backtrace;
270
271 fn get_location(&self) -> L::DropConsistency {
272 self.collection.location().drop_consistency()
273 }
274 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
275 let _ = self.nondet;
276 let out = self.collection.batch(
277 tick,
278 nondet!(),
279 );
280 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
281 out
282 }
283}
284
285impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Unbounded>>
286 Slicable<'a, L::DropConsistency>
287 for Default<crate::live_collections::KeyedSingleton<K, V, L, B>>
288{
289 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
290 type Backtrace = crate::compile::ir::backtrace::Backtrace;
291
292 fn get_location(&self) -> L::DropConsistency {
293 self.collection.location().drop_consistency()
294 }
295 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
296 let _ = self.nondet;
297 let out = self.collection.snapshot(
298 tick,
299 nondet!(),
300 );
301 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
302 out
303 }
304}
305
306impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
307 for Default<crate::live_collections::KeyedSingleton<K, V, L, BoundedValue>>
308{
309 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
310 type Backtrace = crate::compile::ir::backtrace::Backtrace;
311
312 fn get_location(&self) -> L::DropConsistency {
313 self.collection.location().drop_consistency()
314 }
315 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
316 let _ = self.nondet;
317 let out = self.collection.batch(
318 tick,
319 nondet!(),
320 );
321 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
322 out
323 }
324}
325
326impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
334 Slicable<'a, L::DropConsistency>
335 for Batch<
336 crate::live_collections::Stream<T, L, B, O, R>,
337 Option<crate::sim_hooks::BatchHook<T, O, R>>,
338 >
339{
340 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
341 type Backtrace = crate::compile::ir::backtrace::Backtrace;
342
343 fn get_location(&self) -> L::DropConsistency {
344 self.collection.location().drop_consistency()
345 }
346 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
347 let out = self.collection.batch(tick, self.nondet);
348 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
349 out
350 }
351}
352
353impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
354 Slicable<'a, L::DropConsistency>
355 for Batch<
356 crate::live_collections::KeyedStream<K, V, L, B, O, R>,
357 Option<crate::sim_hooks::KeyedBatchHook<K, V, O, R>>,
358 >
359{
360 type Slice =
361 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
362 type Backtrace = crate::compile::ir::backtrace::Backtrace;
363
364 fn get_location(&self) -> L::DropConsistency {
365 self.collection.location().drop_consistency()
366 }
367 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
368 let out = self.collection.batch(tick, self.nondet);
369 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
370 out
371 }
372}
373
374impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
375 for Batch<
376 crate::live_collections::KeyedSingleton<K, V, L, BoundedValue>,
377 Option<crate::sim_hooks::KeyedSnapshotHook<K, V>>,
378 >
379{
380 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
381 type Backtrace = crate::compile::ir::backtrace::Backtrace;
382
383 fn get_location(&self) -> L::DropConsistency {
384 self.collection.location().drop_consistency()
385 }
386 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
387 let out = self.collection.batch(tick, self.nondet);
388 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
389 out
390 }
391}
392
393impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
401 for Snapshot<
402 crate::live_collections::Singleton<T, L, B>,
403 Option<crate::sim_hooks::SnapshotHook<T>>,
404 >
405{
406 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
407 type Backtrace = crate::compile::ir::backtrace::Backtrace;
408
409 fn get_location(&self) -> L::DropConsistency {
410 self.collection.location().drop_consistency()
411 }
412 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
413 let out = self.collection.snapshot(tick, self.nondet);
414 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
415 out
416 }
417}
418
419impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
420 for Snapshot<crate::live_collections::Optional<T, L, B>>
421{
422 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
423 type Backtrace = crate::compile::ir::backtrace::Backtrace;
424
425 fn get_location(&self) -> L::DropConsistency {
426 self.collection.location().drop_consistency()
427 }
428 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
429 let out = self.collection.snapshot(tick, self.nondet);
430 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
431 out
432 }
433}
434
435impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Unbounded>>
436 Slicable<'a, L::DropConsistency>
437 for Snapshot<
438 crate::live_collections::KeyedSingleton<K, V, L, B>,
439 Option<crate::sim_hooks::KeyedSnapshotHook<K, V>>,
440 >
441{
442 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
443 type Backtrace = crate::compile::ir::backtrace::Backtrace;
444
445 fn get_location(&self) -> L::DropConsistency {
446 self.collection.location().drop_consistency()
447 }
448 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
449 let out = self.collection.snapshot(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, O: Ordering, R: Retries>
460 Slicable<'a, L::DropConsistency>
461 for Atomic<crate::live_collections::Stream<T, crate::location::Atomic<L>, B, O, R>>
462{
463 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
464 type Backtrace = crate::compile::ir::backtrace::Backtrace;
465 fn get_location(&self) -> L::DropConsistency {
466 self.collection.location().tick.l.drop_consistency()
467 }
468
469 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
470 let _ = self.nondet;
471 let out = self.collection.batch_atomic(
472 tick,
473 nondet!(),
474 );
475 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
476 out
477 }
478}
479
480impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
481 for Atomic<crate::live_collections::Singleton<T, crate::location::Atomic<L>, B>>
482{
483 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
484 type Backtrace = crate::compile::ir::backtrace::Backtrace;
485 fn get_location(&self) -> L::DropConsistency {
486 self.collection.location().tick.l.drop_consistency()
487 }
488
489 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
490 let _ = self.nondet;
491 let out = self.collection.snapshot_atomic(
492 tick,
493 nondet!(),
494 );
495 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
496 out
497 }
498}
499
500impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
501 for Atomic<crate::live_collections::Optional<T, crate::location::Atomic<L>, B>>
502{
503 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
504 type Backtrace = crate::compile::ir::backtrace::Backtrace;
505 fn get_location(&self) -> L::DropConsistency {
506 self.collection.location().tick.l.drop_consistency()
507 }
508
509 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
510 let out = self.collection.snapshot_atomic(tick, self.nondet);
511 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
512 out
513 }
514}
515
516impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
517 Slicable<'a, L::DropConsistency>
518 for Atomic<crate::live_collections::KeyedStream<K, V, crate::location::Atomic<L>, B, O, R>>
519{
520 type Slice =
521 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
522 type Backtrace = crate::compile::ir::backtrace::Backtrace;
523 fn get_location(&self) -> L::DropConsistency {
524 self.collection.location().tick.l.drop_consistency()
525 }
526
527 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
528 let out = self.collection.batch_atomic(tick, self.nondet);
529 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
530 out
531 }
532}
533
534impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Unbounded>>
535 Slicable<'a, L::DropConsistency>
536 for Atomic<crate::live_collections::KeyedSingleton<K, V, crate::location::Atomic<L>, B>>
537{
538 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
539 type Backtrace = crate::compile::ir::backtrace::Backtrace;
540 fn get_location(&self) -> L::DropConsistency {
541 self.collection.location().tick.l.drop_consistency()
542 }
543
544 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
545 let out = self.collection.snapshot_atomic(tick, self.nondet);
546 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
547 out
548 }
549}
550
551impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
552 for Atomic<
553 crate::live_collections::KeyedSingleton<K, V, crate::location::Atomic<L>, BoundedValue>,
554 >
555{
556 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
557 type Backtrace = crate::compile::ir::backtrace::Backtrace;
558 fn get_location(&self) -> L::DropConsistency {
559 self.collection.location().tick.l.drop_consistency()
560 }
561
562 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
563 let out = self.collection.batch_atomic(tick, self.nondet);
564 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
565 out
566 }
567}