lang_extension/any/
value.rs1use std::any::Any;
2use std::fmt::Debug;
3
4use super::*;
5
6pub trait ValueConstraint: PartialEq + Debug + Clone + Any {}
7
8impl<T: ?Sized + PartialEq + Debug + Clone + Any> ValueConstraint for T {}
9
10pub trait Value: Any + AnyExtension + AsAny + Debug {
11 fn equals(&self, other: &dyn Any) -> bool {
12 self.reference_equals(other)
13 }
14
15 as_trait!(Value);
16 as_boxed!(Value);
17}
18
19impl<T: ?Sized + ValueConstraint> Value for T {
20 fn equals(&self, other: &dyn Any) -> bool {
21 match other.downcast_ref::<T>() {
22 Some(r) => *self == *r,
23 None => false,
24 }
25 }
26
27 as_trait!(impl Value);
28 as_boxed!(impl Value);
29}
30
31#[macro_export]
32macro_rules! boxed_value_trait {
33 ($trait:tt) => {
34as_boxed!(impl PartialEq for $trait);
35as_boxed!(impl Clone for $trait);
36 };
37
38 ($trait:tt<$($param:tt), *>) => {
39as_boxed!(impl PartialEq for $trait<$($param), *>);
40as_boxed!(impl Clone for $trait<$($param), *>);
41 };
42
43 ($trait:tt<$($param:tt: $constraint0:tt $(+ $constraint:tt)*), *>) => {
44as_boxed!(impl PartialEq for $trait<$($param: $constraint0 $(+ $constraint)*), *>);
45as_boxed!(impl Clone for $trait<$($param: $constraint0 $(+ $constraint)*), *>);
46 };
47
48 ($trait:tt<$($param:tt: ?Sized + $constraint0:tt $(+ $constraint:tt)*), *>) => {
49as_boxed!(impl PartialEq for $trait<$($param: ?Sized + $constraint0 $(+ $constraint)*), *>);
50as_boxed!(impl Clone for $trait<$($param: ?Sized + $constraint0 $(+ $constraint)*), *>);
51 };
52
53 ($trait:tt<$($param:tt: 'static + $constraint0:tt $(+ $constraint:tt)*), *>) => {
54as_boxed!(impl PartialEq for $trait<$($param: 'static + $constraint0 $(+ $constraint)*), *>);
55as_boxed!(impl Clone for $trait<$($param: 'static + $constraint0 $(+ $constraint)*), *>);
56 };
57
58 ($trait:tt<$($param:tt: 'static + ?Sized + $constraint0:tt $(+ $constraint:tt)*), *>) => {
59as_boxed!(impl PartialEq for $trait<$($param: 'static + ?Sized + $constraint0 $(+ $constraint)*), *>);
60as_boxed!(impl Clone for $trait<$($param: 'static + ?Sized + $constraint0 $(+ $constraint)*), *>);
61 };
62}
63
64boxed_value_trait!(Value);
65
66#[allow(dead_code)]
67#[cfg(test)]
68mod tests {
69
70 use super::*;
71
72 #[derive(PartialEq, Eq, Debug, Clone)]
73 struct S1 {
74 a: i32,
75 b: u32,
76 }
77
78 #[test]
79 fn eq() {
80 let s = S1 { a: 1, b: 2 };
81 let t: Box<dyn Value> = Box::new(s.clone());
82 let t2: Box<dyn Value> = Box::new(s.clone());
83 assert!(t == t2);
84 }
85
86 #[test]
87 fn debug() {
88 let s = S1 { a: 1, b: 2 };
89 let t: Box<dyn Value> = Box::new(s);
90 println!("{:?}", t);
91 }
92
93 #[test]
94 fn clone() {
95 let s = S1 { a: 1, b: 2 };
96 let b = s.clone_boxed();
97 assert_eq!(type_name::<S1>(), b.as_ref().type_name());
98 assert_eq!(type_name::<Box<dyn Value>>(), b.type_name());
99 assert!(s.equals(b.as_ref().as_any_ref()));
100 }
101
102 #[test]
103 fn as_trait_as_boxed() {
104 let s = S1 { a: 1, b: 2 };
105 s.as_trait_ref();
106
107 println!("{:p}", s.as_trait_ref() as &dyn Value);
108
109 let mut s = s;
110 s.as_trait_mut();
111
112 assert_eq!(&s.clone_boxed(), &s.to_boxed());
113 }
114
115 trait SomeType0<K: KeyConstraint, V: ValueConstraint>: Value {
116 fn say(&self, k: K, v: V);
117
118 as_boxed!(SomeType0<K, V>);
119 as_trait!(SomeType0<K, V>);
120 }
121
122 boxed_value_trait!(SomeType0<K: KeyConstraint, V: ValueConstraint>);
123
124 trait SomeType1<K: KeyConstraint + Debug, V: ValueConstraint>: Value {
125 fn say(&self, k: K, v: V);
126
127 as_boxed!(SomeType1<K, V>);
128 as_trait!(SomeType1<K, V>);
129 }
130
131 boxed_value_trait!(SomeType1<K: KeyConstraint + Debug, V: ValueConstraint>);
132
133 trait SomeType2<K: ?Sized + KeyConstraint, V: ?Sized + ValueConstraint>: Value {
134 fn say(&self, k: K, v: V);
135
136 as_boxed!(SomeType2<K, V>);
137 as_trait!(SomeType2<K, V>);
138 }
139
140 boxed_value_trait!(SomeType2<K: ?Sized + KeyConstraint, V: ?Sized + ValueConstraint>);
141
142 trait SomeType3<K: 'static + KeyConstraint, V: 'static + ValueConstraint>: Value {
143 fn say(&self, k: K, v: V);
144
145 as_boxed!(SomeType3<K, V>);
146 as_trait!(SomeType3<K, V>);
147 }
148
149 boxed_value_trait!(SomeType3<K: 'static + KeyConstraint, V: 'static + ValueConstraint>);
150
151 trait SomeType4<K: 'static + ?Sized + KeyConstraint, V: 'static + ?Sized + ValueConstraint>:
152 Value
153 {
154 fn say(&self, k: K, v: V);
155
156 as_boxed!(SomeType4<K, V>);
157 as_trait!(SomeType4<K, V>);
158 }
159
160 boxed_value_trait!(SomeType4<K: 'static + ?Sized + KeyConstraint, V: 'static + ?Sized + ValueConstraint>);
161}