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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use mio::Ready;
use void::{Void, unreachable};

use {Machine, Scope, Response};


/// Composes two state machines
///
/// Used to "mount" two different application into single main loop, or to
/// use multiple protocols simultaneously. Can be nested to any level.
///
/// We will probably implement n > 2 composition later, for effeciency
/// reasons.
pub enum Compose2<A:Sized, B:Sized> {
    A(A),
    B(B),
}

pub enum Compose2Seed<A:Sized, B:Sized> {
    As(A),
    Bs(B),
}

impl<X, AA, BB> Machine for Compose2<AA, BB>
    where AA: Machine<Context=X>, BB:Machine<Context=X>
{
    type Context = X;
    type Seed = Compose2Seed<AA::Seed, BB::Seed>;

    fn create(seed: Self::Seed, scope: &mut Scope<X>)
        -> Response<Self, Void>
    {
        use Compose2::*;
        use self::Compose2Seed::*;
        match seed {
            As(s) => AA::create(s, scope).map(A, |x| unreachable(x)),
            Bs(s) => BB::create(s, scope).map(B, |x| unreachable(x)),
        }
    }
    fn ready(self, events: Ready, scope: &mut Scope<X>)
        -> Response<Self, Self::Seed>
    {
        use Compose2::*;
        use self::Compose2Seed::*;
        match self {
            A(m) => { m.ready(events, scope).map(A, As) }
            B(m) => { m.ready(events, scope).map(B, Bs) }
        }
    }
    fn spawned(self, scope: &mut Scope<X>) -> Response<Self, Self::Seed>
    {
        use Compose2::*;
        use self::Compose2Seed::*;
        match self {
            A(m) => { m.spawned(scope).map(A, As) }
            B(m) => { m.spawned(scope).map(B, Bs) }
        }
    }
    fn timeout(self, scope: &mut Scope<X>) -> Response<Self, Self::Seed> {
        use Compose2::*;
        use self::Compose2Seed::*;
        match self {
            A(m) => { m.timeout(scope).map(A, As) }
            B(m) => { m.timeout(scope).map(B, Bs) }
        }
    }
    fn wakeup(self, scope: &mut Scope<X>) -> Response<Self, Self::Seed> {
        use Compose2::*;
        use self::Compose2Seed::*;
        match self {
            A(m) => { m.wakeup(scope).map(A, As) }
            B(m) => { m.wakeup(scope).map(B, Bs) }
        }
    }
}