Skip to main content

hara_native/lang/data/
sorted_set.rs

1use std::cell::Cell;
2
3use crate::lang::data::SortedMap;
4use crate::lang::hash::JavaHash;
5use crate::lang::protocol::{
6    HashType, IColl, IConj, ICount, IDisplay, IDissoc, IEmpty, IEquality, IFind, IHash, IMetadata,
7    IMutable, INth, IObjType, IPersistent, IToMutable, IToPersistent, ObjType,
8};
9
10#[derive(Debug, Clone)]
11pub struct Standard<E> {
12    lookup: SortedMap<E, E>,
13}
14impl<E> Default for Standard<E> {
15    fn default() -> Self {
16        Self {
17            lookup: SortedMap::default(),
18        }
19    }
20}
21impl<E: Clone + Ord> Standard<E> {
22    pub fn new() -> Self {
23        Self::default()
24    }
25    pub fn len(&self) -> usize {
26        self.lookup.len()
27    }
28    pub fn is_empty(&self) -> bool {
29        self.lookup.is_empty()
30    }
31    pub fn get(&self, value: &E) -> Option<&E> {
32        self.lookup.get(value)
33    }
34    pub fn iter(&self) -> impl Iterator<Item = &E> {
35        self.lookup.iter().map(|(key, _)| key)
36    }
37    pub fn conj_value(&self, value: E) -> Self {
38        Self {
39            lookup: self.lookup.assoc_value(value.clone(), value),
40        }
41    }
42    pub fn dissoc_value(&self, value: &E) -> Self {
43        Self {
44            lookup: self.lookup.dissoc_value(value),
45        }
46    }
47    pub fn index_of(&self, value: &E) -> Option<usize> {
48        self.lookup.index_of_key(value)
49    }
50    pub fn inclusive_floor_index(&self, value: &E) -> Option<usize> {
51        self.lookup.inclusive_floor_index(value)
52    }
53    pub fn ceil_index(&self, value: &E) -> Option<usize> {
54        self.lookup.ceil_index(value)
55    }
56    pub fn slice(&self, min: &E, max: &E) -> Self {
57        Self {
58            lookup: self.lookup.slice(min, max),
59        }
60    }
61}
62impl<E: Clone + Ord> FromIterator<E> for Standard<E> {
63    fn from_iter<T: IntoIterator<Item = E>>(it: T) -> Self {
64        it.into_iter().fold(Self::new(), |s, v| s.conj_value(v))
65    }
66}
67impl<E: Clone + Ord> ICount for Standard<E> {
68    fn count(&self) -> usize {
69        self.len()
70    }
71}
72impl<E: Clone + Ord> IFind<E> for Standard<E> {
73    type Output = E;
74    fn find(&self, k: &E) -> Option<E> {
75        self.get(k).cloned()
76    }
77}
78impl<E: Clone + Ord> IConj<E> for Standard<E> {
79    type Output = Self;
80    fn conj(&self, v: E) -> Self {
81        self.conj_value(v)
82    }
83}
84impl<E: Clone + Ord> IDissoc<E> for Standard<E> {
85    type Output = Self;
86    fn dissoc(&self, k: &E) -> Self {
87        self.dissoc_value(k)
88    }
89}
90impl<E: Clone + Ord> INth<E> for Standard<E> {
91    fn nth(&self, i: usize) -> Option<&E> {
92        self.iter().nth(i)
93    }
94}
95impl<E: Clone + Ord> IEmpty for Standard<E> {
96    type Output = Self;
97    fn empty(&self) -> Self {
98        Self {
99            lookup: self.lookup.empty(),
100        }
101    }
102}
103impl<E: Clone + Ord> IMetadata for Standard<E> {
104    type Metadata = std::rc::Rc<crate::lang::data::Metadata>;
105    fn meta(&self) -> Option<&Self::Metadata> {
106        self.lookup.meta()
107    }
108    fn with_meta(&self, metadata: Option<Self::Metadata>) -> Self {
109        Self {
110            lookup: self.lookup.with_meta(metadata),
111        }
112    }
113}
114impl<E: Clone + Ord> IPersistent for Standard<E> {}
115impl<E: Clone + Ord> IntoIterator for Standard<E> {
116    type Item = E;
117    type IntoIter = std::vec::IntoIter<E>;
118    fn into_iter(self) -> Self::IntoIter {
119        self.iter().cloned().collect::<Vec<_>>().into_iter()
120    }
121}
122impl<E: Clone + Ord> IEquality for Standard<E> {
123    fn equality(&self, other: &Self) -> bool {
124        self.len() == other.len() && self.iter().eq(other.iter())
125    }
126}
127impl<E: Clone + Ord + std::fmt::Debug> IDisplay for Standard<E> {
128    fn display(&self) -> String {
129        format!(
130            "#{{{}}}",
131            self.iter()
132                .map(|v| format!("{v:?}"))
133                .collect::<Vec<_>>()
134                .join(" ")
135        )
136    }
137}
138impl<E: Clone + Ord + std::hash::Hash + JavaHash> IHash for Standard<E> {
139    fn hash_calc(&self, hash_type: HashType) -> u64 {
140        // Java ISetType → IUnOrderedType: order-insensitive sum,
141        // "::SET" seed (see lang::hash).
142        crate::lang::hash::compose_unordered("SET", self.iter().map(|v| v.java_hash(hash_type)))
143            as u64
144    }
145}
146impl<E: Clone + Ord + std::fmt::Debug> IObjType for Standard<E> {
147    fn obj_type(&self) -> ObjType {
148        ObjType::Set
149    }
150}
151impl<E> IColl<E> for Standard<E>
152where
153    E: Clone + Ord + std::hash::Hash + JavaHash + std::fmt::Debug,
154{
155    fn start_string(&self) -> &'static str {
156        "#{"
157    }
158    fn end_string(&self) -> &'static str {
159        "}"
160    }
161}
162impl<E: Clone + Ord> IToMutable for Standard<E> {
163    type Mutable = Mutable<E>;
164    fn to_mutable(&self) -> Self::Mutable {
165        Mutable {
166            editable: Cell::new(true),
167            set: self.clone(),
168        }
169    }
170}
171
172#[derive(Debug, Clone)]
173pub struct Mutable<E> {
174    editable: Cell<bool>,
175    set: Standard<E>,
176}
177impl<E: Clone + Ord> Mutable<E> {
178    fn check(&self) {
179        assert!(
180            self.editable.get(),
181            "mutable sorted set used after to_persistent"
182        )
183    }
184    pub fn conj(&mut self, v: E) -> &mut Self {
185        self.check();
186        self.set = self.set.conj_value(v);
187        self
188    }
189    pub fn dissoc(&mut self, v: &E) -> &mut Self {
190        self.check();
191        self.set = self.set.dissoc_value(v);
192        self
193    }
194}
195impl<E: Clone + Ord> std::ops::Deref for Mutable<E> {
196    type Target = Standard<E>;
197    fn deref(&self) -> &Self::Target {
198        self.check();
199        &self.set
200    }
201}
202impl<E> IMutable for Mutable<E> {}
203impl<E: Clone + Ord> IToPersistent for Mutable<E> {
204    type Persistent = Standard<E>;
205    fn to_persistent(&mut self) -> Self::Persistent {
206        self.check();
207        self.editable.set(false);
208        self.set.clone()
209    }
210}
211
212#[cfg(test)]
213mod tests {
214    use super::Standard;
215    #[test]
216    fn updates_slices_empty_and_mutable_preserve_metadata() {
217        use crate::lang::protocol::{IEmpty, IMetadata, IToMutable, IToPersistent};
218        let set = [1, 2, 3]
219            .into_iter()
220            .collect::<Standard<_>>()
221            .with_meta(Some(crate::lang::data::Metadata::document("doc")));
222        for value in [
223            set.conj_value(4),
224            set.dissoc_value(&1),
225            set.slice(&1, &2),
226            set.empty(),
227        ] {
228            assert_eq!(value.meta().map(|m| m.doc().unwrap()), Some("doc"));
229        }
230        let mut mutable = set.to_mutable();
231        mutable.conj(4);
232        assert_eq!(
233            mutable.to_persistent().meta().map(|m| m.doc().unwrap()),
234            Some("doc")
235        );
236    }
237
238    #[test]
239    fn deduplicates_and_sorts() {
240        let set = [4, 1, 3, 1, 2].into_iter().collect::<Standard<_>>();
241        assert_eq!(set.iter().copied().collect::<Vec<_>>(), vec![1, 2, 3, 4]);
242        assert_eq!(set.index_of(&3), Some(2));
243        assert_eq!(
244            set.slice(&2, &3).iter().copied().collect::<Vec<_>>(),
245            vec![2, 3]
246        );
247    }
248}