1use std::marker::PhantomData;
2
3use std::ops::{Add, Sub};
4
5use Construct;
6use space::Space;
7
8pub struct Either<T, U>(PhantomData<T>, PhantomData<U>);
10
11#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
13pub enum Select<T, U> {
14 Fst(T),
16 Snd(U),
18}
19
20impl<T, U> Construct for Either<T, U> {
21 fn new() -> Self { Either(PhantomData, PhantomData) }
22}
23
24impl<T, U, N> Space<N> for Either<T, U>
25 where T: Space<N>,
26 U: Space<N>,
27 N: Add<Output = N> +
28 Sub<Output = N> +
29 PartialOrd,
30{
31 type Dim = (T::Dim, U::Dim);
32 type Pos = Select<T::Pos, U::Pos>;
33 fn count(&self, &(ref dim_t, ref dim_u): &Self::Dim) -> N {
34 let t: T = Construct::new();
35 let u: U = Construct::new();
36 t.count(dim_t) + u.count(dim_u)
37 }
38 fn zero(&self, &(ref dim_t, _): &Self::Dim) -> Self::Pos {
39 let t: T = Construct::new();
40 Select::Fst(t.zero(dim_t))
41 }
42 fn to_index(
43 &self,
44 &(ref dim_t, ref dim_u): &Self::Dim,
45 s: &Self::Pos
46 ) -> N {
47 let t: T = Construct::new();
48 let u: U = Construct::new();
49 match *s {
50 Select::Fst(ref pt) => {
51 t.to_index(dim_t, pt)
52 }
53 Select::Snd(ref pu) => {
54 let count = t.count(dim_t);
55 count + u.to_index(dim_u, pu)
56 }
57 }
58 }
59 fn to_pos(
60 &self,
61 &(ref dim_t, ref dim_u): &Self::Dim,
62 ind: N,
63 pos: &mut Self::Pos,
64 ) {
65 let t: T = Construct::new();
66 let u: U = Construct::new();
67 let count = t.count(dim_t);
68 if ind < count {
69 let mut zero = t.zero(dim_t);
70 t.to_pos(dim_t, ind, &mut zero);
71 *pos = Select::Fst(zero)
72 } else {
73 let mut zero = u.zero(dim_u);
74 u.to_pos(dim_u, ind - count, &mut zero);
75 *pos = Select::Snd(zero)
76 }
77 }
78}