Skip to main content

rkyv/
seal.rs

1//! Mutable references to values which may not be moved or de-initialized.
2
3use core::{
4    ops::{Deref, DerefMut},
5    slice::SliceIndex,
6};
7
8use munge::{Borrow, Destructure, Restructure};
9
10use crate::traits::NoUndef;
11
12/// A mutable reference which may not be moved or assigned.
13///
14/// A `Seal` restricts a mutable reference so that the referenced value cannot
15/// be moved or assigned unless it is `Unpin` and `NoUndef`. These properties
16/// allow the safe use of mutable archived values.
17///
18/// Unlike `Pin`, all fields of `Seal`ed values are also sealed. There is no
19/// notion of "structural sealing" as there is structural pinning. This has the
20/// upside that a `Seal` can be uniformly destructured with `munge`, which is
21/// the recommended replacement for `Pin`'s `map_unchecked_mut` function. Also
22/// unlike `Pin`, `Seal`ing a reference does not require upholding the invariant
23/// that the sealed value is dropped before its backing memory is reused. This
24/// means that creating a `Seal` from a mutable reference is completely safe to
25/// do.
26pub struct Seal<'a, T: ?Sized> {
27    inner: &'a mut T,
28}
29
30impl<'a, T: ?Sized> Seal<'a, T> {
31    /// Returns a new `Seal` wrapping the given reference.
32    pub fn new(inner: &'a mut T) -> Self {
33        Self { inner }
34    }
35
36    /// Returns the underlying reference for types that implement `NoUndef`
37    /// and `Unpin`.
38    pub fn unseal(self) -> &'a mut T
39    where
40        T: NoUndef + Unpin,
41    {
42        self.inner
43    }
44
45    /// Returns the underlying reference as shared for types that implement
46    /// `Portable`.
47    pub fn unseal_ref(self) -> &'a T {
48        self.inner
49    }
50
51    /// Returns the underlying reference.
52    ///
53    /// # Safety
54    ///
55    /// The returned reference may not be moved unless `T` is `Unpin`.
56    /// Uninitialized bytes may not be written through the `Seal`.
57    pub unsafe fn unseal_unchecked(self) -> &'a mut T {
58        self.inner
59    }
60
61    /// Mutably reborrows the `Seal`.
62    pub fn as_mut(&mut self) -> Seal<'_, T> {
63        Seal::new(self.inner)
64    }
65}
66
67impl<T: ?Sized> AsRef<T> for Seal<'_, T> {
68    fn as_ref(&self) -> &T {
69        self.inner
70    }
71}
72
73impl<T: ?Sized> Deref for Seal<'_, T> {
74    type Target = T;
75
76    fn deref(&self) -> &Self::Target {
77        self.as_ref()
78    }
79}
80
81impl<T: NoUndef + Unpin + ?Sized> DerefMut for Seal<'_, T> {
82    fn deref_mut(&mut self) -> &mut Self::Target {
83        self.as_mut().unseal()
84    }
85}
86
87unsafe impl<T: ?Sized> Destructure for Seal<'_, T> {
88    type Underlying = T;
89    type Destructuring = Borrow;
90
91    fn underlying(&mut self) -> *mut Self::Underlying {
92        self.inner
93    }
94}
95
96unsafe impl<'a, T: ?Sized, U: 'a + ?Sized> Restructure<U> for Seal<'a, T> {
97    type Restructured = Seal<'a, U>;
98
99    unsafe fn restructure(&self, ptr: *mut U) -> Self::Restructured {
100        // SAFETY: `ptr` is a pointer to a subfield of the underlying pointer,
101        // and so is also properly aligned, and dereferenceable.
102        Seal::new(unsafe { &mut *ptr })
103    }
104}
105
106impl<'a, T> Seal<'a, [T]> {
107    /// Indexes the `Seal`.
108    ///
109    /// # Panics
110    ///
111    /// May panic if the index is out of bounds.
112    pub fn index<I: SliceIndex<[T]>>(
113        self,
114        index: I,
115    ) -> Seal<'a, <I as SliceIndex<[T]>>::Output> {
116        let ptr = unsafe { Seal::unseal_unchecked(self) };
117        Seal::new(&mut ptr[index])
118    }
119}