1use std::any::{Any, TypeId};
2use std::mem::transmute;
3
4#[derive(Default, Copy, Clone)]
5pub struct Dynum;
6
7pub trait DynumAdd<N: Any> {
8 type Next;
9 fn add(self, x: N) -> Self::Next;
10}
11
12pub trait DynumGet {
13 fn get<X: Any>(&self) -> &X;
14 fn get_mut<X: Any>(&mut self) -> &mut X;
15}
16
17#[derive(Default)]
18pub struct DynumPair<T: Any, N: DynumGet + Any> {
19 head: T,
20 next: N,
21}
22
23impl<U: DynumGet + Any, N: Any> DynumAdd<N> for U {
24 type Next = DynumPair<N, Self>;
25 #[inline(always)]
26 fn add(self, x: N) -> Self::Next {
27 DynumPair {
28 head: x,
29 next: self,
30 }
31 }
32}
33
34impl<T: Any, U: DynumGet + Any> DynumGet for DynumPair<T, U> {
35 #[inline(always)]
36 fn get<X: Any>(&self) -> &X {
37 let (tid, xid): (u64, u64) = unsafe { transmute((TypeId::of::<T>(), TypeId::of::<X>())) };
38 if tid == xid {
39 unsafe { transmute(&self.head) }
40 } else {
41 self.next.get::<X>()
42 }
43 }
44 #[inline(always)]
45 fn get_mut<X: Any>(&mut self) -> &mut X {
46 let (tid, xid): (u64, u64) = unsafe { transmute((TypeId::of::<T>(), TypeId::of::<X>())) };
47 if tid == xid {
48 unsafe { transmute(&mut self.head) }
49 } else {
50 self.next.get_mut::<X>()
51 }
52 }
53}
54
55impl DynumGet for Dynum {
56 #[inline(always)]
57 fn get<X: Any>(&self) -> &X {
58 panic!("get: Unregistered type")
59 }
60 #[inline(always)]
61 fn get_mut<X: Any>(&mut self) -> &mut X {
62 panic!("get_mut: Unregistered type")
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 #[test]
70 fn it_works() {
71 let a = Dynum.add(0u32).add(2i32);
72 assert_eq!(a.get::<i32>(), &2);
73 }
74
75 #[test]
76 #[should_panic]
77 fn it_panics() {
78 let a = Dynum.add(0u32).add(2i32);
79 a.get::<i64>();
80 }
81}