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
use std::any::{Any, TypeId}; use std::mem::transmute; #[derive(Default, Copy, Clone)] pub struct Dynum; pub trait DynumAdd<N: Any> { type Next; fn add(self, x: N) -> Self::Next; } pub trait DynumGet { fn get<X: Any>(&self) -> &X; fn get_mut<X: Any>(&mut self) -> &mut X; } #[derive(Default)] pub struct DynumPair<T: Any, N: DynumGet + Any> { head: T, next: N, } impl<U: DynumGet + Any, N: Any> DynumAdd<N> for U { type Next = DynumPair<N, Self>; #[inline(always)] fn add(self, x: N) -> Self::Next { DynumPair { head: x, next: self, } } } impl<T: Any, U: DynumGet + Any> DynumGet for DynumPair<T, U> { #[inline(always)] fn get<X: Any>(&self) -> &X { let (tid, xid): (u64, u64) = unsafe { transmute((TypeId::of::<T>(), TypeId::of::<X>())) }; if tid == xid { unsafe { transmute(&self.head) } } else { self.next.get::<X>() } } #[inline(always)] fn get_mut<X: Any>(&mut self) -> &mut X { let (tid, xid): (u64, u64) = unsafe { transmute((TypeId::of::<T>(), TypeId::of::<X>())) }; if tid == xid { unsafe { transmute(&mut self.head) } } else { self.next.get_mut::<X>() } } } impl DynumGet for Dynum { #[inline(always)] fn get<X: Any>(&self) -> &X { panic!("get: Unregistered type") } #[inline(always)] fn get_mut<X: Any>(&mut self) -> &mut X { panic!("get_mut: Unregistered type") } } #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { let a = Dynum.add(0u32).add(2i32); assert_eq!(a.get::<i32>(), &2); } #[test] #[should_panic] fn it_panics() { let a = Dynum.add(0u32).add(2i32); a.get::<i64>(); } }