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 persistent(&self) -> ValueResult<PersistentVector> {
67 let vector = self.vector.lock().unwrap();
68 let mut persisted = self.persisted.lock().unwrap();
69 if *persisted {
70 return Err(ValueError::TransientAlreadyPersisted);
71 }
72 *persisted = true;
73 Ok(PersistentVector::from_vector(vector.clone()))
74 }
75}
76
77impl ClojureHash for TransientVector {
78 fn clojure_hash(&self) -> u32 {
79 let mut hash: u32 = 0;
80 for v in self.vector.lock().unwrap().iter() {
81 hash = hash_combine_ordered(hash, v.clojure_hash());
82 }
83 hash
84 }
85}
86
87impl Clone for TransientVector {
88 fn clone(&self) -> Self {
89 Self {
90 vector: Mutex::new(self.vector.lock().unwrap().clone()),
91 persisted: Mutex::new(*self.persisted.lock().unwrap()),
92 }
93 }
94}
95
96impl cljrs_gc::Trace for TransientVector {
97 fn trace(&self, visitor: &mut cljrs_gc::MarkVisitor) {
98 {
99 let vec = self.vector.lock().unwrap();
100 for v in vec.iter() {
101 v.trace(visitor);
102 }
103 }
104 }
105}
106
107impl Default for TransientVector {
108 fn default() -> Self {
109 Self::new()
110 }
111}