lang_extension/any/
value.rs

1use 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}