1#[cfg(test)]
2mod tests {
3 use super::AnyBox;
4
5 macro_rules! typed_test {
6 ($name:ident, $ty:ty, $value:expr) => {
7 #[test]
8 fn $name() {
9 let data: $ty = $value;
10 let expected: $ty = $value;
11
12 let anybox = AnyBox::new(data);
13
14 assert_eq!(anybox.get::<$ty>(), &expected);
15 assert_eq!(anybox.try_get::<()>(), None);
16 }
17 };
18 }
19
20 typed_test!(byte, u8, 1);
21 typed_test!(byte2, u8, 123);
22
23 typed_test!(usize1, usize, 1);
24 typed_test!(usize2, usize, 2);
25 typed_test!(usize3, usize, 26387890);
26 typed_test!(usize4, usize, 123789123);
27 typed_test!(usize5, usize, 3279173921873921);
28
29 typed_test!(isize1, isize, 1);
30 typed_test!(isize2, isize, 2);
31 typed_test!(isize3, isize, 26387890);
32 typed_test!(isize4, isize, 123789123);
33 typed_test!(isize5, isize, 3279173921873921);
34 typed_test!(neg_isize1, isize, -1);
35 typed_test!(neg_isize2, isize, -2);
36 typed_test!(neg_isize3, isize, -26387890);
37 typed_test!(neg_isize4, isize, -123789123);
38 typed_test!(neg_isize5, isize, -3279173921873921);
39}
40
41use std::any;
42
43pub struct AnyBox {
48 ty: any::TypeId,
49 value: Box<u8>,
52}
53
54impl AnyBox {
55 pub fn new<T: 'static>(value: T) -> Self {
56 let ty = any::TypeId::of::<T>();
57
58 let value = Box::new(value);
60 let value = unsafe { std::mem::transmute::<Box<T>, Box<u8>>(value) };
61 Self { ty, value }
62 }
63
64 pub fn try_get<'a, T: 'static>(&'a self) -> Option<&'a T> {
66 let ty = any::TypeId::of::<T>();
67
68 if ty != self.ty {
69 return None;
70 }
71
72 let value = unsafe { std::mem::transmute::<&u8, &T>(self.value.as_ref()) };
73
74 Some(value)
75 }
76
77 pub fn get<'a, T: 'static>(&'a self) -> &T {
79 match self.try_get::<T>() {
80 None => {
81 let full_name = any::type_name::<T>();
82 panic!("Attempted to take value as forgein type {}", full_name);
83 }
84 Some(t) => t,
85 }
86 }
87
88 pub fn put<T: 'static>(&mut self, value: T) {
89 let ty = any::TypeId::of::<T>();
90
91 if ty != self.ty {
92 return;
93 }
94
95 let mut value = Box::new(value);
96 {
99 let inner = self.value.as_mut();
100 let mut inner = unsafe {
101 std::mem::transmute::<&mut u8, &mut T>(inner)
102 };
103
104 std::mem::swap(value.as_mut(), &mut inner);
105 }
106 }
107}