use super::descriptor::{AllocationSlot, AllocationSlotDescriptor};
use super::range_authority::MemoryManagerIdRange;
pub const MEMORY_MANAGER_SUBSTRATE: &str = "ic-stable-structures.memory_manager";
pub const MEMORY_MANAGER_DESCRIPTOR_VERSION: u32 = 1;
pub const MEMORY_MANAGER_MIN_ID: u8 = 0;
pub const MEMORY_MANAGER_MAX_ID: u8 = 254;
pub const MEMORY_MANAGER_INVALID_ID: u8 = u8::MAX;
pub const IC_MEMORY_STABLE_KEY_PREFIX: &str = "ic_memory.";
pub const IC_MEMORY_AUTHORITY_OWNER: &str = "ic-memory";
pub const IC_MEMORY_AUTHORITY_PURPOSE: &str = "ic-memory allocation-governance authority";
pub const IC_MEMORY_LEDGER_STABLE_KEY: &str = "ic_memory.ledger.v1";
pub const IC_MEMORY_LEDGER_LABEL: &str = "MemoryLayoutLedger";
pub const MEMORY_MANAGER_LEDGER_ID: u8 = MEMORY_MANAGER_MIN_ID;
pub const MEMORY_MANAGER_GOVERNANCE_MAX_ID: u8 = 9;
#[must_use]
pub fn is_ic_memory_stable_key(stable_key: &str) -> bool {
stable_key.starts_with(IC_MEMORY_STABLE_KEY_PREFIX)
}
#[must_use]
pub const fn memory_manager_governance_range() -> MemoryManagerIdRange {
MemoryManagerIdRange {
start: MEMORY_MANAGER_MIN_ID,
end: MEMORY_MANAGER_GOVERNANCE_MAX_ID,
}
}
impl AllocationSlotDescriptor {
pub fn memory_manager(id: u8) -> Result<Self, MemoryManagerSlotError> {
validate_memory_manager_id(id)?;
Ok(Self::memory_manager_unchecked(id))
}
#[must_use]
pub(crate) fn memory_manager_unchecked(id: u8) -> Self {
Self {
slot: AllocationSlot::MemoryManagerId(id),
substrate: MEMORY_MANAGER_SUBSTRATE.to_string(),
descriptor_version: MEMORY_MANAGER_DESCRIPTOR_VERSION,
}
}
pub fn memory_manager_id(&self) -> Result<u8, MemoryManagerSlotError> {
if self.substrate != MEMORY_MANAGER_SUBSTRATE {
return Err(MemoryManagerSlotError::UnsupportedSubstrate {
substrate: self.substrate.clone(),
});
}
if self.descriptor_version != MEMORY_MANAGER_DESCRIPTOR_VERSION {
return Err(MemoryManagerSlotError::UnsupportedDescriptorVersion {
version: self.descriptor_version,
});
}
let AllocationSlot::MemoryManagerId(id) = self.slot;
validate_memory_manager_id(id)?;
Ok(id)
}
}
#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
pub enum MemoryManagerSlotError {
#[error("allocation slot substrate '{substrate}' is not supported as a MemoryManager slot")]
UnsupportedSubstrate {
substrate: String,
},
#[error("MemoryManager slot descriptor version {version} is unsupported")]
UnsupportedDescriptorVersion {
version: u32,
},
#[error("MemoryManager ID {id} is not a usable allocation slot")]
InvalidMemoryManagerId {
id: u8,
},
}
pub const fn validate_memory_manager_id(id: u8) -> Result<(), MemoryManagerSlotError> {
if id == MEMORY_MANAGER_INVALID_ID {
return Err(MemoryManagerSlotError::InvalidMemoryManagerId { id });
}
Ok(())
}