gc_sequence/
sequence_result_ext.rs

1use gc_arena::{Collect, MutationContext};
2
3use crate::{
4    and_then::{AndThen, AndThenWith},
5    flatten_result::FlattenOk,
6    map_result::{MapError, MapOk, MapOkWith},
7    Sequence,
8};
9
10/// Extension trait for `Sequences` producing a `Result` that provides useful combinator methods.
11pub trait SequenceResultExt<'gc, I, E>: Sized + Sequence<'gc, Output = Result<I, E>> {
12    /// Map a function over the result of this sequence if it is successful.
13    ///
14    /// Similarly to `SequenceExt::map`, this function is run in the same call to `Sequence::step`.
15    fn map_ok<F, R>(self, f: F) -> MapOk<Self, F>
16    where
17        F: 'static + FnOnce(I) -> R,
18    {
19        MapOk::new(self, f)
20    }
21
22    /// Equivalent to `SequenceResultExt::map_ok`, but takes a context parameter.
23    fn map_ok_with<C, F, R>(self, c: C, f: F) -> MapOkWith<Self, C, F>
24    where
25        F: 'static + FnOnce(C, I) -> R,
26    {
27        MapOkWith::new(self, c, f)
28    }
29
30    /// Map a function over the error result of this sequence, if it errors.
31    ///
32    /// Similarly to `SequenceExt::map`, this function is run in the same call to `Sequence::step`.
33    fn map_err<F, R>(self, f: F) -> MapError<Self, F>
34    where
35        F: 'static + FnOnce(E) -> R,
36    {
37        MapError::new(self, f)
38    }
39
40    /// Execute another sequence step after this sequence completes successfully.
41    ///
42    /// Similar to `SequenceExt::then` but only calls the given function when this sequence
43    /// completes successfully.
44    fn and_then<F, R>(self, f: F) -> AndThen<Self, F, I>
45    where
46        I: Collect,
47        F: 'static + FnOnce(MutationContext<'gc, '_>, I) -> Result<R, E>,
48    {
49        AndThen::new(self, f)
50    }
51
52    /// Equivalent to `SequenceResultExt::and_then`, but calls the function with the given context
53    /// parameter.
54    fn and_then_with<C, F, R>(self, c: C, f: F) -> AndThenWith<Self, C, F, I>
55    where
56        C: Collect,
57        I: Collect,
58        F: 'static + FnOnce(MutationContext<'gc, '_>, C, I) -> Result<R, E>,
59    {
60        AndThenWith::new(self, c, f)
61    }
62
63    /// Call a function on the result of this sequence, producing a new sequence to run.
64    ///
65    /// Similar to `SequenceExt::chain` but only calls the given function when this sequence
66    /// completes successfully.
67    fn and_chain<F, R, I2>(self, f: F) -> FlattenOk<AndThen<Self, F, I>, R>
68    where
69        I: Collect,
70        F: 'static + FnOnce(MutationContext<'gc, '_>, I) -> Result<R, E>,
71        R: Sequence<'gc, Output = Result<I2, E>>,
72    {
73        FlattenOk::new(AndThen::new(self, f))
74    }
75
76    /// Equivalent to `SequenceResultExt::and_then`, but calls the function with the given context
77    /// parameter.
78    fn and_chain_with<C, F, R, I2>(self, c: C, f: F) -> FlattenOk<AndThenWith<Self, C, F, I>, R>
79    where
80        C: Collect,
81        I: Collect,
82        F: 'static + FnOnce(MutationContext<'gc, '_>, C, I) -> Result<R, E>,
83        R: Sequence<'gc, Output = Result<I2, E>>,
84    {
85        FlattenOk::new(AndThenWith::new(self, c, f))
86    }
87
88    /// Similar to `SequenceExt::flatten`, but this sequence must result in an `Ok(next_sequence)`.
89    fn flatten_ok<I2>(self) -> FlattenOk<Self, I>
90    where
91        I: Sequence<'gc, Output = Result<I2, E>>,
92    {
93        FlattenOk::new(self)
94    }
95}
96
97impl<'gc, T, I, E> SequenceResultExt<'gc, I, E> for T where T: Sequence<'gc, Output = Result<I, E>> {}