rkyv_test/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        Ok(RcResolver {
65            pos: serializer.serialize_shared(value)?,
66            metadata_resolver: value.serialize_metadata(serializer)?,
67        })
68    }
69}
70
71impl<T: ArchivePointee + ?Sized, F> AsRef<T> for ArchivedRc<T, F> {
72    #[inline]
73    fn as_ref(&self) -> &T {
74        self.get()
75    }
76}
77
78impl<T: ArchivePointee + ?Sized, F> Borrow<T> for ArchivedRc<T, F> {
79    #[inline]
80    fn borrow(&self) -> &T {
81        self.get()
82    }
83}
84
85impl<T: ArchivePointee + fmt::Debug + ?Sized, F> fmt::Debug for ArchivedRc<T, F> {
86    #[inline]
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        self.get().fmt(f)
89    }
90}
91
92impl<T: ArchivePointee + ?Sized, F> Deref for ArchivedRc<T, F> {
93    type Target = T;
94
95    #[inline]
96    fn deref(&self) -> &Self::Target {
97        self.get()
98    }
99}
100
101impl<T: ArchivePointee + fmt::Display + ?Sized, F> fmt::Display for ArchivedRc<T, F> {
102    #[inline]
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        self.get().fmt(f)
105    }
106}
107
108impl<T: ArchivePointee + Eq + ?Sized, F> Eq for ArchivedRc<T, F> {}
109
110impl<T: ArchivePointee + hash::Hash + ?Sized, F> hash::Hash for ArchivedRc<T, F> {
111    fn hash<H: hash::Hasher>(&self, state: &mut H) {
112        self.get().hash(state)
113    }
114}
115
116impl<T: ArchivePointee + Ord + ?Sized, F> Ord for ArchivedRc<T, F> {
117    fn cmp(&self, other: &Self) -> cmp::Ordering {
118        self.get().cmp(other.get())
119    }
120}
121
122impl<T, TF, U, UF> PartialEq<ArchivedRc<U, UF>> for ArchivedRc<T, TF>
123where
124    T: ArchivePointee + PartialEq<U> + ?Sized,
125    U: ArchivePointee + ?Sized,
126{
127    fn eq(&self, other: &ArchivedRc<U, UF>) -> bool {
128        self.get().eq(other.get())
129    }
130}
131
132impl<T, TF, U, UF> PartialOrd<ArchivedRc<U, UF>> for ArchivedRc<T, TF>
133where
134    T: ArchivePointee + PartialOrd<U> + ?Sized,
135    U: ArchivePointee + ?Sized,
136{
137    fn partial_cmp(&self, other: &ArchivedRc<U, UF>) -> Option<cmp::Ordering> {
138        self.get().partial_cmp(other.get())
139    }
140}
141
142impl<T, F> fmt::Pointer for ArchivedRc<T, F> {
143    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144        fmt::Pointer::fmt(&self.0.base(), f)
145    }
146}
147
148/// The resolver for `Rc`.
149pub struct RcResolver<T> {
150    pos: usize,
151    metadata_resolver: T,
152}
153
154/// An archived `rc::Weak`.
155///
156/// This is essentially just an optional [`ArchivedRc`].
157#[repr(u8)]
158pub enum ArchivedRcWeak<T: ArchivePointee + ?Sized, F> {
159    /// A null weak pointer
160    None,
161    /// A weak pointer to some shared pointer
162    Some(ArchivedRc<T, F>),
163}
164
165impl<T: ArchivePointee + ?Sized, F> ArchivedRcWeak<T, F> {
166    /// Attempts to upgrade the weak pointer to an `ArchivedArc`.
167    ///
168    /// Returns `None` if a null weak pointer was serialized.
169    #[inline]
170    pub fn upgrade(&self) -> Option<&ArchivedRc<T, F>> {
171        match self {
172            ArchivedRcWeak::None => None,
173            ArchivedRcWeak::Some(r) => Some(r),
174        }
175    }
176
177    /// Attempts to upgrade a pinned mutable weak pointer.
178    #[inline]
179    pub fn upgrade_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut ArchivedRc<T, F>>> {
180        unsafe {
181            match self.get_unchecked_mut() {
182                ArchivedRcWeak::None => None,
183                ArchivedRcWeak::Some(r) => Some(Pin::new_unchecked(r)),
184            }
185        }
186    }
187
188    /// Resolves an archived `Weak` from a given optional reference.
189    ///
190    /// # Safety
191    ///
192    /// - `pos` must be the position of `out` within the archive
193    /// - `resolver` must be the result of serializing `value`
194    #[inline]
195    pub unsafe fn resolve_from_ref<U: ArchiveUnsized<Archived = T> + ?Sized>(
196        value: Option<&U>,
197        pos: usize,
198        resolver: RcWeakResolver<MetadataResolver<U>>,
199        out: *mut Self,
200    ) {
201        match resolver {
202            RcWeakResolver::None => {
203                let out = out.cast::<ArchivedRcWeakVariantNone>();
204                ptr::addr_of_mut!((*out).0).write(ArchivedRcWeakTag::None);
205            }
206            RcWeakResolver::Some(resolver) => {
207                let out = out.cast::<ArchivedRcWeakVariantSome<T, F>>();
208                ptr::addr_of_mut!((*out).0).write(ArchivedRcWeakTag::Some);
209
210                let (fp, fo) = out_field!(out.1);
211                ArchivedRc::resolve_from_ref(value.unwrap(), pos + fp, resolver, fo);
212            }
213        }
214    }
215
216    /// Serializes an archived `Weak` from a given optional reference.
217    #[inline]
218    pub fn serialize_from_ref<U, S>(
219        value: Option<&U>,
220        serializer: &mut S,
221    ) -> Result<RcWeakResolver<MetadataResolver<U>>, S::Error>
222    where
223        U: SerializeUnsized<S, Archived = T> + ?Sized,
224        S: Serializer + SharedSerializeRegistry + ?Sized,
225    {
226        Ok(match value {
227            None => RcWeakResolver::None,
228            Some(r) => RcWeakResolver::Some(ArchivedRc::<T, F>::serialize_from_ref(r, serializer)?),
229        })
230    }
231}
232
233impl<T: ArchivePointee + fmt::Debug + ?Sized, F> fmt::Debug for ArchivedRcWeak<T, F> {
234    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235        write!(f, "(Weak)")
236    }
237}
238
239/// The resolver for `rc::Weak`.
240pub enum RcWeakResolver<T> {
241    /// The weak pointer was null
242    None,
243    /// The weak pointer was to some shared pointer
244    Some(RcResolver<T>),
245}
246
247#[allow(dead_code)]
248#[repr(u8)]
249enum ArchivedRcWeakTag {
250    None,
251    Some,
252}
253
254#[repr(C)]
255struct ArchivedRcWeakVariantNone(ArchivedRcWeakTag);
256
257#[repr(C)]
258struct ArchivedRcWeakVariantSome<T: ArchivePointee + ?Sized, F>(
259    ArchivedRcWeakTag,
260    ArchivedRc<T, F>,
261);