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 for v in self.vector.lock().unwrap().iter() {
85 hash = hash_combine_ordered(hash, v.clojure_hash());
86 }
87 hash
88 }
89}
90
91impl Clone for TransientVector {
92 fn clone(&self) -> Self {
93 Self {
94 vector: Mutex::new(self.vector.lock().unwrap().clone()),
95 persisted: Mutex::new(*self.persisted.lock().unwrap()),
96 }
97 }
98}
99
100impl cljrs_gc::Trace for TransientVector {
101 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
102 {
103 let vec = self.vector.lock().unwrap();
104 for v in vec.iter() {
105 v.trace(visitor);
106 }
107 }
108 }
109
110 fn gc_size_extra(&self) -> usize {
111 let n = self.vector.lock().unwrap().len();
112 n * (24 + std::mem::size_of::<crate::Value>())
113 }
114}
115
116impl Default for TransientVector {
117 fn default() -> Self {
118 Self::new()
119 }
120}