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}