use crate::{
declaration::AllocationDeclaration, key::StableKey, slot::AllocationSlotDescriptor,
substrate::StorageSubstrate,
};
use std::sync::Arc;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ValidatedAllocations {
inner: Arc<ValidatedState>,
_private: (),
}
#[derive(Clone, Debug, Eq, PartialEq)]
struct ValidatedState {
base_generation: u64,
declarations: Vec<AllocationDeclaration>,
runtime_fingerprint: Option<String>,
}
impl ValidatedAllocations {
pub(crate) fn new(
base_generation: u64,
declarations: Vec<AllocationDeclaration>,
runtime_fingerprint: Option<String>,
) -> Self {
Self {
inner: Arc::new(ValidatedState {
base_generation,
declarations,
runtime_fingerprint,
}),
_private: (),
}
}
#[must_use]
pub fn base_generation(&self) -> u64 {
self.inner.base_generation
}
#[must_use]
pub fn declarations(&self) -> &[AllocationDeclaration] {
&self.inner.declarations
}
#[must_use]
pub fn runtime_fingerprint(&self) -> Option<&str> {
self.inner.runtime_fingerprint.as_deref()
}
#[must_use]
pub fn slot_for(&self, key: &StableKey) -> Option<&AllocationSlotDescriptor> {
self.declarations()
.iter()
.find(|declaration| &declaration.stable_key == key)
.map(|declaration| &declaration.slot)
}
pub(crate) const fn confirm_persisted(self, generation: u64) -> CommittedAllocations {
CommittedAllocations {
validated: self,
generation,
_private: (),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CommittedAllocations {
validated: ValidatedAllocations,
generation: u64,
_private: (),
}
impl CommittedAllocations {
#[must_use]
pub const fn generation(&self) -> u64 {
self.generation
}
#[must_use]
pub fn declarations(&self) -> &[AllocationDeclaration] {
self.validated.declarations()
}
#[must_use]
pub fn runtime_fingerprint(&self) -> Option<&str> {
self.validated.runtime_fingerprint()
}
#[must_use]
pub fn slot_for(&self, key: &StableKey) -> Option<&AllocationSlotDescriptor> {
self.validated.slot_for(key)
}
pub(crate) fn without_stable_key_prefix(mut self, prefix: &str) -> Self {
let mut state = (*self.validated.inner).clone();
state
.declarations
.retain(|declaration| !declaration.stable_key.as_str().starts_with(prefix));
self.validated.inner = Arc::new(state);
self
}
}
pub struct AllocationSession<S: StorageSubstrate> {
substrate: S,
committed: CommittedAllocations,
}
impl<S: StorageSubstrate> AllocationSession<S> {
#[must_use]
pub const fn new(substrate: S, committed: CommittedAllocations) -> Self {
Self {
substrate,
committed,
}
}
#[must_use]
pub const fn committed(&self) -> &CommittedAllocations {
&self.committed
}
pub fn open(
&self,
key: &StableKey,
) -> Result<S::MemoryHandle, AllocationSessionError<S::Error>> {
let slot = self
.committed
.slot_for(key)
.ok_or_else(|| AllocationSessionError::UnknownStableKey(key.clone()))?;
self.substrate
.open_slot(slot)
.map_err(AllocationSessionError::Substrate)
}
}
#[non_exhaustive]
#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
pub enum AllocationSessionError<E> {
#[error("stable key '{0}' was not committed for this allocation session")]
UnknownStableKey(StableKey),
#[error("storage substrate failed to open allocation slot")]
Substrate(E),
}