ic_canister_kit/
stable.rs1use std::cell::RefCell;
2
3use ic_stable_structures::{DefaultMemoryImpl, memory_manager::MemoryManager};
4
5pub type VirtualMemory = ic_stable_structures::memory_manager::VirtualMemory<ic_stable_structures::DefaultMemoryImpl>;
7pub use ic_stable_structures::GrowFailed;
8pub use ic_stable_structures::Memory;
9pub use ic_stable_structures::Storable;
10pub use ic_stable_structures::memory_manager::MemoryId;
11pub use ic_stable_structures::storable::Bound;
12pub use ic_stable_structures::writer::Writer;
13pub use std::borrow::Cow;
14
15pub type StableCell<T> = ic_stable_structures::Cell<T, VirtualMemory>;
18pub type StableVec<T> = ic_stable_structures::Vec<T, VirtualMemory>;
24pub type StableBTreeMap<K, V> = ic_stable_structures::BTreeMap<K, V, VirtualMemory>;
26pub type StableLog<T> = ic_stable_structures::Log<T, VirtualMemory, VirtualMemory>;
29pub type StablePriorityQueue<T> = ic_stable_structures::MinHeap<T, VirtualMemory>;
32
33thread_local! {
34 static MEMORY_MANAGER: RefCell<MemoryManager<DefaultMemoryImpl>> = RefCell::new(MemoryManager::init(DefaultMemoryImpl::default()));
35}
36
37const MEMORY_ID_UPGRADED: MemoryId = MemoryId::new(254);
41
42#[inline]
44pub fn get_virtual_memory(memory_id: MemoryId) -> VirtualMemory {
45 MEMORY_MANAGER.with(|memory_manager| memory_manager.borrow().get(memory_id))
46}
47
48#[inline]
50pub fn get_upgrades_memory() -> VirtualMemory {
51 get_virtual_memory(MEMORY_ID_UPGRADED)
52}
53
54pub fn init_cell_data<T: Storable>(memory_id: MemoryId, default: T) -> StableCell<T> {
56 StableCell::init(get_virtual_memory(memory_id), default)
57}
58pub fn init_vec_data<T: Storable>(memory_id: MemoryId) -> StableVec<T> {
60 StableVec::init(get_virtual_memory(memory_id))
61}
62pub fn init_map_data<K: Storable + Ord + Clone, V: Storable>(memory_id: MemoryId) -> StableBTreeMap<K, V> {
64 StableBTreeMap::init(get_virtual_memory(memory_id))
65}
66pub fn init_log_data<T: Storable>(index_memory_id: MemoryId, data_memory_id: MemoryId) -> StableLog<T> {
68 StableLog::init(get_virtual_memory(index_memory_id), get_virtual_memory(data_memory_id))
69}
70pub fn init_priority_queue_data<T: Storable + PartialOrd>(memory_id: MemoryId) -> StablePriorityQueue<T> {
72 StablePriorityQueue::init(get_virtual_memory(memory_id))
73}
74
75pub struct WriteUpgradeMemory<'a, M> {
77 writer: Writer<'a, M>,
78}
79
80pub struct ReadUpgradeMemory<'a, M> {
82 memory: &'a M,
83 offset: u64,
84}
85
86impl<'a, M: Memory> WriteUpgradeMemory<'a, M> {
87 pub fn new(memory: &'a mut M) -> WriteUpgradeMemory<'a, M> {
89 Self {
90 writer: Writer::new(memory, 0),
91 }
92 }
93
94 pub fn write(&mut self, bytes: &[u8]) -> Result<(), GrowFailed> {
96 self.writer.write(bytes)
97 }
98
99 pub fn write_u32(&mut self, value: u32) -> Result<(), GrowFailed> {
101 let mut bytes = Vec::with_capacity(4);
102 common::u32_to_bytes(&mut bytes, value);
103 self.write(&bytes)
104 }
105
106 pub fn write_u64(&mut self, value: u64) -> Result<(), GrowFailed> {
108 let mut bytes = Vec::with_capacity(8);
109 common::u64_to_bytes(&mut bytes, value);
110 self.write(&bytes)
111 }
112}
113
114impl<'a, M: Memory> ReadUpgradeMemory<'a, M> {
115 pub fn new(memory: &'a M) -> ReadUpgradeMemory<'a, M> {
117 Self { memory, offset: 0 }
118 }
119
120 pub fn read(&mut self, bytes: &mut [u8]) {
122 self.memory.read(self.offset, bytes);
123 self.offset += bytes.len() as u64;
124 }
125
126 pub fn read_u32(&mut self) -> u32 {
128 let mut bytes = [0; 4];
129 self.read(&mut bytes);
130 common::u32_from_bytes(&bytes)
131 }
132
133 pub fn read_u64(&mut self) -> u64 {
135 let mut bytes = [0; 8];
136 self.read(&mut bytes);
137 common::u64_from_bytes(&bytes)
138 }
139}
140
141pub mod common {
143 use super::*;
144
145 #[inline]
147 pub fn usize_to_4bytes(buf: &mut Vec<u8>, value: usize) {
148 buf.extend(&(value as u32).to_bytes()[..]);
149 }
150
151 #[inline]
153 pub fn usize_from_4bytes(bytes: &[u8]) -> usize {
154 u32::from_bytes(Cow::Borrowed(&bytes[..4])) as usize
155 }
156
157 #[inline]
159 pub fn u32_to_bytes(buf: &mut Vec<u8>, value: u32) {
160 buf.extend(&value.to_bytes()[..]);
161 }
162
163 #[inline]
165 pub fn u32_from_bytes(bytes: &[u8]) -> u32 {
166 u32::from_bytes(Cow::Borrowed(&bytes[..4]))
167 }
168
169 #[inline]
171 pub fn u64_to_bytes(buf: &mut Vec<u8>, value: u64) {
172 buf.extend(&value.to_bytes()[..]);
173 }
174
175 #[inline]
177 pub fn u64_from_bytes(bytes: &[u8]) -> u64 {
178 u64::from_bytes(Cow::Borrowed(&bytes[..8]))
179 }
180}