rkyv/rc/
mod.rs

1//! Archived versions of shared pointers.
2
3#[cfg(feature = "validation")]
4pub mod validation;
5
6use crate::{
7    ser::{Serializer, SharedSerializeRegistry},
8    ArchivePointee, ArchiveUnsized, MetadataResolver, RelPtr, SerializeUnsized,
9};
10use core::{borrow::Borrow, cmp, fmt, hash, marker::PhantomData, ops::Deref, pin::Pin, ptr};
11
12/// An archived `Rc`.
13///
14/// This is a thin wrapper around a [`RelPtr`] to the archived type paired with a "flavor" type.
15/// Because there may be many varieties of shared pointers and they may not be used together, the
16/// flavor helps check that memory is not being shared incorrectly during validation.
17#[repr(transparent)]
18pub struct ArchivedRc<T: ArchivePointee + ?Sized, F>(RelPtr<T>, PhantomData<F>);
19
20impl<T: ArchivePointee + ?Sized, F> ArchivedRc<T, F> {
21    /// Gets the value of the `ArchivedRc`.
22    #[inline]
23    pub fn get(&self) -> &T {
24        unsafe { &*self.0.as_ptr() }
25    }
26
27    /// Gets the pinned mutable value of this `ArchivedRc`.
28    ///
29    /// # Safety
30    ///
31    /// Any other `ArchivedRc` pointers to the same value must not be dereferenced for the duration
32    /// of the returned borrow.
33    #[inline]
34    pub unsafe fn get_pin_mut_unchecked(self: Pin<&mut Self>) -> Pin<&mut T> {
35        self.map_unchecked_mut(|s| &mut *s.0.as_mut_ptr())
36    }
37
38    /// Resolves an archived `Rc` from a given reference.
39    ///
40    /// # Safety
41    ///
42    /// - `pos` must be the position of `out` within the archive
43    /// - `resolver` must be the result of serializing `value`
44    #[inline]
45    pub unsafe fn resolve_from_ref<U: ArchiveUnsized<Archived = T> + ?Sized>(
46        value: &U,
47        pos: usize,
48        resolver: RcResolver<MetadataResolver<U>>,
49        out: *mut Self,
50    ) {
51        let (fp, fo) = out_field!(out.0);
52        value.resolve_unsized(pos + fp, resolver.pos, resolver.metadata_resolver, fo);
53    }
54
55    /// Serializes an archived `Rc` from a given reference.
56    #[inline]
57    pub fn serialize_from_ref<
58        U: SerializeUnsized<S> + ?Sized,
59        S: Serializer + SharedSerializeRegistry + ?Sized,
60    >(
61        value: &U,
62        serializer: &mut S,
63    ) -> Result<RcResolver<MetadataResolver<U>>, S::Error> {
64        let pos = serializer.serialize_shared(value)?;
65
66        // The positions of serialized `Rc` values must be unique. If we didn't
67        // write any data by serializing `value`, pad the serializer by a byte
68        // to ensure that our position will be unique.
69        if serializer.pos() == pos {
70            serializer.pad(1)?;
71        }
72
73        Ok(RcResolver {
74            pos,
75            metadata_resolver: value.serialize_metadata(serializer)?,
76        })
77    }
78}
79
80impl<T: ArchivePointee + ?Sized, F> AsRef<T> for ArchivedRc<T, F> {
81    #[inline]
82    fn as_ref(&self) -> &T {
83        self.get()
84    }
85}
86
87impl<T: ArchivePointee + ?Sized, F> Borrow<T> for ArchivedRc<T, F> {
88    #[inline]
89    fn borrow(&self) -> &T {
90        self.get()
91    }
92}
93
94impl<T: ArchivePointee + fmt::Debug + ?Sized, F> fmt::Debug for ArchivedRc<T, F> {
95    #[inline]
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        self.get().fmt(f)
98    }
99}
100
101impl<T: ArchivePointee + ?Sized, F> Deref for ArchivedRc<T, F> {
102    type Target = T;
103
104    #[inline]
105    fn deref(&self) -> &Self::Target {
106        self.get()
107    }
108}
109
110impl<T: ArchivePointee + fmt::Display + ?Sized, F> fmt::Display for ArchivedRc<T, F> {
111    #[inline]
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113        self.get().fmt(f)
114    }
115}
116
117impl<T: ArchivePointee + Eq + ?Sized, F> Eq for ArchivedRc<T, F> {}
118
119impl<T: ArchivePointee + hash::Hash + ?Sized, F> hash::Hash for ArchivedRc<T, F> {
120    fn hash<H: hash::Hasher>(&self, state: &mut H) {
121        self.get().hash(state)
122    }
123}
124
125impl<T: ArchivePointee + Ord + ?Sized, F> Ord for ArchivedRc<T, F> {
126    fn cmp(&self, other: &Self) -> cmp::Ordering {
127        self.get().cmp(other.get())
128    }
129}
130
131impl<T, TF, U, UF> PartialEq<ArchivedRc<U, UF>> for ArchivedRc<T, TF>
132where
133    T: ArchivePointee + PartialEq<U> + ?Sized,
134    U: ArchivePointee + ?Sized,
135{
136    fn eq(&self, other: &ArchivedRc<U, UF>) -> bool {
137        self.get().eq(other.get())
138    }
139}
140
141impl<T, TF, U, UF> PartialOrd<ArchivedRc<U, UF>> for ArchivedRc<T, TF>
142where
143    T: ArchivePointee + PartialOrd<U> + ?Sized,
144    U: ArchivePointee + ?Sized,
145{
146    fn partial_cmp(&self, other: &ArchivedRc<U, UF>) -> Option<cmp::Ordering> {
147        self.get().partial_cmp(other.get())
148    }
149}
150
151impl<T, F> fmt::Pointer for ArchivedRc<T, F> {
152    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153        fmt::Pointer::fmt(&self.0.base(), f)
154    }
155}
156
157/// The resolver for `Rc`.
158pub struct RcResolver<T> {
159    pos: usize,
160    metadata_resolver: T,
161}
162
163/// An archived `rc::Weak`.
164///
165/// This is essentially just an optional [`ArchivedRc`].
166#[repr(u8)]
167pub enum ArchivedRcWeak<T: ArchivePointee + ?Sized, F> {
168    /// A null weak pointer
169    None,
170    /// A weak pointer to some shared pointer
171    Some(ArchivedRc<T, F>),
172}
173
174impl<T: ArchivePointee + ?Sized, F> ArchivedRcWeak<T, F> {
175    /// Attempts to upgrade the weak pointer to an `ArchivedArc`.
176    ///
177    /// Returns `None` if a null weak pointer was serialized.
178    #[inline]
179    pub fn upgrade(&self) -> Option<&ArchivedRc<T, F>> {
180        match self {
181            ArchivedRcWeak::None => None,
182            ArchivedRcWeak::Some(r) => Some(r),
183        }
184    }
185
186    /// Attempts to upgrade a pinned mutable weak pointer.
187    #[inline]
188    pub fn upgrade_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut ArchivedRc<T, F>>> {
189        unsafe {
190            match self.get_unchecked_mut() {
191                ArchivedRcWeak::None => None,
192                ArchivedRcWeak::Some(r) => Some(Pin::new_unchecked(r)),
193            }
194        }
195    }
196
197    /// Resolves an archived `Weak` from a given optional reference.
198    ///
199    /// # Safety
200    ///
201    /// - `pos` must be the position of `out` within the archive
202    /// - `resolver` must be the result of serializing `value`
203    #[inline]
204    pub unsafe fn resolve_from_ref<U: ArchiveUnsized<Archived = T> + ?Sized>(
205        value: Option<&U>,
206        pos: usize,
207        resolver: RcWeakResolver<MetadataResolver<U>>,
208        out: *mut Self,
209    ) {
210        match resolver {
211            RcWeakResolver::None => {
212                let out = out.cast::<ArchivedRcWeakVariantNone>();
213                ptr::addr_of_mut!((*out).0).write(ArchivedRcWeakTag::None);
214            }
215            RcWeakResolver::Some(resolver) => {
216                let out = out.cast::<ArchivedRcWeakVariantSome<T, F>>();
217                ptr::addr_of_mut!((*out).0).write(ArchivedRcWeakTag::Some);
218
219                let (fp, fo) = out_field!(out.1);
220                ArchivedRc::resolve_from_ref(value.unwrap(), pos + fp, resolver, fo);
221            }
222        }
223    }
224
225    /// Serializes an archived `Weak` from a given optional reference.
226    #[inline]
227    pub fn serialize_from_ref<U, S>(
228        value: Option<&U>,
229        serializer: &mut S,
230    ) -> Result<RcWeakResolver<MetadataResolver<U>>, S::Error>
231    where
232        U: SerializeUnsized<S, Archived = T> + ?Sized,
233        S: Serializer + SharedSerializeRegistry + ?Sized,
234    {
235        Ok(match value {
236            None => RcWeakResolver::None,
237            Some(r) => RcWeakResolver::Some(ArchivedRc::<T, F>::serialize_from_ref(r, serializer)?),
238        })
239    }
240}
241
242impl<T: ArchivePointee + fmt::Debug + ?Sized, F> fmt::Debug for ArchivedRcWeak<T, F> {
243    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244        write!(f, "(Weak)")
245    }
246}
247
248/// The resolver for `rc::Weak`.
249pub enum RcWeakResolver<T> {
250    /// The weak pointer was null
251    None,
252    /// The weak pointer was to some shared pointer
253    Some(RcResolver<T>),
254}
255
256#[allow(dead_code)]
257#[repr(u8)]
258enum ArchivedRcWeakTag {
259    None,
260    Some,
261}
262
263#[repr(C)]
264struct ArchivedRcWeakVariantNone(ArchivedRcWeakTag);
265
266#[repr(C)]
267struct ArchivedRcWeakVariantSome<T: ArchivePointee + ?Sized, F>(
268    ArchivedRcWeakTag,
269    ArchivedRc<T, F>,
270);