1use better_any::{Tid, TidExt};
2
3pub trait ShareableTid<'a>: Tid<'a> + Send + Sync {}
7
8impl<'a, T: Tid<'a> + Send + Sync> ShareableTid<'a> for T {}
9
10pub enum Data<'ty, 'r> {
14 Owned(Box<dyn ShareableTid<'ty>>),
15 Borrowed(&'r dyn ShareableTid<'ty>),
16 Mut(&'r mut dyn ShareableTid<'ty>),
17}
18
19impl<'ty, 'r> Data<'ty, 'r> {
20 pub fn downcast_ref<'b, T: Tid<'ty>>(&'b self) -> Option<&'b T> {
22 match self {
23 Data::Owned(value) => (**value).downcast_ref(),
24 Data::Borrowed(value) => (*value).downcast_ref(),
25 Data::Mut(value) => (*value).downcast_ref(),
26 }
27 }
28
29 pub fn downcast_mut<'b, T: Tid<'ty>>(&'b mut self) -> Option<&'b mut T> {
31 match self {
32 Data::Owned(value) => (**value).downcast_mut(),
33 Data::Mut(value) => (*value).downcast_mut(),
34 _ => None,
35 }
36 }
37
38 pub fn into_owned<T: Clone + Tid<'ty>>(self) -> Result<T, Self> {
42 match self {
43 Data::Owned(value) => match value.downcast_box::<T>() {
44 Ok(value) => Ok(*value),
45 Err(v) => Err(Data::Owned(v)),
46 },
47 Data::Borrowed(value) => match value.downcast_ref::<T>() {
48 Some(value) => Ok(value.clone()),
49 None => Err(Data::Borrowed(value)),
50 },
51 Data::Mut(value) => match value.downcast_ref::<T>() {
52 Some(value) => Ok(value.clone()),
53 None => Err(Data::Mut(value)),
54 },
55 }
56 }
57
58 pub fn try_take_owned<T: Tid<'ty>>(self) -> Result<T, Self> {
62 match self {
63 Data::Owned(value) => match value.downcast_box::<T>() {
64 Ok(value) => Ok(*value),
65 Err(v) => Err(Data::Owned(v)),
66 },
67 _ => Err(self),
68 }
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use better_any::tid;
75
76 use super::*;
77
78 #[derive(Debug, Clone)]
79 struct Test;
80 tid!(Test);
81
82 #[test]
83 fn test_data_owned() {
84 let mut owned = Data::Owned(Box::new(Test));
85
86 let _ = owned.downcast_ref::<Test>().unwrap();
87 let _ = owned.downcast_mut::<Test>().unwrap();
88 assert!(matches!(owned.into_owned::<Test>(), Ok(Test)));
89
90 let owned = Data::Owned(Box::new(Test));
91 assert!(matches!(owned.try_take_owned::<Test>(), Ok(Test)));
92 }
93
94 #[test]
95 fn test_data_ref() {
96 let test = Test;
97 let mut borrowed = Data::Borrowed(&test);
98
99 let _ = borrowed.downcast_ref::<Test>().unwrap();
100 assert!(borrowed.downcast_mut::<Test>().is_none());
101 assert!(matches!(borrowed.into_owned::<Test>(), Ok(Test)));
102
103 let borrowed = Data::Borrowed(&test);
104 assert!(matches!(borrowed.try_take_owned::<Test>(), Err(_)));
105 }
106
107 #[test]
108 fn test_data_mut() {
109 let mut test = Test;
110 let mut mut_ref = Data::Mut(&mut test);
111
112 let _ = mut_ref.downcast_ref::<Test>().unwrap();
113 let _ = mut_ref.downcast_mut::<Test>().unwrap();
114 assert!(matches!(mut_ref.into_owned::<Test>(), Ok(Test)));
115
116 let mut_ref = Data::Mut(&mut test);
117 assert!(matches!(mut_ref.try_take_owned::<Test>(), Err(_)));
118 }
119
120 #[test]
121 fn test_into_owned_wrong_type() {
122 #[derive(Debug, Clone)]
123 struct Other;
124 tid!(Other);
125
126 let data = Data::Owned(Box::new(Test));
127 assert!(matches!(data.into_owned::<Other>(), Err(_)));
128 }
129}