1use crate::{Join, MetaItem, MetaTuple};
2use core::{any::Any, ptr::NonNull};
3
4pub enum ErasedInner<'t> {
6 None,
7 Any(&'t dyn Any),
8 Joined(&'t dyn MetaBox, &'t dyn MetaBox),
9}
10
11pub enum ErasedInnerMut<'t> {
13 None,
14 Any(&'t mut dyn Any),
15 Joined(&'t mut dyn MetaBox, &'t mut dyn MetaBox),
16}
17
18pub trait MetaBox {
20 fn as_erased(&self) -> ErasedInner<'_>;
21 fn as_erased_mut(&mut self) -> ErasedInnerMut<'_>;
22}
23
24impl dyn MetaBox + '_ {
25 pub fn get<T: 'static>(&self) -> Option<&T> {
29 if let Some(value) = (&() as &dyn Any).downcast_ref() {
30 return Some(value);
31 }
32 match self.as_erased() {
33 ErasedInner::None => None,
34 ErasedInner::Any(any) => any.downcast_ref(),
35 ErasedInner::Joined(a, b) => a.get().or_else(|| b.get()),
36 }
37 }
38
39 pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
43 if (&mut () as &mut dyn Any).downcast_mut::<T>().is_some() {
44 return Some(unsafe { NonNull::dangling().as_mut() });
48 }
49 match self.as_erased_mut() {
50 ErasedInnerMut::None => None,
51 ErasedInnerMut::Any(any) => any.downcast_mut(),
52 ErasedInnerMut::Joined(a, b) => a.get_mut().or_else(|| b.get_mut()),
53 }
54 }
55}
56
57impl MetaBox for () {
58 fn as_erased<'t>(&self) -> ErasedInner<'_> {
59 ErasedInner::None
60 }
61
62 fn as_erased_mut(&mut self) -> ErasedInnerMut<'_> {
63 ErasedInnerMut::None
64 }
65}
66
67impl<T: MetaBox> MetaBox for &T {
68 fn as_erased<'t>(&self) -> ErasedInner<'_> {
69 MetaBox::as_erased(*self)
70 }
71
72 fn as_erased_mut(&mut self) -> ErasedInnerMut<'_> {
73 ErasedInnerMut::None
74 }
75}
76
77impl<T: MetaBox> MetaBox for &mut T {
78 fn as_erased<'t>(&self) -> ErasedInner<'_> {
79 MetaBox::as_erased(*self)
80 }
81
82 fn as_erased_mut(&mut self) -> ErasedInnerMut<'_> {
83 MetaBox::as_erased_mut(*self)
84 }
85}
86
87impl<T: 'static> MetaBox for MetaItem<T> {
88 fn as_erased<'t>(&self) -> ErasedInner<'_> {
89 ErasedInner::Any(&self.0)
90 }
91
92 fn as_erased_mut(&mut self) -> ErasedInnerMut<'_> {
93 ErasedInnerMut::Any(&mut self.0)
94 }
95}
96
97impl<T: 'static> MetaBox for Option<T> {
98 fn as_erased<'t>(&self) -> ErasedInner<'_> {
99 match self.as_ref() {
100 Some(value) => ErasedInner::Any(value),
101 None => ErasedInner::None,
102 }
103 }
104
105 fn as_erased_mut(&mut self) -> ErasedInnerMut<'_> {
106 match self.as_mut() {
107 Some(value) => ErasedInnerMut::Any(value),
108 None => ErasedInnerMut::None,
109 }
110 }
111}
112
113impl<A: MetaTuple, B: MetaTuple> MetaBox for Join<A, B> {
114 fn as_erased<'t>(&self) -> ErasedInner<'_> {
115 ErasedInner::Joined(&self.0, &self.1)
116 }
117
118 fn as_erased_mut(&mut self) -> ErasedInnerMut<'_> {
119 ErasedInnerMut::Joined(&mut self.0, &mut self.1)
120 }
121}