Coverage Report

Created: 2024-02-20 21:15

/builds/xfbs/cindy/common/src/cache/key.rs
Line
Count
Source (jump to first uncovered line)
1
use super::Invalidatable;
2
use std::{any::Any, cmp::Ordering, fmt::Debug};
3
4
pub trait CacheKey<M = ()>: Debug + Invalidatable<M> + 'static {
5
    fn any(&self) -> &(dyn Any + 'static);
6
    fn any_eq(&self, other: &dyn Any) -> bool;
7
    fn any_ord(&self, other: &dyn Any) -> Ordering;
8
    fn clone_boxed(&self) -> Box<dyn CacheKey>;
9
}
10
11
impl PartialOrd<Self> for dyn CacheKey {
12
0
    fn partial_cmp(&self, other: &dyn CacheKey) -> Option<Ordering> {
13
0
        Some(self.any_ord(other.any()))
14
0
    }
15
}
16
17
impl PartialEq<Self> for dyn CacheKey {
18
6
    fn eq(&self, other: &dyn CacheKey) -> bool {
19
6
        self.any_eq(other.any())
20
6
    }
21
}
22
23
impl Eq for dyn CacheKey {}
24
25
impl Ord for dyn CacheKey {
26
1
    fn cmp(&self, other: &dyn CacheKey) -> Ordering {
27
1
        self.any_ord(other.any())
28
1
    }
29
}
30
31
impl Clone for Box<dyn CacheKey> {
32
0
    fn clone(&self) -> Self {
33
0
        self.clone_boxed()
34
0
    }
35
}
36
37
impl<M, T: Debug + Eq + Ord + Any + Clone + Invalidatable<M> + 'static> CacheKey<M> for T {
38
10
    fn any_eq(&self, other: &dyn Any) -> bool {
39
10
        match other.downcast_ref::<T>() {
40
9
            Some(other) => {
41
9
                println!("Using eq: {}", std::any::type_name::<T>());
42
9
                self.eq(other)
43
            }
44
1
            None => false,
45
        }
46
10
    }
47
48
1
    fn any_ord(&self, other: &dyn Any) -> Ordering {
49
1
        match self.type_id().cmp(&other.type_id()) {
50
1
            Ordering::Equal => match <dyn Any>::downcast_ref::<T>(other) {
51
1
                Some(other) => self.cmp(other),
52
0
                None => unreachable!(),
53
            },
54
0
            ordering => ordering,
55
        }
56
1
    }
57
58
7
    fn any(&self) -> &(dyn Any + 'static) {
59
7
        self as &(dyn Any + 'static)
60
7
    }
61
62
0
    fn clone_boxed(&self) -> Box<dyn CacheKey> {
63
0
        Box::new(self.clone())
64
0
    }
65
}
66
67
#[cfg(test)]
68
mod tests {
69
    use super::*;
70
    use std::collections::BTreeMap;
71
72
1
    #[test]
73
1
    fn cache_item_eq_identity() {
74
1
        let string: Box<dyn CacheKey> = Box::new(String::from("Hello"));
75
1
        assert_eq!(string.any_eq(&string), true);
76
1
        assert!(&string == &string);
77
1
    }
78
79
1
    #[test]
80
1
    fn cache_item_eq_equal() {
81
1
        println!("Running test");
82
1
        let string1: Box<dyn CacheKey> = Box::new(String::from("Hello"));
83
1
        let string2: Box<dyn CacheKey> = Box::new(String::from("Hello"));
84
1
        assert_eq!(string1.any_eq(&string2), true);
85
1
        assert!(&string1 == &string2);
86
1
    }
87
88
1
    #[test]
89
1
    fn cache_item_new_different() {
90
1
        let string_hello: Box<dyn CacheKey> = Box::new(String::from("Hello"));
91
1
        let string_world: Box<dyn CacheKey> = Box::new(String::from("World"));
92
1
        assert_eq!(string_hello.any_eq(&string_world), false);
93
1
    }
94
95
1
    #[test]
96
1
    fn cache_item_different_type() {
97
1
        let string_hello: Box<dyn CacheKey> = Box::new(String::from("Hello"));
98
1
        let array_empty: Box<dyn CacheKey> = Box::new(Vec::<usize>::new());
99
1
        assert_eq!(string_hello.any_eq(&array_empty), false);
100
1
    }
101
102
1
    #[test]
103
1
    fn test_cache_key() {
104
1
        let mut map: BTreeMap<Box<dyn CacheKey>, &str> = Default::default();
105
1
        map.insert(Box::new(String::from("Hello")), "String Hello");
106
1
        map.insert(Box::new(String::from("World")), "String World");
107
1
    }
108
}