Skip to main content

cljrs_value/collections/
transient_set.rs

1use crate::hash::hash_combine_unordered;
2use crate::{ClojureHash, PersistentHashSet, Value, ValueError, ValueResult};
3use std::sync::Mutex;
4
5#[derive(Debug)]
6pub struct TransientSet {
7    set: Mutex<rpds::HashTrieSetSync<Value>>,
8    persisted: Mutex<bool>,
9}
10
11impl TransientSet {
12    pub fn new() -> Self {
13        TransientSet {
14            set: Mutex::new(Default::default()),
15            persisted: Mutex::new(false),
16        }
17    }
18
19    pub fn new_from_set(set: &rpds::HashTrieSetSync<Value>) -> TransientSet {
20        TransientSet {
21            set: Mutex::new(set.clone()),
22            persisted: Mutex::new(false),
23        }
24    }
25
26    pub fn conj(&self, value: Value) -> ValueResult<()> {
27        if *self.persisted.lock().unwrap() {
28            return Err(ValueError::TransientAlreadyPersisted);
29        }
30        self.set.lock().unwrap().insert_mut(value.clone());
31        Ok(())
32    }
33
34    pub fn disj(&self, value: &Value) -> ValueResult<()> {
35        if *self.persisted.lock().unwrap() {
36            return Err(ValueError::TransientAlreadyPersisted);
37        }
38        self.set.lock().unwrap().remove_mut(value);
39        Ok(())
40    }
41
42    pub fn persistent(&self) -> ValueResult<PersistentHashSet> {
43        let set = self.set.lock().unwrap();
44        let mut persisted = self.persisted.lock().unwrap();
45        if *persisted {
46            return Err(ValueError::TransientAlreadyPersisted);
47        }
48        *persisted = true;
49        Ok(PersistentHashSet::from_set(set.clone()))
50    }
51
52    pub fn count(&self) -> usize {
53        let set = self.set.lock().unwrap();
54        set.size()
55    }
56}
57
58impl Clone for TransientSet {
59    fn clone(&self) -> Self {
60        Self {
61            set: Mutex::new(self.set.lock().unwrap().clone()),
62            persisted: Mutex::new(*self.persisted.lock().unwrap()),
63        }
64    }
65}
66
67impl ClojureHash for TransientSet {
68    fn clojure_hash(&self) -> u32 {
69        let mut hash: u32 = 0;
70        for v in self.set.lock().unwrap().iter() {
71            hash = hash_combine_unordered(hash, v.clojure_hash())
72        }
73        hash
74    }
75}
76
77impl cljrs_gc::Trace for TransientSet {
78    fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
79        {
80            let set = self.set.lock().unwrap();
81            for v in set.iter() {
82                v.trace(visitor);
83            }
84        }
85    }
86}
87
88impl Default for TransientSet {
89    fn default() -> Self {
90        Self::new()
91    }
92}