Skip to main content

cljrs_value/collections/
sorted_map.rs

1use crate::Value;
2
3/// An immutable sorted map backed by `rpds::RedBlackTreeMapSync`.
4#[derive(Debug, Clone)]
5pub struct SortedMap {
6    inner: rpds::RedBlackTreeMapSync<Value, Value>,
7}
8
9impl SortedMap {
10    pub fn empty() -> Self {
11        Self {
12            inner: rpds::RedBlackTreeMapSync::new_sync(),
13        }
14    }
15
16    pub fn count(&self) -> usize {
17        self.inner.size()
18    }
19
20    pub fn is_empty(&self) -> bool {
21        self.inner.is_empty()
22    }
23
24    pub fn get(&self, key: &Value) -> Option<&Value> {
25        self.inner.get(key)
26    }
27
28    pub fn contains_key(&self, key: &Value) -> bool {
29        self.inner.contains_key(key)
30    }
31
32    pub fn assoc(&self, key: Value, value: Value) -> Self {
33        Self {
34            inner: self.inner.insert(key, value),
35        }
36    }
37
38    pub fn dissoc(&self, key: &Value) -> Self {
39        Self {
40            inner: self.inner.remove(key),
41        }
42    }
43
44    /// Iterate over all `(key, value)` pairs in sorted key order.
45    pub fn iter(&self) -> impl Iterator<Item = (&Value, &Value)> {
46        self.inner.iter()
47    }
48
49    pub fn keys(&self) -> Vec<Value> {
50        self.inner.keys().cloned().collect()
51    }
52
53    pub fn vals(&self) -> Vec<Value> {
54        self.inner.values().cloned().collect()
55    }
56
57    pub fn from_pairs<I: IntoIterator<Item = (Value, Value)>>(iter: I) -> Self {
58        let mut m = Self::empty();
59        for (k, v) in iter {
60            m = m.assoc(k, v);
61        }
62        m
63    }
64}
65
66impl PartialEq for SortedMap {
67    fn eq(&self, other: &Self) -> bool {
68        if self.count() != other.count() {
69            return false;
70        }
71        self.inner.iter().all(|(k, v)| other.get(k) == Some(v))
72    }
73}
74
75impl cljrs_gc::Trace for SortedMap {
76    fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
77        for (k, v) in self.inner.iter() {
78            k.trace(visitor);
79            v.trace(visitor);
80        }
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87    use crate::Value;
88
89    fn int(n: i64) -> Value {
90        Value::Long(n)
91    }
92
93    #[test]
94    fn test_basic_ops() {
95        let m = SortedMap::empty();
96        let m = m.assoc(int(3), int(30));
97        let m = m.assoc(int(1), int(10));
98        let m = m.assoc(int(2), int(20));
99        assert_eq!(m.count(), 3);
100        assert_eq!(m.get(&int(1)), Some(&int(10)));
101        assert_eq!(m.get(&int(2)), Some(&int(20)));
102        assert_eq!(m.get(&int(3)), Some(&int(30)));
103    }
104
105    #[test]
106    fn test_sorted_iteration_order() {
107        let m = SortedMap::empty()
108            .assoc(int(3), int(30))
109            .assoc(int(1), int(10))
110            .assoc(int(2), int(20));
111        let keys: Vec<Value> = m.iter().map(|(k, _)| k.clone()).collect();
112        assert_eq!(keys, vec![int(1), int(2), int(3)]);
113    }
114
115    #[test]
116    fn test_dissoc() {
117        let m = SortedMap::empty()
118            .assoc(int(1), int(10))
119            .assoc(int(2), int(20));
120        let m2 = m.dissoc(&int(1));
121        assert_eq!(m2.count(), 1);
122        assert_eq!(m2.get(&int(1)), None);
123        assert_eq!(m2.get(&int(2)), Some(&int(20)));
124    }
125}