inc_complete/
value.rs

1use std::any::Any;
2use std::hash::{Hash, Hasher};
3
4use crate::db_handle::DbHandle;
5
6pub trait Run: Sized {
7    fn run(self, db: &mut DbHandle<Self>) -> Value;
8}
9
10pub struct Value(Box<dyn ValueTrait>);
11
12impl Value {
13    pub fn new(obj: impl ValueTrait) -> Value {
14        Value(Box::new(obj))
15    }
16
17    pub fn downcast_obj_ref<T: 'static>(&self) -> Option<&T> {
18        let obj = self.0.as_ref() as &dyn Any;
19        obj.downcast_ref()
20    }
21}
22
23impl std::fmt::Debug for Value {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        write!(f, "(Value)")
26    }
27}
28
29impl HashEqObj for Value {
30    fn hash_value(&self, hasher: &mut std::hash::DefaultHasher) {
31        self.0.hash_value(hasher);
32    }
33
34    fn eq_value(&self, other: &dyn ValueTrait) -> bool {
35        self.0.eq_value(other)
36    }
37}
38
39impl Eq for Value {}
40
41impl PartialEq for Value {
42    fn eq(&self, other: &Self) -> bool {
43        self.0.as_ref().eq_value(other.0.as_ref())
44    }
45}
46
47impl<T: ValueTrait> From<T> for Value {
48    fn from(value: T) -> Self {
49        Self::new(value)
50    }
51}
52
53pub trait ValueTrait: Any + HashEqObj {}
54
55pub trait HashEqObj {
56    /// Object-safe hash
57    fn hash_value(&self, hasher: &mut std::hash::DefaultHasher);
58
59    /// Object-safe Eq
60    fn eq_value(&self, other: &dyn ValueTrait) -> bool;
61
62    fn get_hash(&self) -> u64 {
63        let mut hasher = std::hash::DefaultHasher::default();
64        self.hash_value(&mut hasher);
65        hasher.finish()
66    }
67}
68
69impl<T> ValueTrait for T where T: Any + Hash + Eq {}
70
71impl<T> HashEqObj for T where T: Any + Hash + Eq {
72    fn hash_value(&self, hasher: &mut std::hash::DefaultHasher) {
73        self.hash(hasher);
74    }
75
76    fn eq_value(&self, other: &dyn ValueTrait) -> bool {
77        let Some(other) = (other as &dyn Any).downcast_ref() else {
78            return false;
79        };
80        self == other
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::Value;
87
88    #[test]
89    fn dyn_eq() {
90        let i32_0 = Value::new(0i32);
91        let i32_1 = Value::new(1i32);
92        let u32_0 = Value::new(0u32);
93
94        assert_eq!(i32_0, i32_0, "i32_0 == i32_0");
95        assert_ne!(i32_0, i32_1, "i32_0 == i32_1");
96        assert_ne!(i32_0, u32_0, "i32_0 == u32_0");
97        assert_eq!(i32_0, Value::new(0i32), "i32_0 == fresh i32_0");
98    }
99}