Skip to main content

canic_core/dto/
memory.rs

1use crate::dto::prelude::*;
2
3pub use crate::domain::memory::{
4    MemoryAllocationBinding, MemoryAllocationState, MemoryCommitRecoveryErrorResponse,
5    MemoryRangeAuthorityMode,
6};
7
8/// Measured physical and virtual allocations exposed by protected observations.
9/// Covers all usable IDs, including unknown bindings and the substrate ledger.
10#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
11pub struct MemoryAllocationsResponse {
12    pub current_generation: u64,
13    pub manager_layout_version: u8,
14    /// Actual persisted size, never a requested/default assumption.
15    pub bucket_size_pages: u16,
16    pub bucket_size_bytes: u64,
17    pub bucket_capacity: u32,
18    pub allocated_buckets: u16,
19    pub remaining_buckets: u32,
20    pub maximum_bucket_bytes: u64,
21    /// Backing extent: IC stable memory in canisters, vector memory on native hosts.
22    pub physical_extent: MemoryAllocationSizeEntry,
23    /// Addressable capacity, not stored payload occupancy.
24    pub virtual_extent: MemoryAllocationSizeEntry,
25    pub manager_metadata_bytes: u64,
26    pub manager_header_bytes: u64,
27    pub manager_bucket_table_bytes: u64,
28    pub manager_padding_bytes: u64,
29    pub allocated_bucket_bytes: u64,
30    pub bucket_slack_bytes: u64,
31    pub known_binding_bytes: u64,
32    pub unknown_binding_bytes: u64,
33    /// Physical bytes outside the assigned manager region.
34    pub unmanaged_bytes: u64,
35    pub metadata_bytes_read: u64,
36    pub memories: Vec<MemoryAllocationEntry>,
37}
38
39/// One manager ID's measured capacity and independently sourced ownership metadata.
40#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
41pub struct MemoryAllocationEntry {
42    pub memory_manager_id: u8,
43    pub binding: MemoryAllocationBinding,
44    pub range_claim: Option<MemoryAllocationRangeClaim>,
45    pub virtual_extent: MemoryAllocationSizeEntry,
46    pub allocated_buckets: u16,
47    pub allocated_bytes: u64,
48    pub bucket_slack_bytes: u64,
49    /// Unavailable: allocation metadata does not measure payload occupancy.
50    pub payload_bytes: Option<u64>,
51}
52
53/// Current range policy metadata; this does not establish a stable-key binding.
54#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
55pub struct MemoryAllocationRangeClaim {
56    pub authority: String,
57    pub mode: MemoryRangeAuthorityMode,
58}
59
60///
61/// MemoryLedgerResponse
62///
63
64#[derive(CandidType, Clone, Debug, Deserialize)]
65pub struct MemoryLedgerResponse {
66    pub ledger_schema_version: u32,
67    pub physical_format_id: u32,
68    pub current_generation: u64,
69    pub commit_recovery: MemoryCommitRecoveryResponse,
70    pub authorities: Vec<MemoryRangeAuthorityEntry>,
71    pub memories: Vec<MemoryLedgerMemoryEntry>,
72    pub records: Vec<MemoryAllocationRecordEntry>,
73    pub generations: Vec<MemoryLedgerGenerationEntry>,
74}
75
76///
77/// MemoryCommitRecoveryResponse
78///
79
80#[derive(CandidType, Clone, Debug, Deserialize)]
81pub struct MemoryCommitRecoveryResponse {
82    pub slot0: MemoryCommitSlotResponse,
83    pub slot1: MemoryCommitSlotResponse,
84    pub authoritative_generation: Option<u64>,
85    pub recovery_error: Option<MemoryCommitRecoveryErrorResponse>,
86}
87
88///
89/// MemoryCommitSlotResponse
90///
91
92#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
93pub struct MemoryCommitSlotResponse {
94    pub present: bool,
95    pub generation: Option<u64>,
96    pub valid: bool,
97}
98
99///
100/// MemoryRangeAuthorityEntry
101///
102
103#[derive(CandidType, Clone, Debug, Deserialize)]
104pub struct MemoryRangeAuthorityEntry {
105    pub owner: String,
106    pub start: u8,
107    pub end: u8,
108    pub mode: MemoryRangeAuthorityMode,
109    pub purpose: String,
110}
111
112///
113/// MemoryLedgerMemoryEntry
114///
115
116#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
117pub struct MemoryLedgerMemoryEntry {
118    pub memory_manager_id: u8,
119    pub stable_key: String,
120    pub state: MemoryAllocationState,
121    pub size: MemoryAllocationSizeEntry,
122}
123
124///
125/// MemoryAllocationRecordEntry
126///
127
128#[derive(CandidType, Clone, Debug, Deserialize)]
129pub struct MemoryAllocationRecordEntry {
130    pub memory_manager_id: Option<u8>,
131    pub stable_key: String,
132    pub state: MemoryAllocationState,
133    pub memory_size: Option<MemoryAllocationSizeEntry>,
134    pub first_generation: u64,
135    pub last_seen_generation: u64,
136    pub retired_generation: Option<u64>,
137    pub schema_history: Vec<MemorySchemaMetadataEntry>,
138}
139
140///
141/// MemoryAllocationSizeEntry
142///
143
144#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
145pub struct MemoryAllocationSizeEntry {
146    pub wasm_pages: u64,
147    pub bytes: u64,
148}
149
150///
151/// MemorySchemaMetadataEntry
152///
153
154#[derive(CandidType, Clone, Debug, Deserialize)]
155pub struct MemorySchemaMetadataEntry {
156    pub generation: u64,
157    pub schema_version: Option<u32>,
158    pub schema_fingerprint: Option<String>,
159}
160
161///
162/// MemoryLedgerGenerationEntry
163///
164
165#[derive(CandidType, Clone, Debug, Deserialize)]
166pub struct MemoryLedgerGenerationEntry {
167    pub generation: u64,
168    pub parent_generation: Option<u64>,
169    pub runtime_fingerprint: Option<String>,
170    pub declaration_count: u32,
171    pub committed_at: Option<u64>,
172}
173
174#[cfg(test)]
175mod tests {
176    use super::*;
177    use candid::{Decode, Encode};
178    use serde::de::DeserializeOwned;
179    use std::fmt::Debug;
180
181    #[test]
182    fn memory_enums_roundtrip_candid_with_existing_variant_labels() {
183        assert_enum_candid_contract(MemoryCommitRecoveryErrorResponse::InvalidCommitSlots);
184        assert_enum_candid_contract(MemoryCommitRecoveryErrorResponse::UnexpectedGeneration);
185        assert_enum_candid_contract(MemoryRangeAuthorityMode::Allowed);
186        assert_enum_candid_contract(MemoryAllocationState::Retired);
187    }
188
189    fn assert_enum_candid_contract<T>(value: T)
190    where
191        T: CandidType + Clone + Debug + DeserializeOwned + Eq,
192    {
193        let bytes = Encode!(&value).expect("encode memory enum");
194        let decoded = Decode!(&bytes, T).expect("decode memory enum");
195
196        assert_eq!(decoded, value);
197    }
198}