cljrs_value/collections/
transient_set.rs1use 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<PersistentHashSet>,
8 persisted: Mutex<bool>,
9}
10
11impl TransientSet {
12 pub fn new() -> Self {
13 TransientSet {
14 set: Mutex::new(PersistentHashSet::empty()),
15 persisted: Mutex::new(false),
16 }
17 }
18
19 pub fn new_from_set(set: &PersistentHashSet) -> 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 let mut set = self.set.lock().unwrap();
31 set.conj_mut(value);
32 Ok(())
33 }
34
35 pub fn disj(&self, value: &Value) -> ValueResult<()> {
36 if *self.persisted.lock().unwrap() {
37 return Err(ValueError::TransientAlreadyPersisted);
38 }
39 let mut set = self.set.lock().unwrap();
40 *set = set.disj(value);
41 Ok(())
42 }
43
44 pub fn persistent(&self) -> ValueResult<PersistentHashSet> {
45 let set = self.set.lock().unwrap();
46 let mut persisted = self.persisted.lock().unwrap();
47 if *persisted {
48 return Err(ValueError::TransientAlreadyPersisted);
49 }
50 *persisted = true;
51 Ok(set.clone())
52 }
53
54 pub fn count(&self) -> usize {
55 let set = self.set.lock().unwrap();
56 set.count()
57 }
58
59 pub fn contains(&self, value: &Value) -> bool {
60 self.set.lock().unwrap().contains(value)
61 }
62}
63
64impl Clone for TransientSet {
65 fn clone(&self) -> Self {
66 Self {
67 set: Mutex::new(self.set.lock().unwrap().clone()),
68 persisted: Mutex::new(*self.persisted.lock().unwrap()),
69 }
70 }
71}
72
73impl ClojureHash for TransientSet {
74 fn clojure_hash(&self) -> u32 {
75 let mut hash: u32 = 0;
76 for v in self.set.lock().unwrap().iter() {
77 hash = hash_combine_unordered(hash, v.clojure_hash())
78 }
79 hash
80 }
81}
82
83impl cljrs_gc::Trace for TransientSet {
84 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
85 {
86 let set = self.set.lock().unwrap();
87 for v in set.iter() {
88 v.trace(visitor);
89 }
90 }
91 }
92
93 fn gc_size_extra(&self) -> usize {
94 let set = self.set.lock().unwrap();
95 set.full_size_extra()
96 }
97}
98
99impl Default for TransientSet {
100 fn default() -> Self {
101 Self::new()
102 }
103}