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}