ic_stable_memory/primitive/
s_ref.rs1use crate::encoding::AsFixedSizeBytes;
2use crate::primitive::StableType;
3use candid::types::{Serializer, Type, TypeId};
4use candid::CandidType;
5use std::cell::UnsafeCell;
6use std::marker::PhantomData;
7use std::ops::Deref;
8
9pub struct SRef<'o, T> {
18 ptr: u64,
19 inner: UnsafeCell<Option<T>>,
20 _marker: PhantomData<&'o T>,
21}
22
23impl<'o, T> SRef<'o, T> {
24 #[inline]
29 pub unsafe fn new(ptr: u64) -> Self {
30 Self {
31 ptr,
32 inner: UnsafeCell::new(None),
33 _marker: PhantomData::default(),
34 }
35 }
36}
37
38impl<'o, T: StableType + AsFixedSizeBytes> SRef<'o, T> {
39 unsafe fn read(&self) {
40 if (*self.inner.get()).is_none() {
41 let it = crate::mem::read_fixed_for_reference(self.ptr);
42 *self.inner.get() = Some(it);
43 }
44 }
45}
46
47impl<'o, T: StableType + AsFixedSizeBytes> Deref for SRef<'o, T> {
48 type Target = T;
49
50 #[inline]
51 fn deref(&self) -> &Self::Target {
52 unsafe {
53 self.read();
54
55 (*self.inner.get()).as_ref().unwrap()
56 }
57 }
58}
59
60impl<'o, T: StableType + AsFixedSizeBytes + CandidType> CandidType for SRef<'o, T> {
61 #[inline]
62 fn _ty() -> Type {
63 T::_ty()
64 }
65
66 #[inline]
67 fn idl_serialize<S>(&self, serializer: S) -> Result<(), S::Error>
68 where
69 S: Serializer,
70 {
71 unsafe {
72 self.read();
73
74 (*self.inner.get())
75 .as_ref()
76 .unwrap()
77 .idl_serialize(serializer)
78 }
79 }
80}