use crate::{declaration::AllocationDeclaration, key::StableKey, slot::MemoryManagerSlot};
use std::sync::Arc;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ValidatedAllocations {
inner: Arc<ValidatedState>,
}
#[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,
}),
}
}
#[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<&MemoryManagerSlot> {
slot_for_key(self.declarations(), key.as_str())
}
pub(crate) const fn confirm_persisted(self, generation: u64) -> CommittedAllocations {
CommittedAllocations {
validated: self,
generation,
}
}
}
pub fn slot_for_key<'a>(
declarations: &'a [AllocationDeclaration],
key: &str,
) -> Option<&'a MemoryManagerSlot> {
declarations
.iter()
.find(|declaration| declaration.stable_key.as_str() == key)
.map(|declaration| &declaration.slot)
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CommittedAllocations {
validated: ValidatedAllocations,
generation: u64,
}
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<&MemoryManagerSlot> {
self.validated.slot_for(key)
}
pub(crate) fn into_application_allocations(mut self) -> Self {
Arc::make_mut(&mut self.validated.inner)
.declarations
.retain(|declaration| !crate::is_ic_memory_stable_key(declaration.stable_key.as_str()));
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn filtering_governance_does_not_change_shared_capabilities() {
let validated = ValidatedAllocations::new(
1,
vec![
AllocationDeclaration::memory_manager(
crate::IC_MEMORY_LEDGER_STABLE_KEY,
0,
"ledger",
)
.unwrap(),
AllocationDeclaration::memory_manager("app.rows.v1", 100, "rows").unwrap(),
],
Some("host".to_string()),
);
let committed = validated.clone().confirm_persisted(2);
let filtered = committed.clone().into_application_allocations();
assert_eq!(validated.declarations().len(), 2);
assert_eq!(committed.declarations().len(), 2);
assert_eq!(filtered.declarations().len(), 1);
assert_eq!(
filtered.declarations()[0].stable_key().as_str(),
"app.rows.v1"
);
assert_eq!(filtered.generation(), committed.generation());
assert_eq!(
filtered.runtime_fingerprint(),
committed.runtime_fingerprint()
);
}
}