gc_sequence/
then.rs

1use gc_arena::{Collect, MutationContext, StaticCollect};
2
3use crate::Sequence;
4
5#[must_use = "sequences do nothing unless stepped"]
6#[derive(Debug, Collect)]
7#[collect(no_drop)]
8pub enum Then<'gc, S, F>
9where
10    S: Sequence<'gc>,
11{
12    First(S, Option<StaticCollect<F>>),
13    Second(Option<(S::Output, StaticCollect<F>)>),
14}
15
16impl<'gc, S, F> Then<'gc, S, F>
17where
18    S: Sequence<'gc>,
19{
20    pub fn new(s: S, f: F) -> Then<'gc, S, F> {
21        Then::First(s, Some(StaticCollect(f)))
22    }
23}
24
25impl<'gc, S, F, R> Sequence<'gc> for Then<'gc, S, F>
26where
27    S: Sequence<'gc>,
28    S::Output: Collect,
29    F: 'static + FnOnce(MutationContext<'gc, '_>, S::Output) -> R,
30{
31    type Output = R;
32
33    fn step(&mut self, mc: MutationContext<'gc, '_>) -> Option<R> {
34        match self {
35            Then::First(seq, f) => match seq.step(mc) {
36                Some(res) => {
37                    *self = Then::Second(Some((res, f.take().unwrap())));
38                    None
39                }
40                None => None,
41            },
42            Then::Second(sec) => {
43                let (res, f) = sec.take().expect("cannot step a finished sequence");
44                Some(f.0(mc, res))
45            }
46        }
47    }
48}
49
50#[must_use = "sequences do nothing unless stepped"]
51#[derive(Debug, Collect)]
52#[collect(no_drop)]
53pub enum ThenWith<'gc, S, C, F>
54where
55    S: Sequence<'gc>,
56{
57    First(S, Option<(C, StaticCollect<F>)>),
58    Second(Option<(C, S::Output, StaticCollect<F>)>),
59}
60
61impl<'gc, S, C, F> ThenWith<'gc, S, C, F>
62where
63    S: Sequence<'gc>,
64{
65    pub fn new(s: S, c: C, f: F) -> ThenWith<'gc, S, C, F> {
66        ThenWith::First(s, Some((c, StaticCollect(f))))
67    }
68}
69
70impl<'gc, S, C, F, R> Sequence<'gc> for ThenWith<'gc, S, C, F>
71where
72    S: Sequence<'gc>,
73    S::Output: Collect,
74    C: Collect,
75    F: 'static + FnOnce(MutationContext<'gc, '_>, C, S::Output) -> R,
76{
77    type Output = R;
78
79    fn step(&mut self, mc: MutationContext<'gc, '_>) -> Option<R> {
80        match self {
81            ThenWith::First(seq, cf) => match seq.step(mc) {
82                Some(res) => {
83                    let (c, f) = cf.take().unwrap();
84                    *self = ThenWith::Second(Some((c, res, f)));
85                    None
86                }
87                None => None,
88            },
89            ThenWith::Second(sec) => {
90                let (c, res, f) = sec.take().expect("cannot step a finished sequence");
91                Some(f.0(mc, c, res))
92            }
93        }
94    }
95}