cljrs_value/collections/
transient_vector.rs1use crate::hash::hash_combine_ordered;
2use crate::{ClojureHash, PersistentVector, Value, ValueError, ValueResult};
3use std::sync::Mutex;
4
5#[derive(Debug)]
6pub struct TransientVector {
7 vector: Mutex<rpds::VectorSync<Value>>,
8 persisted: Mutex<bool>,
9}
10
11impl TransientVector {
12 pub fn new() -> TransientVector {
13 TransientVector {
14 vector: Mutex::new(Default::default()),
15 persisted: Mutex::new(false),
16 }
17 }
18
19 pub fn new_from_vector(vector: &rpds::VectorSync<Value>) -> TransientVector {
20 TransientVector {
21 vector: Mutex::new(vector.clone()),
22 persisted: Mutex::new(false),
23 }
24 }
25
26 pub fn append(&self, v: Value) -> ValueResult<()> {
27 if *self.persisted.lock().unwrap() {
28 return Err(ValueError::TransientAlreadyPersisted);
29 }
30 let mut vector = self.vector.lock().unwrap();
31 vector.push_back_mut(v);
32 Ok(())
33 }
34
35 pub fn pop(&self) -> ValueResult<()> {
36 if *self.persisted.lock().unwrap() {
37 return Err(ValueError::TransientAlreadyPersisted);
38 }
39 let mut vector = self.vector.lock().unwrap();
40 if vector.drop_last_mut() {
41 Ok(())
42 } else {
43 Err(ValueError::OutOfRange)
44 }
45 }
46
47 pub fn set(&self, index: usize, v: Value) -> ValueResult<()> {
48 if *self.persisted.lock().unwrap() {
49 return Err(ValueError::TransientAlreadyPersisted);
50 }
51 let mut vector = self.vector.lock().unwrap();
52 if index > vector.len() {
53 return Err(ValueError::IndexOutOfBounds {
54 idx: index,
55 count: vector.len(),
56 });
57 }
58 vector.set_mut(index, v);
59 Ok(())
60 }
61
62 pub fn count(&self) -> usize {
63 self.vector.lock().unwrap().len()
64 }
65
66 pub fn get(&self, index: usize) -> Option<Value> {
67 self.vector.lock().unwrap().get(index).cloned()
68 }
69
70 pub fn persistent(&self) -> ValueResult<PersistentVector> {
71 let vector = self.vector.lock().unwrap();
72 let mut persisted = self.persisted.lock().unwrap();
73 if *persisted {
74 return Err(ValueError::TransientAlreadyPersisted);
75 }
76 *persisted = true;
77 Ok(PersistentVector::from_vector(vector.clone()))
78 }
79}
80
81impl ClojureHash for TransientVector {
82 fn clojure_hash(&self) -> u32 {
83 let mut hash: u32 = 0;
84 let values = self.vector.lock().unwrap().clone();
85 let snapshot = super::Snapshot::new(crate::PersistentVector::from_vector(values));
86 for v in snapshot.get().iter() {
87 hash = hash_combine_ordered(hash, v.clojure_hash());
88 }
89 hash
90 }
91}
92
93impl Clone for TransientVector {
94 fn clone(&self) -> Self {
95 Self {
96 vector: Mutex::new(self.vector.lock().unwrap().clone()),
97 persisted: Mutex::new(*self.persisted.lock().unwrap()),
98 }
99 }
100}
101
102impl cljrs_gc::Trace for TransientVector {
103 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
104 {
105 let vec = self.vector.lock().unwrap();
106 for v in vec.iter() {
107 v.trace(visitor);
108 }
109 }
110 }
111
112 fn gc_size_extra(&self) -> usize {
113 let n = self.vector.lock().unwrap().len();
114 n * (24 + std::mem::size_of::<crate::Value>())
115 }
116}
117
118impl Default for TransientVector {
119 fn default() -> Self {
120 Self::new()
121 }
122}