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<rpds::HashTrieMapSync<Value, Value>>,
16 persisted: Mutex<bool>,
17}
18
19impl TransientMap {
20 pub fn new() -> TransientMap {
21 TransientMap {
22 map: Mutex::new(rpds::HashTrieMapSync::default()),
23 persisted: Mutex::new(false),
24 }
25 }
26
27 pub fn new_from_map(map: &rpds::HashTrieMapSync<Value, Value>) -> 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.insert_mut(key.clone(), value.clone());
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.remove_mut(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(PersistentHashMap::new(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| (v.clone(), v.clone()))
66 }
67
68 pub fn count(&self) -> usize {
69 let map = self.map.lock().unwrap();
70 map.size()
71 }
72}
73
74impl Clone for TransientMap {
75 fn clone(&self) -> Self {
76 Self {
77 map: Mutex::new(self.map.lock().unwrap().clone()),
78 persisted: Mutex::new(*self.persisted.lock().unwrap()),
79 }
80 }
81}
82
83impl ClojureHash for TransientMap {
84 fn clojure_hash(&self) -> u32 {
85 let mut hash: u32 = 0;
86 for (k, v) in self.map.lock().unwrap().iter() {
87 hash = hash_combine_unordered(
88 hash,
89 hash_combine_ordered(k.clojure_hash(), v.clojure_hash()),
90 );
91 }
92 hash
93 }
94}
95
96impl cljrs_gc::Trace for TransientMap {
97 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
98 {
99 let map = self.map.lock().unwrap();
100 for (k, v) in map.iter() {
101 k.trace(visitor);
102 v.trace(visitor);
103 }
104 }
105 }
106}
107
108impl Default for TransientMap {
109 fn default() -> Self {
110 Self::new()
111 }
112}