Skip to main content

loftspec_store/
memory.rs

1//! The memory store: the document held as the model, for tests and for a later server.
2
3use loftspec::codec::{self, Files};
4use loftspec::document::Document;
5use loftspec::hash::{Roots, hash_document};
6
7use crate::{DocumentStore, Saved, StoreError};
8
9/// A document held in memory, beside the writer's output for it.
10#[derive(Debug, Clone, Default)]
11pub struct MemoryStore {
12    held: Option<(Document, Files)>,
13}
14
15impl MemoryStore {
16    /// A store that holds no document yet.
17    #[must_use]
18    pub fn new() -> Self {
19        Self::default()
20    }
21
22    fn document(&self) -> Result<&Document, StoreError> {
23        self.held
24            .as_ref()
25            .map(|(document, _)| document)
26            .ok_or(StoreError::NoDocument)
27    }
28}
29
30impl DocumentStore for MemoryStore {
31    fn load(&self) -> Result<Document, StoreError> {
32        self.document().cloned()
33    }
34
35    /// Reports what a file store would write and remove for the same save, from the writer's
36    /// output for the document held before and after.
37    fn save(&mut self, document: &Document) -> Result<Saved, StoreError> {
38        let next = codec::write(document);
39        let saved = match &self.held {
40            Some((_, current)) => Saved::between(current, &next),
41            None => Saved::between(&Files::new(), &next),
42        };
43        self.held = Some((document.clone(), next));
44        Ok(saved)
45    }
46
47    fn roots(&self) -> Result<Roots, StoreError> {
48        hash_document(self.document()?)
49            .map(|hashes| hashes.roots)
50            .map_err(StoreError::Index)
51    }
52}