ic_stable_memory/primitive/
mod.rs

1//! Smart-pointers and [StableType] trait
2
3use candid::{Int, Nat, Principal};
4use serde_bytes::ByteBuf;
5use std::collections::{BTreeSet, HashSet};
6
7/// [SBox] smart-pointer that allows storing dynamically-sized data to stable memory
8pub mod s_box;
9
10/// Immutable reference to fixed size data on stable memory
11pub mod s_ref;
12
13/// Mutable reference to fixed size data on stable memory
14pub mod s_ref_mut;
15
16/// Anything that can be stored on stable memory should implement this trait.
17///
18/// *None of methods of this trait should be called manually, unless you're implementing your own
19/// stable data structure!*
20///
21/// This trait defines behavior for stable drop function and stable drop flag interactions.
22/// In order to implement this trait for a data type, there are two options:
23/// 1. Use [derive::StableType](crate::derive::StableType) derive macro. This macro requires that any
24/// field of your data type also implements [StableType] trait. For most cases consider this option.
25/// Supports non-generic structs and enums.
26/// 2. Implement it yourself. For data types which do not contain any stable structures inside, default
27/// implementation will work fine. For data types which do contain stable structures, the implementation
28/// should definitely override [StableType::stable_drop_flag_off] and [StableType::stable_drop::flag_on]
29/// calling the same methods on the underlying stable structures. If you want to implement your own
30/// stable data structure, you should definitely implement this trait completely, overriding all of
31/// its methods.
32///
33/// # Examples
34/// ```rust
35/// # use ic_stable_memory::collections::SVec;
36/// # use ic_stable_memory::SBox;
37/// # use ic_stable_memory::derive::StableType;
38///
39/// // implement using derive macro
40/// #[derive(StableType)]
41/// struct A {
42///     x: u64,
43///     y: [u32; 4],
44///     z: Option<SVec<SBox<String>>>,
45/// }
46/// ```
47///
48/// ```rust
49/// // provide default implementation, if the type does not contain any stable structures
50/// # use ic_stable_memory::StableType;
51/// struct A {
52///     x: u64,
53///     y: [u32; 4],
54/// }
55///
56/// impl StableType for A {}
57/// ```
58///
59/// ```rust
60/// # use ic_stable_memory::StableType;
61/// enum MyOption<T> {
62///     Some(T),
63///     None,
64/// }
65///
66/// // provide proxy implementation for generics or types which contain stable data structures inside
67/// impl<T: StableType> StableType for MyOption<T> {
68///     unsafe fn stable_drop_flag_on(&mut self) {
69///         if let MyOption::Some(it) = self {
70///             it.stable_drop_flag_on();
71///         }
72///     }
73///
74///     unsafe fn stable_drop_flag_off(&mut self) {
75///         if let MyOption::Some(it) = self {
76///             it.stable_drop_flag_off();
77///         }
78///     }
79/// }
80/// ```
81///
82/// ```rust
83/// // provide full implementation, if you're building new stable data structure
84/// # use ic_stable_memory::mem::StablePtr;
85/// # use ic_stable_memory::StableType;
86/// struct ExampleStableDataStructure {
87///     drop_flag: bool,
88///     ptr: StablePtr,
89/// }
90///
91/// impl StableType for ExampleStableDataStructure {
92///     fn should_stable_drop(&self) -> bool {
93///         self.drop_flag
94///     }
95///
96///     unsafe fn stable_drop_flag_on(&mut self) {
97///        self.drop_flag = true;
98///     }
99///
100///     unsafe fn stable_drop_flag_off(&mut self) {
101///         self.drop_flag = false;
102///     }
103///
104///     unsafe fn stable_drop(&mut self) {
105///         // deallocate any stable memory managed by this data structure
106///     }
107/// }
108/// ```
109pub trait StableType {
110    /// Sets stable drop flag to `off` position, if it is applicable
111    ///
112    /// # Safety
113    /// Setting stable drop flag to an invalid position will lead to memory leaks and unexpected panics
114    /// and considered undefined behavior.
115    #[inline]
116    unsafe fn stable_drop_flag_off(&mut self) {}
117
118    /// Should set stable drop flag to `on` position, if it is applicable
119    ///
120    /// # Safety
121    /// Setting stable drop flag to an invalid position will lead to memory leaks and unexpected panics
122    /// and considered undefined behavior.
123    #[inline]
124    unsafe fn stable_drop_flag_on(&mut self) {}
125
126    /// Should return the value of the stable drop flag
127    #[inline]
128    fn should_stable_drop(&self) -> bool {
129        false
130    }
131
132    /// Performs stable drop, releasing all underlying stable memory of this data structure
133    ///
134    /// You only want to implement this trait method, if you're building your own stable data structure.
135    /// In that case you may want to call this method during [Drop], so your data structure will clean
136    /// itself automatically. You may also want to call this method during some dropping or transforming
137    /// methods of your data structure, like `into_inner()` or `into_<type_name>().
138    ///
139    /// # Safety
140    /// Performing stable drop twice is undefined behavior.
141    ///
142    /// # Example
143    /// Implementation of [Drop] for your stable data structure should look something like this
144    /// ```rust
145    /// # use ic_stable_memory::StableType;
146    /// struct A {}
147    ///
148    /// impl StableType for A {
149    ///     // implement as usual
150    /// }
151    ///
152    /// impl Drop for A {
153    ///     fn drop(&mut self) {
154    ///         if self.should_stable_drop() {
155    ///             unsafe { self.stable_drop(); }
156    ///         }    
157    ///     }
158    /// }
159    /// ```
160    #[inline]
161    unsafe fn stable_drop(&mut self) {}
162}
163
164impl StableType for () {}
165impl StableType for bool {}
166impl StableType for u8 {}
167impl StableType for i8 {}
168impl StableType for u16 {}
169impl StableType for i16 {}
170impl StableType for u32 {}
171impl StableType for i32 {}
172impl StableType for u64 {}
173impl StableType for i64 {}
174impl StableType for u128 {}
175impl StableType for i128 {}
176impl StableType for usize {}
177impl StableType for isize {}
178impl StableType for f32 {}
179impl StableType for f64 {}
180impl StableType for char {}
181impl StableType for Principal {}
182impl StableType for Nat {}
183impl StableType for Int {}
184
185impl<const N: usize> StableType for [(); N] {}
186impl<const N: usize> StableType for [bool; N] {}
187impl<const N: usize> StableType for [u8; N] {}
188impl<const N: usize> StableType for [i8; N] {}
189impl<const N: usize> StableType for [u16; N] {}
190impl<const N: usize> StableType for [i16; N] {}
191impl<const N: usize> StableType for [u32; N] {}
192impl<const N: usize> StableType for [i32; N] {}
193impl<const N: usize> StableType for [u64; N] {}
194impl<const N: usize> StableType for [i64; N] {}
195impl<const N: usize> StableType for [u128; N] {}
196impl<const N: usize> StableType for [i128; N] {}
197impl<const N: usize> StableType for [usize; N] {}
198impl<const N: usize> StableType for [isize; N] {}
199impl<const N: usize> StableType for [f32; N] {}
200impl<const N: usize> StableType for [f64; N] {}
201impl<const N: usize> StableType for [char; N] {}
202impl<const N: usize> StableType for [String; N] {}
203impl<const N: usize> StableType for [Principal; N] {}
204impl<const N: usize> StableType for [Nat; N] {}
205impl<const N: usize> StableType for [Int; N] {}
206
207impl StableType for ByteBuf {}
208impl<T: StableType> StableType for Option<T> {
209    #[inline]
210    unsafe fn stable_drop_flag_on(&mut self) {
211        if let Some(it) = self {
212            it.stable_drop_flag_on();
213        }
214    }
215
216    #[inline]
217    unsafe fn stable_drop_flag_off(&mut self) {
218        if let Some(it) = self {
219            it.stable_drop_flag_off();
220        }
221    }
222}
223impl<const N: usize> StableType for [ByteBuf; N] {}
224
225impl<A: StableType> StableType for (A,) {
226    #[inline]
227    unsafe fn stable_drop_flag_on(&mut self) {
228        self.0.stable_drop_flag_on();
229    }
230
231    #[inline]
232    unsafe fn stable_drop_flag_off(&mut self) {
233        self.0.stable_drop_flag_off();
234    }
235}
236
237impl<A: StableType, B: StableType> StableType for (A, B) {
238    #[inline]
239    unsafe fn stable_drop_flag_on(&mut self) {
240        self.0.stable_drop_flag_on();
241        self.1.stable_drop_flag_on();
242    }
243
244    #[inline]
245    unsafe fn stable_drop_flag_off(&mut self) {
246        self.0.stable_drop_flag_off();
247        self.1.stable_drop_flag_off();
248    }
249}
250
251impl<A: StableType, B: StableType, C: StableType> StableType for (A, B, C) {
252    #[inline]
253    unsafe fn stable_drop_flag_on(&mut self) {
254        self.0.stable_drop_flag_on();
255        self.1.stable_drop_flag_on();
256        self.2.stable_drop_flag_on();
257    }
258
259    #[inline]
260    unsafe fn stable_drop_flag_off(&mut self) {
261        self.0.stable_drop_flag_off();
262        self.1.stable_drop_flag_off();
263        self.2.stable_drop_flag_off();
264    }
265}
266
267impl<A: StableType, B: StableType, C: StableType, D: StableType> StableType for (A, B, C, D) {
268    #[inline]
269    unsafe fn stable_drop_flag_on(&mut self) {
270        self.0.stable_drop_flag_on();
271        self.1.stable_drop_flag_on();
272        self.2.stable_drop_flag_on();
273        self.3.stable_drop_flag_on();
274    }
275
276    #[inline]
277    unsafe fn stable_drop_flag_off(&mut self) {
278        self.0.stable_drop_flag_off();
279        self.1.stable_drop_flag_off();
280        self.2.stable_drop_flag_off();
281        self.3.stable_drop_flag_off();
282    }
283}
284
285impl<A: StableType, B: StableType, C: StableType, D: StableType, E: StableType> StableType
286    for (A, B, C, D, E)
287{
288    #[inline]
289    unsafe fn stable_drop_flag_on(&mut self) {
290        self.0.stable_drop_flag_on();
291        self.1.stable_drop_flag_on();
292        self.2.stable_drop_flag_on();
293        self.3.stable_drop_flag_on();
294        self.4.stable_drop_flag_on();
295    }
296
297    #[inline]
298    unsafe fn stable_drop_flag_off(&mut self) {
299        self.0.stable_drop_flag_off();
300        self.1.stable_drop_flag_off();
301        self.2.stable_drop_flag_off();
302        self.3.stable_drop_flag_off();
303        self.4.stable_drop_flag_off();
304    }
305}
306
307impl<A: StableType, B: StableType, C: StableType, D: StableType, E: StableType, F: StableType>
308    StableType for (A, B, C, D, E, F)
309{
310    #[inline]
311    unsafe fn stable_drop_flag_on(&mut self) {
312        self.0.stable_drop_flag_on();
313        self.1.stable_drop_flag_on();
314        self.2.stable_drop_flag_on();
315        self.3.stable_drop_flag_on();
316        self.4.stable_drop_flag_on();
317        self.5.stable_drop_flag_on();
318    }
319
320    #[inline]
321    unsafe fn stable_drop_flag_off(&mut self) {
322        self.0.stable_drop_flag_off();
323        self.1.stable_drop_flag_off();
324        self.2.stable_drop_flag_off();
325        self.3.stable_drop_flag_off();
326        self.4.stable_drop_flag_off();
327        self.5.stable_drop_flag_off();
328    }
329}
330
331impl StableType for String {}
332impl StableType for Vec<u8> {}
333impl StableType for Vec<i8> {}
334impl StableType for Vec<u16> {}
335impl StableType for Vec<i16> {}
336impl StableType for Vec<u32> {}
337impl StableType for Vec<i32> {}
338impl StableType for Vec<u64> {}
339impl StableType for Vec<i64> {}
340impl StableType for Vec<u128> {}
341impl StableType for Vec<i128> {}
342impl StableType for Vec<usize> {}
343impl StableType for Vec<isize> {}
344impl StableType for Vec<f32> {}
345impl StableType for Vec<f64> {}
346impl StableType for Vec<()> {}
347impl StableType for Vec<bool> {}
348impl StableType for Vec<char> {}
349impl StableType for Vec<String> {}
350impl StableType for Vec<Principal> {}
351impl StableType for Vec<Nat> {}
352impl StableType for Vec<Int> {}
353impl StableType for Vec<ByteBuf> {}
354
355impl StableType for HashSet<u8> {}
356impl StableType for HashSet<i8> {}
357impl StableType for HashSet<u16> {}
358impl StableType for HashSet<i16> {}
359impl StableType for HashSet<u32> {}
360impl StableType for HashSet<i32> {}
361impl StableType for HashSet<u64> {}
362impl StableType for HashSet<i64> {}
363impl StableType for HashSet<u128> {}
364impl StableType for HashSet<i128> {}
365impl StableType for HashSet<usize> {}
366impl StableType for HashSet<isize> {}
367impl StableType for HashSet<f32> {}
368impl StableType for HashSet<f64> {}
369impl StableType for HashSet<()> {}
370impl StableType for HashSet<bool> {}
371impl StableType for HashSet<char> {}
372impl StableType for HashSet<String> {}
373impl StableType for HashSet<Principal> {}
374impl StableType for HashSet<Nat> {}
375impl StableType for HashSet<Int> {}
376impl StableType for HashSet<ByteBuf> {}
377
378impl StableType for BTreeSet<u8> {}
379impl StableType for BTreeSet<i8> {}
380impl StableType for BTreeSet<u16> {}
381impl StableType for BTreeSet<i16> {}
382impl StableType for BTreeSet<u32> {}
383impl StableType for BTreeSet<i32> {}
384impl StableType for BTreeSet<u64> {}
385impl StableType for BTreeSet<i64> {}
386impl StableType for BTreeSet<u128> {}
387impl StableType for BTreeSet<i128> {}
388impl StableType for BTreeSet<usize> {}
389impl StableType for BTreeSet<isize> {}
390impl StableType for BTreeSet<f32> {}
391impl StableType for BTreeSet<f64> {}
392impl StableType for BTreeSet<()> {}
393impl StableType for BTreeSet<bool> {}
394impl StableType for BTreeSet<char> {}
395impl StableType for BTreeSet<String> {}
396impl StableType for BTreeSet<Principal> {}
397impl StableType for BTreeSet<Nat> {}
398impl StableType for BTreeSet<Int> {}
399impl StableType for BTreeSet<ByteBuf> {}