Skip to main content

cljrs_value/collections/
transient_vector.rs

1use 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}