pijul_core/changestore/
memory.rs1use super::*;
2use crate::HashMap;
3use crate::change::Change;
4use crate::pristine::{ChangeId, Hash, Vertex};
5use std::sync::{Arc, RwLock};
6
7#[derive(Clone, Default)]
8pub 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}