ic_memory/ledger/
record.rs1use super::{AllocationRetirementError, LedgerIntegrityError};
2use crate::{
3 declaration::AllocationDeclaration, key::StableKey, schema::SchemaMetadata,
4 slot::MemoryManagerSlot,
5};
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
20#[serde(deny_unknown_fields)]
21pub struct AllocationLedger {
22 pub(crate) current_generation: u64,
23 #[serde(deserialize_with = "crate::cbor::deserialize_records")]
24 pub(crate) records: Vec<AllocationRecord>,
25}
26
27#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
36#[serde(deny_unknown_fields)]
37pub struct AllocationRecord {
38 pub(crate) stable_key: StableKey,
39 pub(crate) slot: MemoryManagerSlot,
40 pub(crate) state: AllocationState,
41 pub(crate) schema: SchemaMetadata,
42}
43
44#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
52#[serde(deny_unknown_fields)]
53pub enum AllocationState {
54 Reserved,
56 Active,
58 Retired,
60}
61
62#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
70#[serde(deny_unknown_fields)]
71pub struct AllocationRetirement {
72 pub(crate) stable_key: StableKey,
73 pub(crate) slot: MemoryManagerSlot,
74}
75
76impl AllocationRetirement {
77 pub fn new(
79 stable_key: impl AsRef<str>,
80 slot: MemoryManagerSlot,
81 ) -> Result<Self, AllocationRetirementError> {
82 let stable_key = StableKey::parse(stable_key).map_err(AllocationRetirementError::Key)?;
83 Ok(Self { stable_key, slot })
84 }
85
86 #[must_use]
88 pub const fn stable_key(&self) -> &StableKey {
89 &self.stable_key
90 }
91
92 #[must_use]
94 pub const fn slot(&self) -> &MemoryManagerSlot {
95 &self.slot
96 }
97}
98
99#[derive(Clone, Debug, Eq, PartialEq)]
108pub struct RecoveredLedger {
109 ledger: AllocationLedger,
110}
111
112impl RecoveredLedger {
113 pub(crate) const fn from_trusted_ledger(ledger: AllocationLedger) -> Self {
114 Self { ledger }
115 }
116
117 #[must_use]
119 pub const fn ledger(&self) -> &AllocationLedger {
120 &self.ledger
121 }
122
123 #[must_use]
125 pub const fn current_generation(&self) -> u64 {
126 self.ledger.current_generation
127 }
128
129 pub(crate) fn into_ledger(self) -> AllocationLedger {
130 self.ledger
131 }
132}
133
134impl AllocationRecord {
135 fn from_declaration(declaration: &AllocationDeclaration, state: AllocationState) -> Self {
136 Self {
137 stable_key: declaration.stable_key.clone(),
138 slot: declaration.slot.clone(),
139 state,
140 schema: declaration.schema.clone(),
141 }
142 }
143
144 pub(crate) fn active(declaration: &AllocationDeclaration) -> Self {
145 Self::from_declaration(declaration, AllocationState::Active)
146 }
147
148 pub(crate) fn reserved(declaration: &AllocationDeclaration) -> Self {
149 Self::from_declaration(declaration, AllocationState::Reserved)
150 }
151
152 #[must_use]
154 pub const fn stable_key(&self) -> &StableKey {
155 &self.stable_key
156 }
157
158 #[must_use]
160 pub const fn slot(&self) -> &MemoryManagerSlot {
161 &self.slot
162 }
163
164 #[must_use]
166 pub const fn state(&self) -> AllocationState {
167 self.state
168 }
169
170 #[must_use]
172 pub const fn schema(&self) -> &SchemaMetadata {
173 &self.schema
174 }
175}
176
177impl AllocationLedger {
178 pub(crate) const fn empty_genesis() -> Self {
179 Self {
180 current_generation: 0,
181 records: Vec::new(),
182 }
183 }
184
185 pub fn new(
188 current_generation: u64,
189 records: Vec<AllocationRecord>,
190 ) -> Result<Self, LedgerIntegrityError> {
191 let ledger = Self {
192 current_generation,
193 records,
194 };
195 ledger.validate_integrity()?;
196 Ok(ledger)
197 }
198
199 #[must_use]
201 pub const fn current_generation(&self) -> u64 {
202 self.current_generation
203 }
204
205 #[must_use]
207 pub fn records(&self) -> &[AllocationRecord] {
208 &self.records
209 }
210
211 pub(crate) fn occupied_slots(&self) -> [bool; crate::constants::MAX_ALLOCATIONS] {
213 let mut occupied = [false; crate::constants::MAX_ALLOCATIONS];
214 for record in &self.records {
215 occupied[usize::from(record.slot.id())] = true;
216 }
217 occupied
218 }
219}