extern crate alloc;
use alloc::collections::{BTreeSet, VecDeque};
use alloc::vec::Vec;
use core::num::{NonZeroU64, NonZeroUsize};
use super::super::arrival::ArrivalRound;
use super::super::{Epochs, SealedEpoch, Window};
#[derive(Clone, Debug, PartialEq, Eq)]
pub(super) struct SnapshotState {
pub(super) generation: NonZeroU64,
pub(super) roster: BTreeSet<u32>,
pub(super) horizon: u64,
pub(super) window: Option<Window>,
pub(super) lineage: Vec<SealedEpoch>,
pub(super) arrival: Option<ArrivalRound>,
}
impl SnapshotState {
pub(super) fn from_epochs(epochs: &Epochs) -> Self {
if let Some(window) = &epochs.window {
debug_assert!(
window.confirmations.reports.keys().eq(epochs.roster.iter()),
"a round ranges over exactly the roster"
);
debug_assert!(
window.adoptions.keys().eq(window.candidates.keys()),
"adoption rounds pair with the candidates"
);
debug_assert!(
window
.adoptions
.values()
.all(|round| round.reports.keys().eq(epochs.roster.iter())),
"every adoption round ranges over exactly the roster"
);
}
if let Some(round) = &epochs.arrival {
debug_assert!(
epochs
.lineage
.back()
.is_some_and(|sealed| sealed.declaration() == round.admission().base()),
"an open arrival round's base is the newest sealed record"
);
}
Self {
generation: epochs.generation,
roster: epochs.roster.clone(),
horizon: u64::try_from(epochs.horizon.get()).unwrap_or(u64::MAX),
window: epochs.window.clone(),
lineage: epochs.lineage.iter().cloned().collect(),
arrival: epochs.arrival.clone(),
}
}
pub(super) fn to_epochs(&self, horizon: NonZeroUsize) -> Epochs {
Epochs {
roster: self.roster.clone(),
horizon,
generation: self.generation,
window: self.window.clone(),
lineage: VecDeque::from(self.lineage.clone()),
arrival: self.arrival.clone(),
}
}
}