cljrs_value/collections/
transient_map.rs1use crate::hash::{hash_combine_ordered, hash_combine_unordered};
10use crate::{ClojureHash, PersistentHashMap, Value, ValueError, ValueResult};
11use std::sync::Mutex;
12
13#[derive(Debug)]
14pub struct TransientMap {
15 map: Mutex<PersistentHashMap>,
16 persisted: Mutex<bool>,
17}
18
19impl TransientMap {
20 pub fn new() -> TransientMap {
21 TransientMap {
22 map: Mutex::new(PersistentHashMap::empty()),
23 persisted: Mutex::new(false),
24 }
25 }
26
27 pub fn new_from_map(map: &PersistentHashMap) -> TransientMap {
28 TransientMap {
29 map: Mutex::new(map.clone()),
30 persisted: Mutex::new(false),
31 }
32 }
33
34 pub fn assoc(&self, key: Value, value: Value) -> ValueResult<()> {
35 if *self.persisted.lock().unwrap() {
36 return Err(ValueError::TransientAlreadyPersisted);
37 }
38 let mut map = self.map.lock().unwrap();
39 *map = map.assoc(key, value);
40 Ok(())
41 }
42
43 pub fn dissoc(&self, key: &Value) -> ValueResult<()> {
44 if *self.persisted.lock().unwrap() {
45 return Err(ValueError::TransientAlreadyPersisted);
46 }
47 let mut map = self.map.lock().unwrap();
48 *map = map.dissoc(key);
49 Ok(())
50 }
51
52 pub fn persistent(&self) -> ValueResult<PersistentHashMap> {
53 let map = self.map.lock().unwrap();
54 let mut persisted = self.persisted.lock().unwrap();
55 if *persisted {
56 return Err(ValueError::TransientAlreadyPersisted);
57 }
58 *persisted = true;
59 Ok(map.clone())
60 }
61
62 pub fn find(&self, key: &Value) -> Option<(Value, Value)> {
63 let map = self.map.lock().unwrap();
64 let value = map.get(key);
65 value.map(|v| (key.clone(), v.clone()))
66 }
67
68 pub fn get(&self, key: &Value) -> Option<Value> {
69 self.map.lock().unwrap().get(key).cloned()
70 }
71
72 pub fn contains_key(&self, key: &Value) -> bool {
73 self.map.lock().unwrap().contains_key(key)
74 }
75
76 pub fn count(&self) -> usize {
77 let map = self.map.lock().unwrap();
78 map.count()
79 }
80}
81
82impl Clone for TransientMap {
83 fn clone(&self) -> Self {
84 Self {
85 map: Mutex::new(self.map.lock().unwrap().clone()),
86 persisted: Mutex::new(*self.persisted.lock().unwrap()),
87 }
88 }
89}
90
91impl ClojureHash for TransientMap {
92 fn clojure_hash(&self) -> u32 {
93 let mut hash: u32 = 0;
94 for (k, v) in self.map.lock().unwrap().iter() {
95 hash = hash_combine_unordered(
96 hash,
97 hash_combine_ordered(k.clojure_hash(), v.clojure_hash()),
98 );
99 }
100 hash
101 }
102}
103
104impl cljrs_gc::Trace for TransientMap {
105 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
106 {
107 let map = self.map.lock().unwrap();
108 for (k, v) in map.iter() {
109 k.trace(visitor);
110 v.trace(visitor);
111 }
112 }
113 }
114
115 fn gc_size_extra(&self) -> usize {
116 let map = self.map.lock().unwrap();
117 map.gc_size_extra()
118 }
119}
120
121impl Default for TransientMap {
122 fn default() -> Self {
123 Self::new()
124 }
125}