dungeon_cell/align/
unaligned.rs

1use core::ptr::{addr_of, addr_of_mut, read_unaligned, write_unaligned};
2
3use crate::bound::Dynamic;
4use crate::marker_traits::IsBound;
5use crate::vtable::{ConstVTableOf, VTable, VTableOf, VTableSubset};
6
7/// Force value to be unaligned.
8///
9/// Because all borrows must be properly aligned, this type doesn't give out
10/// borrows to the inner type. However, if the inner type is [`Copy`] then the stored
11/// value can be accessed using [`Self::into_inner`].
12#[repr(C, packed)]
13pub struct Unaligned<T> {
14    value: T,
15}
16
17impl<T> Unaligned<T> {
18    /// Create new unaligned value.
19    ///
20    /// The returned type will have an alignment of 1 byte.
21    pub const fn new(value: T) -> Self {
22        Self { value }
23    }
24
25    /// Convert into inner value.
26    ///
27    /// The returned value will have it's normal alignment.
28    pub fn into_inner(self) -> T {
29        self.value
30    }
31
32    /// Replace the currently stored value.
33    pub fn replace(&mut self, value: T) -> T {
34        // Read the value currently stored (acts as move out).
35        // SAFETY: We know the pointer is valid because we have a &mut self.
36        let old = unsafe { read_unaligned(self.as_ptr()) };
37
38        // Write the new value (acts as move int).
39        // SAFETY: We know the pointer is valid because we have a &mut self.
40        unsafe { write_unaligned(self.as_mut_ptr(), value) };
41
42        old
43    }
44
45    /// Get unaligned pointer to the inner value.
46    ///
47    /// The returned pointer cannot be made into a borrow or used
48    /// with normal pointer functions unless the type `T` already has
49    /// an alignment of 1 byte.
50    pub fn as_ptr(&self) -> *const T {
51        addr_of!(self.value)
52    }
53
54    /// Get unaligned mutable pointer to the inner value.
55    ///
56    /// The returned pointer cannot be made into a borrow or used
57    /// with normal pointer functions unless the type `T` already has
58    /// an alignment of 1 byte.
59    pub fn as_mut_ptr(&mut self) -> *mut T {
60        addr_of_mut!(self.value)
61    }
62}
63
64impl<T: Copy> Copy for Unaligned<T> {}
65
66impl<T: Copy> Clone for Unaligned<T> {
67    #[inline]
68    fn clone(&self) -> Self {
69        *self
70    }
71}
72
73// SAFETY: Forwards implementation to T.
74unsafe impl<T: VTable> VTable for Unaligned<&T> {
75    type Bounds = T::Bounds;
76
77    type Id = T::Id;
78
79    fn descriptor(&self) -> &crate::vtable::Descriptor<Self::Id> {
80        T::descriptor(self.into_inner())
81    }
82
83    fn bound_impl(&self) -> &crate::vtable::BoundsImpl<Self::Bounds> {
84        T::bound_impl(self.into_inner())
85    }
86}
87
88// SAFETY: The type we describe doesnt change.
89unsafe impl<'a, T: VTable, Bnew: IsBound> VTableSubset<Bnew>
90    for Unaligned<&'a T>
91where
92    &'a T: VTableSubset<Bnew>,
93    <&'a T as VTableSubset<Bnew>>::Subset: Copy,
94    Unaligned<<&'a T as VTableSubset<Bnew>>::Subset>: VTable<Bounds = Bnew>,
95{
96    type Subset = Unaligned<<&'a T as VTableSubset<Bnew>>::Subset>;
97
98    fn into_subset(self) -> Self::Subset {
99        Unaligned::new(self.into_inner().into_subset())
100    }
101}
102
103// SAFETY: Forwards implementation to T.
104unsafe impl<'a, T: VTable, U: Dynamic<T::Bounds>> VTableOf<U>
105    for Unaligned<&'a T>
106where
107    &'a T: VTableOf<U, Bounds = T::Bounds>,
108{
109    fn instance() -> Self {
110        Unaligned::new(<&T>::instance())
111    }
112}
113
114// SAFETY: Forwards implementation to T.
115unsafe impl<'a, T: VTable, U: Dynamic<T::Bounds>> ConstVTableOf<U>
116    for Unaligned<&'a T>
117where
118    &'a T: ConstVTableOf<U, Bounds = T::Bounds>,
119{
120    const INSTANCE: Self = Unaligned::new(<&T>::INSTANCE);
121}