Skip to main content

rotor_tools/
compose.rs

1//! Composition tools
2
3use rotor::mio::EventSet;
4use rotor::void::{Void, unreachable};
5use rotor::{Machine, Scope, Response};
6
7
8/// Composes two state machines where of the state machines spawns
9/// multiple instances of another one
10pub enum Spawn<S: Spawner> {
11    Spawner(S),
12    Child(S::Child),
13}
14
15pub trait Spawner {
16    type Child: Machine<Seed=Void>;
17    type Seed;
18
19    fn spawn(seed: Self::Seed,
20        scope: &mut Scope<<Self::Child as Machine>::Context>)
21        -> Response<Self::Child, Void>;
22}
23
24impl<T, C, S> Spawner for ::uniform::Uniform<T>
25    where T: Spawner<Seed=S> + ::uniform::Action<Seed=S, Context=C>
26{
27    type Child = T::Child;
28    type Seed = <T as Spawner>::Seed;
29
30    fn spawn(seed: <Self as Spawner>::Seed,
31        scope: &mut Scope<<<Self as Spawner>::Child as Machine>::Context>)
32        -> Response<Self::Child, Void>
33    {
34        T::spawn(seed, scope)
35    }
36}
37
38impl<S, C, D> Machine for Spawn<S>
39    where S: Spawner<Child=C, Seed=D> + Machine<Context=C::Context, Seed=D>,
40          C: Machine<Seed=Void>,
41{
42    type Context = <S::Child as Machine>::Context;
43    type Seed = <S as Spawner>::Seed;
44
45    fn create(seed: <S as Spawner>::Seed, scope: &mut Scope<Self::Context>)
46        -> Response<Self, Void>
47    {
48        S::spawn(seed, scope).wrap(Spawn::Child)
49    }
50    fn ready(self, events: EventSet, scope: &mut Scope<Self::Context>)
51        -> Response<Self, Self::Seed>
52    {
53        use self::Spawn::*;
54        match self {
55            Spawner(m) => { m.ready(events, scope).wrap(Spawner) }
56            Child(m) => { m.ready(events, scope)
57                           .map(Child, |x| unreachable(x)) }
58        }
59    }
60    fn spawned(self, scope: &mut Scope<Self::Context>)
61        -> Response<Self, Self::Seed>
62    {
63        use self::Spawn::*;
64        match self {
65            Spawner(m) => { m.spawned(scope).wrap(Spawner) }
66            Child(m) => { m.spawned(scope).map(Child, |x| unreachable(x)) }
67        }
68    }
69    fn timeout(self, scope: &mut Scope<Self::Context>)
70        -> Response<Self, Self::Seed>
71    {
72        use self::Spawn::*;
73        match self {
74            Spawner(m) => { m.timeout(scope).wrap(Spawner) }
75            Child(m) => { m.timeout(scope).map(Child, |x| unreachable(x)) }
76        }
77    }
78    fn wakeup(self, scope: &mut Scope<Self::Context>)
79        -> Response<Self, Self::Seed>
80    {
81        use self::Spawn::*;
82        match self {
83            Spawner(m) => { m.wakeup(scope).wrap(Spawner) }
84            Child(m) => { m.wakeup(scope).map(Child, |x| unreachable(x)) }
85        }
86    }
87}