use super::{AllocationRetirementError, LedgerIntegrityError};
use crate::{
declaration::AllocationDeclaration, key::StableKey, schema::SchemaMetadata,
slot::MemoryManagerSlot,
};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct AllocationLedger {
pub(crate) current_generation: u64,
#[serde(deserialize_with = "crate::cbor::deserialize_records")]
pub(crate) records: Vec<AllocationRecord>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct AllocationRecord {
pub(crate) stable_key: StableKey,
pub(crate) slot: MemoryManagerSlot,
pub(crate) state: AllocationState,
pub(crate) schema: SchemaMetadata,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub enum AllocationState {
Reserved,
Active,
Retired,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct AllocationRetirement {
pub(crate) stable_key: StableKey,
pub(crate) slot: MemoryManagerSlot,
}
impl AllocationRetirement {
pub fn new(
stable_key: impl AsRef<str>,
slot: MemoryManagerSlot,
) -> Result<Self, AllocationRetirementError> {
let stable_key = StableKey::parse(stable_key).map_err(AllocationRetirementError::Key)?;
Ok(Self { stable_key, slot })
}
#[must_use]
pub const fn stable_key(&self) -> &StableKey {
&self.stable_key
}
#[must_use]
pub const fn slot(&self) -> &MemoryManagerSlot {
&self.slot
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RecoveredLedger {
ledger: AllocationLedger,
}
impl RecoveredLedger {
pub(crate) const fn from_trusted_ledger(ledger: AllocationLedger) -> Self {
Self { ledger }
}
#[must_use]
pub const fn ledger(&self) -> &AllocationLedger {
&self.ledger
}
#[must_use]
pub const fn physical_generation(&self) -> u64 {
self.ledger.current_generation
}
#[must_use]
pub const fn current_generation(&self) -> u64 {
self.ledger.current_generation
}
pub(crate) fn into_ledger(self) -> AllocationLedger {
self.ledger
}
}
impl AllocationRecord {
fn from_declaration(declaration: &AllocationDeclaration, state: AllocationState) -> Self {
Self {
stable_key: declaration.stable_key.clone(),
slot: declaration.slot.clone(),
state,
schema: declaration.schema.clone(),
}
}
pub(crate) fn active(declaration: &AllocationDeclaration) -> Self {
Self::from_declaration(declaration, AllocationState::Active)
}
pub(crate) fn reserved(declaration: &AllocationDeclaration) -> Self {
Self::from_declaration(declaration, AllocationState::Reserved)
}
#[must_use]
pub const fn stable_key(&self) -> &StableKey {
&self.stable_key
}
#[must_use]
pub const fn slot(&self) -> &MemoryManagerSlot {
&self.slot
}
#[must_use]
pub const fn state(&self) -> AllocationState {
self.state
}
#[must_use]
pub const fn schema(&self) -> &SchemaMetadata {
&self.schema
}
}
impl AllocationLedger {
pub(crate) const fn empty_genesis() -> Self {
Self {
current_generation: 0,
records: Vec::new(),
}
}
pub fn new(
current_generation: u64,
records: Vec<AllocationRecord>,
) -> Result<Self, LedgerIntegrityError> {
let ledger = Self {
current_generation,
records,
};
ledger.validate_integrity()?;
Ok(ledger)
}
#[must_use]
pub const fn current_generation(&self) -> u64 {
self.current_generation
}
#[must_use]
pub fn records(&self) -> &[AllocationRecord] {
&self.records
}
}