1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use std::marker::PhantomData;
use {IntoTransaction, Transaction};
pub fn loop_fn<Ctx, S, T, F, A>(initial_state: S, f: F) -> LoopFn<Ctx, F, A>
where
A: IntoTransaction<Ctx, Item = Loop<S, T>>,
F: Fn(S) -> A,
{
LoopFn {
tx: f(initial_state).into_transaction(),
f: f,
_phantom: PhantomData,
}
}
#[derive(Debug)]
#[must_use]
pub struct LoopFn<Ctx, F, A: IntoTransaction<Ctx>> {
tx: A::Tx,
f: F,
_phantom: PhantomData<(Ctx)>,
}
#[derive(Debug)]
pub enum Loop<S, T> {
Break(T),
Continue(S),
}
impl<Ctx, S, T, F, A> Transaction for LoopFn<Ctx, F, A>
where
F: Fn(S) -> A,
A: IntoTransaction<Ctx, Item = Loop<S, T>>,
{
type Ctx = Ctx;
type Item = T;
type Err = A::Err;
fn run(&self, ctx: &mut Self::Ctx) -> Result<Self::Item, Self::Err> {
let LoopFn { ref tx, ref f, .. } = *self;
let mut ret = tx.run(ctx)?;
loop {
let s = match ret {
Loop::Break(t) => return Ok(t),
Loop::Continue(s) => s,
};
ret = f(s).into_transaction().run(ctx)?;
}
}
}