Skip to main content

sim_lib_journal/
persistent.rs

1use sim_kernel::{ContentId, Datum};
2use thiserror::Error;
3
4use crate::{JournalBackend, JournalError, JournalObject};
5
6/// A verified crossing from semantic Datum identity to physical byte identity.
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct StoredDatumRef {
9    /// Kernel Datum identity used by callers and journal entries.
10    pub meaning: ContentId,
11    /// Exact-byte identity used only by the storage adapter.
12    pub storage: ContentId,
13}
14
15/// Failure of the owned-return persistent semantic object facet.
16#[derive(Clone, Debug, PartialEq, Eq, Error)]
17pub enum StoreError {
18    /// The journal object backend refused or could not verify the operation.
19    #[error(transparent)]
20    Journal(#[from] JournalError),
21}
22
23/// Owned-return persistent Datum operations over the journal object backend.
24pub trait PersistentSemanticObjects {
25    /// Stores a canonical value idempotently and returns both identities.
26    fn put(&mut self, value: Datum) -> Result<StoredDatumRef, StoreError>;
27    /// Resolves a value by semantic identity and verifies that identity again.
28    fn get(&self, meaning: &ContentId) -> Result<Datum, StoreError>;
29    /// Rebuilds and verifies the derived semantic-to-storage index.
30    fn rebuild_index(&mut self) -> Result<Vec<StoredDatumRef>, StoreError>;
31}
32
33/// Persistent semantic object facet backed by an existing journal backend.
34pub struct PersistentObjectStore<B> {
35    backend: B,
36}
37
38impl<B: JournalBackend> PersistentObjectStore<B> {
39    /// Opens the facet and verifies its rebuildable correspondence index.
40    pub fn open(backend: B) -> Result<Self, StoreError> {
41        backend.rebuild_datum_index()?;
42        Ok(Self { backend })
43    }
44
45    /// Returns the wrapped backend.
46    pub fn into_inner(self) -> B {
47        self.backend
48    }
49}
50
51impl<B: JournalBackend> PersistentSemanticObjects for PersistentObjectStore<B> {
52    fn put(&mut self, value: Datum) -> Result<StoredDatumRef, StoreError> {
53        Ok(self.backend.put_datum(JournalObject::from_datum(value)?)?)
54    }
55
56    fn get(&self, meaning: &ContentId) -> Result<Datum, StoreError> {
57        let value = self.backend.get_datum(meaning)?;
58        if value
59            .content_id()
60            .map_err(|_| JournalError::NonCanonicalDatum)?
61            != *meaning
62        {
63            return Err(JournalError::CorruptObject(meaning.clone()).into());
64        }
65        Ok(value)
66    }
67
68    fn rebuild_index(&mut self) -> Result<Vec<StoredDatumRef>, StoreError> {
69        Ok(self.backend.rebuild_datum_index()?)
70    }
71}