ic_stable_memory/primitive/
s_ref_mut.rs1use crate::encoding::AsFixedSizeBytes;
2use crate::primitive::StableType;
3use candid::types::{Serializer, Type};
4use candid::CandidType;
5use std::cell::UnsafeCell;
6use std::marker::PhantomData;
7use std::ops::{Deref, DerefMut};
8
9pub struct SRefMut<'o, T: StableType + AsFixedSizeBytes> {
19 ptr: u64,
20 inner: UnsafeCell<Option<T>>,
21 _marker: PhantomData<&'o mut T>,
22}
23
24impl<'o, T: StableType + AsFixedSizeBytes> SRefMut<'o, T> {
25 #[inline]
30 pub unsafe fn new(ptr: u64) -> Self {
31 Self {
32 ptr,
33 inner: UnsafeCell::new(None),
34 _marker: PhantomData::default(),
35 }
36 }
37
38 #[inline]
39 unsafe fn read(&self) {
40 if (*self.inner.get()).is_none() {
41 let it = crate::mem::read_fixed_for_move(self.ptr);
42 *self.inner.get() = Some(it);
43 }
44 }
45
46 #[inline]
47 unsafe fn repersist(&mut self) {
48 if let Some(it) = self.inner.get_mut() {
49 crate::mem::write_fixed(self.ptr, it);
50 }
51 }
52}
53
54impl<'o, T: StableType + AsFixedSizeBytes> Deref for SRefMut<'o, T> {
55 type Target = T;
56
57 #[inline]
58 fn deref(&self) -> &Self::Target {
59 unsafe {
60 self.read();
61
62 (*self.inner.get()).as_ref().unwrap()
63 }
64 }
65}
66
67impl<'o, T: StableType + AsFixedSizeBytes> DerefMut for SRefMut<'o, T> {
68 #[inline]
69 fn deref_mut(&mut self) -> &mut Self::Target {
70 unsafe { self.read() };
71
72 self.inner.get_mut().as_mut().unwrap()
73 }
74}
75
76impl<'o, T: StableType + AsFixedSizeBytes> Drop for SRefMut<'o, T> {
77 #[inline]
78 fn drop(&mut self) {
79 unsafe { self.repersist() };
80 }
81}
82
83impl<'o, T: StableType + AsFixedSizeBytes + CandidType> CandidType for SRefMut<'o, T> {
84 #[inline]
85 fn _ty() -> Type {
86 T::_ty()
87 }
88
89 #[inline]
90 fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
91 where
92 S: Serializer,
93 {
94 unsafe {
95 self.read();
96
97 (*self.inner.get())
98 .as_ref()
99 .unwrap()
100 .idl_serialize(serializer)
101 }
102 }
103}