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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::mem;
use std::marker::PhantomData;
use super::SessionType;
use protocol::{Channel, Protocol, Handler, Defer, DeferFunc};
pub trait Acceptor<I, E: SessionType, T>: Protocol + Sized {
fn defer<Y: SessionType>(chan: Channel<Self, I, E, Y>, usize) -> Defer<Self, I>;
}
impl<I, E: SessionType, H: Protocol + Handler<I, E, S> + Acceptor<I, E, Q>, S: SessionType, Q: SessionType> Acceptor<I, E, Accept<S, Q>> for H {
#[inline(always)]
fn defer<Y: SessionType>(chan: Channel<Self, I, E, Y>, num: usize) -> Defer<H, I> {
if num == 0 {
let next_func: DeferFunc<Self, I, E, S> = <Self as Handler<I, E, S>>::with;
Defer::new(chan, unsafe { mem::transmute(next_func) }, true)
} else {
<Self as Acceptor<I, E, Q>>::defer(chan, num - 1)
}
}
}
impl<I, E: SessionType, H: Protocol + Handler<I, E, S>, S: SessionType> Acceptor<I, E, Finally<S>> for H {
#[inline(always)]
fn defer<Y: SessionType>(chan: Channel<Self, I, E, Y>, _: usize) -> Defer<H, I> {
let next_func: DeferFunc<Self, I, E, S> = <Self as Handler<I, E, S>>::with;
Defer::new(chan, unsafe { mem::transmute(next_func) }, true)
}
}
pub struct Choose<S: SessionType, Q: SessionType>(PhantomData<(S, Q)>);
unsafe impl<S: SessionType, Q: SessionType> SessionType for Choose<S, Q> {
type Dual = Accept<S::Dual, Q::Dual>;
}
trait NotSame { }
impl NotSame for .. { }
impl<A> !NotSame for (A, A) { }
pub trait Chooser<T> {
fn num() -> usize;
}
impl<S: SessionType, Q: SessionType> Chooser<S> for Choose<S, Q> {
#[inline(always)]
fn num() -> usize { 0 }
}
impl<S: SessionType> Chooser<S> for Finally<S> {
#[inline(always)]
fn num() -> usize { 0 }
}
impl<R: SessionType, S: SessionType, Q: SessionType + Chooser<S>> Chooser<S> for Choose<R, Q>
where (S, R): NotSame
{
#[inline(always)]
fn num() -> usize { Q::num().checked_add(1).unwrap() }
}
pub struct Accept<S: SessionType, Q: SessionType>(PhantomData<(S, Q)>);
unsafe impl<S: SessionType, Q: SessionType> SessionType for Accept<S, Q> {
type Dual = Choose<S::Dual, Q::Dual>;
}
pub struct Finally<S: SessionType>(PhantomData<S>);
unsafe impl<S: SessionType> SessionType for Finally<S> {
type Dual = Finally<S::Dual>;
}
#[test]
fn check_choose_works() {
use super::{Recv, End};
type GetUsize = Recv<usize, End>;
type GetU8 = Recv<u8, End>;
type GetString = Recv<String, End>;
type Getisize = Recv<isize, End>;
type Proto = Choose<Getisize, Choose<GetString, Choose<GetU8, Finally<GetUsize>>>>;
assert_eq!(<Proto as Chooser<Getisize>>::num(), 0);
assert_eq!(<Proto as Chooser<GetString>>::num(), 1);
assert_eq!(<Proto as Chooser<GetU8>>::num(), 2);
assert_eq!(<Proto as Chooser<GetUsize>>::num(), 3);
}