Skip to main content

ic_memory/slot/
memory_manager.rs

1use serde::{Deserialize, Serialize};
2
3///
4/// MemoryManagerSlot
5///
6/// A usable physical `ic-stable-structures::MemoryManager` allocation ID.
7///
8/// Construction and deserialization reject the unallocated-bucket sentinel
9/// (255), so reading the ID is infallible. A slot is an identity, not authority
10/// to open memory; that still requires committed allocation validation.
11///
12/// Serde encodes the numeric ID directly. Decoding uses the same checked
13/// constructor, so serialized DTOs cannot introduce the sentinel.
14///
15
16#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
17#[serde(try_from = "u8", into = "u8")]
18pub struct MemoryManagerSlot(u8);
19
20impl MemoryManagerSlot {
21    /// Construct a slot, rejecting ID 255.
22    pub const fn new(id: u8) -> Result<Self, MemoryManagerSlotError> {
23        match validate_memory_manager_id(id) {
24            Ok(()) => Ok(Self(id)),
25            Err(error) => Err(error),
26        }
27    }
28
29    /// Return the usable virtual memory ID.
30    #[must_use]
31    pub const fn id(&self) -> u8 {
32        self.0
33    }
34}
35
36impl From<MemoryManagerSlot> for u8 {
37    fn from(slot: MemoryManagerSlot) -> Self {
38        slot.id()
39    }
40}
41
42impl TryFrom<u8> for MemoryManagerSlot {
43    type Error = MemoryManagerSlotError;
44
45    fn try_from(id: u8) -> Result<Self, Self::Error> {
46        Self::new(id)
47    }
48}
49
50/// First usable `MemoryManager` virtual memory ID.
51pub const MEMORY_MANAGER_MIN_ID: u8 = 0;
52
53/// Last usable `MemoryManager` virtual memory ID.
54pub const MEMORY_MANAGER_MAX_ID: u8 = 254;
55
56/// `MemoryManager` unallocated-bucket sentinel. This is not a usable slot.
57pub const MEMORY_MANAGER_INVALID_ID: u8 = u8::MAX;
58
59/// Stable-key namespace prefix reserved for `ic-memory` allocation-governance infrastructure.
60pub const IC_MEMORY_STABLE_KEY_PREFIX: &str = "ic_memory.";
61
62/// Diagnostic owner label for `ic-memory` allocation-governance infrastructure.
63pub const IC_MEMORY_AUTHORITY_OWNER: &str = "ic-memory";
64
65/// Stable key of the allocation ledger when backed by the current MemoryManager substrate.
66pub const IC_MEMORY_LEDGER_STABLE_KEY: &str = "ic_memory.ledger.v1";
67
68/// MemoryManager ID used by the allocation ledger in the current MemoryManager substrate.
69pub const MEMORY_MANAGER_LEDGER_ID: u8 = MEMORY_MANAGER_MIN_ID;
70
71/// Last MemoryManager ID reserved for `ic-memory` governance in the current substrate.
72pub const MEMORY_MANAGER_GOVERNANCE_MAX_ID: u8 = 9;
73
74/// Return true when `stable_key` belongs to the `ic-memory` namespace.
75#[must_use]
76pub fn is_ic_memory_stable_key(stable_key: &str) -> bool {
77    stable_key.starts_with(IC_MEMORY_STABLE_KEY_PREFIX)
78}
79
80///
81/// MemoryManagerSlotError
82///
83/// Invalid `MemoryManager` allocation ID.
84///
85
86#[non_exhaustive]
87#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
88pub enum MemoryManagerSlotError {
89    /// ID 255 is the unallocated-bucket sentinel.
90    #[error("MemoryManager ID {id} is not a usable allocation slot")]
91    InvalidMemoryManagerId {
92        /// Invalid MemoryManager ID.
93        id: u8,
94    },
95}
96
97/// Validate that a `MemoryManager` ID is usable as an allocation slot.
98pub const fn validate_memory_manager_id(id: u8) -> Result<(), MemoryManagerSlotError> {
99    if id == MEMORY_MANAGER_INVALID_ID {
100        return Err(MemoryManagerSlotError::InvalidMemoryManagerId { id });
101    }
102    Ok(())
103}