49 lines
1.7 KiB
Rust
49 lines
1.7 KiB
Rust
//! Persistence interface for complete validated candidate snapshots.
|
|
|
|
use core::num::NonZeroU64;
|
|
|
|
/// Storage-owned monotonically increasing committed snapshot generation.
|
|
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
|
pub struct Generation(NonZeroU64);
|
|
|
|
impl Generation {
|
|
/// Creates a generation supplied only by a persistence backend.
|
|
pub const fn new(value: u64) -> Self {
|
|
match NonZeroU64::new(value) {
|
|
Some(value) => Self(value),
|
|
None => panic!("configuration generation must be nonzero"),
|
|
}
|
|
}
|
|
|
|
/// Parses an on-disk or wire generation, rejecting the factory sentinel.
|
|
pub const fn try_new(value: u64) -> Option<Self> {
|
|
match NonZeroU64::new(value) {
|
|
Some(value) => Some(Self(value)),
|
|
None => None,
|
|
}
|
|
}
|
|
|
|
/// Returns the committed generation value.
|
|
pub const fn get(self) -> u64 {
|
|
self.0.get()
|
|
}
|
|
}
|
|
|
|
/// Durable storage of complete configuration snapshots.
|
|
///
|
|
/// Flight implementations use a two-slot journal: a record contains a header,
|
|
/// bounded CBOR payload, integrity check, and a commit marker written last.
|
|
/// A backend must retain its previous valid record until the replacement is
|
|
/// fully verified. Host file stores may implement the same interface without
|
|
/// claiming flash power-loss semantics.
|
|
pub trait ProfileStore<C> {
|
|
/// Backend-specific I/O or integrity failure.
|
|
type Error;
|
|
|
|
/// Loads the newest valid committed candidate, if one exists.
|
|
fn load(&mut self) -> Result<Option<(Generation, C)>, Self::Error>;
|
|
|
|
/// Persists one complete already-validated candidate atomically.
|
|
fn persist(&mut self, candidate: &C) -> Result<Generation, Self::Error>;
|
|
}
|