Skip to main content

pijul_core/changestore/
memory.rs

1use super::*;
2use crate::HashMap;
3use crate::change::Change;
4use crate::pristine::{ChangeId, Hash, Vertex};
5use std::sync::{Arc, RwLock};
6
7#[derive(Clone, Default)]
8/// A change store in memory, i.e. basically a hash table.
9pub struct Memory {
10    changes: Arc<RwLock<HashMap<Hash, Change>>>,
11}
12
13impl Memory {
14    pub fn new() -> Self {
15        Self::default()
16    }
17}
18
19#[derive(Debug, Error)]
20pub enum Error {
21    #[error(transparent)]
22    Io(#[from] std::io::Error),
23    #[error(transparent)]
24    Utf8(#[from] std::str::Utf8Error),
25    #[error(transparent)]
26    Change(#[from] crate::change::ChangeError),
27    #[error("Change not found: {:?}", hash)]
28    ChangeNotFound { hash: crate::Hash },
29    #[error(transparent)]
30    Bincode(#[from] bincode::Error),
31}
32
33impl ChangeStore for Memory {
34    type Error = Error;
35    fn has_contents(&self, hash: Hash, _: Option<ChangeId>) -> bool {
36        let changes = self.changes.read().unwrap();
37        let p = changes.get(&hash).unwrap();
38        !p.contents.is_empty()
39    }
40
41    fn get_contents<F: Fn(ChangeId) -> Option<Hash>>(
42        &self,
43        hash: F,
44        key: Vertex<ChangeId>,
45        buf: &mut [u8],
46    ) -> Result<usize, Self::Error> {
47        if key.end <= key.start {
48            return Ok(0);
49        }
50        assert_eq!(buf.len(), key.end - key.start);
51        let changes = self.changes.read().unwrap();
52        let p = changes.get(&hash(key.change).unwrap()).unwrap();
53        let start = key.start.us();
54        let end = key.end.us();
55        buf.clone_from_slice(&p.contents[start..end]);
56        Ok(end - start)
57    }
58    fn get_contents_ext(
59        &self,
60        key: Vertex<Option<Hash>>,
61        buf: &mut [u8],
62    ) -> Result<usize, Self::Error> {
63        if let Some(change) = key.change {
64            if key.end <= key.start {
65                return Ok(0);
66            }
67            assert_eq!(key.end.us() - key.start.us(), buf.len());
68            let changes = self.changes.read().unwrap();
69            let p = changes.get(&change).unwrap();
70            let start = key.start.us();
71            let end = key.end.us();
72            buf.clone_from_slice(&p.contents[start..end]);
73            Ok(end - start)
74        } else {
75            Ok(0)
76        }
77    }
78    fn change_deletes_position<F: Fn(ChangeId) -> Option<Hash>>(
79        &self,
80        hash: F,
81        change: ChangeId,
82        pos: Position<Option<Hash>>,
83    ) -> Result<Vec<Hash>, Self::Error> {
84        let changes = self.changes.read().unwrap();
85        let change = changes.get(&hash(change).unwrap()).unwrap();
86        let mut v = Vec::new();
87        for c in change.changes.iter() {
88            for c in c.iter() {
89                v.extend(c.deletes_pos(pos))
90            }
91        }
92        Ok(v)
93    }
94    fn save_change<
95        E: From<Self::Error> + From<ChangeError>,
96        F: FnOnce(&mut Change, &Hash) -> Result<(), E>,
97    >(
98        &self,
99        p: &mut Change,
100        f: F,
101    ) -> Result<Hash, E> {
102        let mut w = self.changes.write().unwrap();
103        let hash = p.hash().map_err(Self::Error::from)?;
104        f(p, &hash)?;
105        w.insert(hash, p.clone());
106        Ok(hash)
107    }
108    fn del_change(&self, h: &Hash) -> Result<bool, Self::Error> {
109        let mut w = self.changes.write().unwrap();
110        Ok(w.remove(h).is_some())
111    }
112    fn get_change(&self, h: &Hash) -> Result<Change, Self::Error> {
113        let w = self.changes.read().unwrap();
114        if let Some(p) = w.get(h) {
115            Ok(p.clone())
116        } else {
117            Err(Error::ChangeNotFound { hash: *h })
118        }
119    }
120}