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
//! This is an implementation of variadic templates using recursive generics.
//! It functions something like a TypeMap, but the optimizer should make getting
//! and adding values much faster.

use std::any::{Any, TypeId};
use std::mem;

pub trait Key {
    type Value: Any;
}

/// The building block trait for recursive variadics.
pub trait RecursiveVariadic {
    /// Try to get the value for N.
    fn get<N: Key>(&self) -> Option<&N::Value>;
    /// Try to get the value for N mutably.
    fn get_mut<N: Key>(&mut self) -> Option<&mut N::Value>;
    /// Add a key-value pair to this.
    fn and<N: Key>(self, val: N::Value) -> Entry<N, Self> where Self: Sized {
        Entry {
            data: val,
            parent: self,
        }
    }
    /// Add the default value for N
    fn and_default<N: Key>(self) -> Entry<N, Self> 
    where N::Value: Default, Self: Sized {
        self.and(N::Value::default())
    }
}

/// The base case for recursive variadics: no fields.
pub type Empty = ();
impl RecursiveVariadic for Empty {
    fn get<N: Key>(&self) -> Option<&N::Value> { None }
    fn get_mut<N: Key>(&mut self) -> Option<&mut N::Value> { None }
}

/// Wraps some field data and a parent, which is either another Entry or Empty
pub struct Entry<T: Key, R> {
    data: T::Value,
    parent: R,
}

impl<T: Key, R: RecursiveVariadic> RecursiveVariadic for Entry<T, R> {
    fn get<N: Key>(&self) -> Option<&N::Value> { 
        if TypeId::of::<N::Value>() == TypeId::of::<T::Value>() {
            Some(unsafe { mem::transmute(&self.data) })
        } else {
            self.parent.get::<N>()
        }
    }
    fn get_mut<N: Key>(&mut self) -> Option<&mut N::Value> { 
        if TypeId::of::<N::Value>() == TypeId::of::<T::Value>() {
            Some(unsafe { mem::transmute(&mut self.data) })
        } else {
            self.parent.get_mut::<N>()
        }
    }
}

#[cfg(test)]
mod tests {
    use std::any::Any;

    use super::*;

    #[test]
    fn it_works() {
        impl Key for i32 { type Value = i32; }
        impl Key for usize { type Value = Vec<usize>; }
        impl Key for bool { type Value = bool; }
        impl Key for &'static str { type Value = &'static str; }

        let mut thing = ().and::<i32>(23).and_default::<usize>().and::<&'static str>("Hello!");
        thing.get_mut::<usize>().unwrap().push(1);
        assert!(thing.get::<i32>().is_some());
        assert!(thing.get::<&'static str>().is_some());
        assert!(thing.get::<bool>().is_none());
    }
}