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