1*499dc02cSMiguel Ojeda // SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT 2*499dc02cSMiguel Ojeda 3c3739801SMiguel Ojeda // Copyright 2023 The Fuchsia Authors 4c3739801SMiguel Ojeda // 5c3739801SMiguel Ojeda // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 6c3739801SMiguel Ojeda // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT 7c3739801SMiguel Ojeda // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. 8c3739801SMiguel Ojeda // This file may not be copied, modified, or distributed except according to 9c3739801SMiguel Ojeda // those terms. 10c3739801SMiguel Ojeda 11c3739801SMiguel Ojeda use core::{fmt, hash::Hash}; 12c3739801SMiguel Ojeda 13c3739801SMiguel Ojeda use super::*; 14c3739801SMiguel Ojeda use crate::pointer::{invariant::Valid, SizeEq, TransmuteFrom}; 15c3739801SMiguel Ojeda 16c3739801SMiguel Ojeda /// A type with no alignment requirement. 17c3739801SMiguel Ojeda /// 18c3739801SMiguel Ojeda /// An `Unalign` wraps a `T`, removing any alignment requirement. `Unalign<T>` 19c3739801SMiguel Ojeda /// has the same size and bit validity as `T`, but not necessarily the same 20c3739801SMiguel Ojeda /// alignment [or ABI]. This is useful if a type with an alignment requirement 21c3739801SMiguel Ojeda /// needs to be read from a chunk of memory which provides no alignment 22c3739801SMiguel Ojeda /// guarantees. 23c3739801SMiguel Ojeda /// 24c3739801SMiguel Ojeda /// Since `Unalign` has no alignment requirement, the inner `T` may not be 25c3739801SMiguel Ojeda /// properly aligned in memory. There are five ways to access the inner `T`: 26c3739801SMiguel Ojeda /// - by value, using [`get`] or [`into_inner`] 27c3739801SMiguel Ojeda /// - by reference inside of a callback, using [`update`] 28c3739801SMiguel Ojeda /// - fallibly by reference, using [`try_deref`] or [`try_deref_mut`]; these can 29c3739801SMiguel Ojeda /// fail if the `Unalign` does not satisfy `T`'s alignment requirement at 30c3739801SMiguel Ojeda /// runtime 31c3739801SMiguel Ojeda /// - unsafely by reference, using [`deref_unchecked`] or 32c3739801SMiguel Ojeda /// [`deref_mut_unchecked`]; it is the caller's responsibility to ensure that 33c3739801SMiguel Ojeda /// the `Unalign` satisfies `T`'s alignment requirement 34c3739801SMiguel Ojeda /// - (where `T: Unaligned`) infallibly by reference, using [`Deref::deref`] or 35c3739801SMiguel Ojeda /// [`DerefMut::deref_mut`] 36c3739801SMiguel Ojeda /// 37c3739801SMiguel Ojeda /// [or ABI]: https://github.com/google/zerocopy/issues/164 38c3739801SMiguel Ojeda /// [`get`]: Unalign::get 39c3739801SMiguel Ojeda /// [`into_inner`]: Unalign::into_inner 40c3739801SMiguel Ojeda /// [`update`]: Unalign::update 41c3739801SMiguel Ojeda /// [`try_deref`]: Unalign::try_deref 42c3739801SMiguel Ojeda /// [`try_deref_mut`]: Unalign::try_deref_mut 43c3739801SMiguel Ojeda /// [`deref_unchecked`]: Unalign::deref_unchecked 44c3739801SMiguel Ojeda /// [`deref_mut_unchecked`]: Unalign::deref_mut_unchecked 45c3739801SMiguel Ojeda /// 46c3739801SMiguel Ojeda /// # Example 47c3739801SMiguel Ojeda /// 48c3739801SMiguel Ojeda /// In this example, we need `EthernetFrame` to have no alignment requirement - 49c3739801SMiguel Ojeda /// and thus implement [`Unaligned`]. `EtherType` is `#[repr(u16)]` and so 50c3739801SMiguel Ojeda /// cannot implement `Unaligned`. We use `Unalign` to relax `EtherType`'s 51c3739801SMiguel Ojeda /// alignment requirement so that `EthernetFrame` has no alignment requirement 52c3739801SMiguel Ojeda /// and can implement `Unaligned`. 53c3739801SMiguel Ojeda /// 54c3739801SMiguel Ojeda /// ```rust 55c3739801SMiguel Ojeda /// use zerocopy::*; 56c3739801SMiguel Ojeda /// # use zerocopy_derive::*; 57c3739801SMiguel Ojeda /// # #[derive(FromBytes, KnownLayout, Immutable, Unaligned)] #[repr(C)] struct Mac([u8; 6]); 58c3739801SMiguel Ojeda /// 59c3739801SMiguel Ojeda /// # #[derive(PartialEq, Copy, Clone, Debug)] 60c3739801SMiguel Ojeda /// #[derive(TryFromBytes, KnownLayout, Immutable)] 61c3739801SMiguel Ojeda /// #[repr(u16)] 62c3739801SMiguel Ojeda /// enum EtherType { 63c3739801SMiguel Ojeda /// Ipv4 = 0x0800u16.to_be(), 64c3739801SMiguel Ojeda /// Arp = 0x0806u16.to_be(), 65c3739801SMiguel Ojeda /// Ipv6 = 0x86DDu16.to_be(), 66c3739801SMiguel Ojeda /// # /* 67c3739801SMiguel Ojeda /// ... 68c3739801SMiguel Ojeda /// # */ 69c3739801SMiguel Ojeda /// } 70c3739801SMiguel Ojeda /// 71c3739801SMiguel Ojeda /// #[derive(TryFromBytes, KnownLayout, Immutable, Unaligned)] 72c3739801SMiguel Ojeda /// #[repr(C)] 73c3739801SMiguel Ojeda /// struct EthernetFrame { 74c3739801SMiguel Ojeda /// src: Mac, 75c3739801SMiguel Ojeda /// dst: Mac, 76c3739801SMiguel Ojeda /// ethertype: Unalign<EtherType>, 77c3739801SMiguel Ojeda /// payload: [u8], 78c3739801SMiguel Ojeda /// } 79c3739801SMiguel Ojeda /// 80c3739801SMiguel Ojeda /// let bytes = &[ 81c3739801SMiguel Ojeda /// # 0, 1, 2, 3, 4, 5, 82c3739801SMiguel Ojeda /// # 6, 7, 8, 9, 10, 11, 83c3739801SMiguel Ojeda /// # /* 84c3739801SMiguel Ojeda /// ... 85c3739801SMiguel Ojeda /// # */ 86c3739801SMiguel Ojeda /// 0x86, 0xDD, // EtherType 87c3739801SMiguel Ojeda /// 0xDE, 0xAD, 0xBE, 0xEF // Payload 88c3739801SMiguel Ojeda /// ][..]; 89c3739801SMiguel Ojeda /// 90c3739801SMiguel Ojeda /// // PANICS: Guaranteed not to panic because `bytes` is of the right 91c3739801SMiguel Ojeda /// // length, has the right contents, and `EthernetFrame` has no 92c3739801SMiguel Ojeda /// // alignment requirement. 93c3739801SMiguel Ojeda /// let packet = EthernetFrame::try_ref_from_bytes(&bytes).unwrap(); 94c3739801SMiguel Ojeda /// 95c3739801SMiguel Ojeda /// assert_eq!(packet.ethertype.get(), EtherType::Ipv6); 96c3739801SMiguel Ojeda /// assert_eq!(packet.payload, [0xDE, 0xAD, 0xBE, 0xEF]); 97c3739801SMiguel Ojeda /// ``` 98c3739801SMiguel Ojeda /// 99c3739801SMiguel Ojeda /// # Safety 100c3739801SMiguel Ojeda /// 101c3739801SMiguel Ojeda /// `Unalign<T>` is guaranteed to have the same size and bit validity as `T`, 102c3739801SMiguel Ojeda /// and to have [`UnsafeCell`]s covering the same byte ranges as `T`. 103c3739801SMiguel Ojeda /// `Unalign<T>` is guaranteed to have alignment 1. 104c3739801SMiguel Ojeda // NOTE: This type is sound to use with types that need to be dropped. The 105c3739801SMiguel Ojeda // reason is that the compiler-generated drop code automatically moves all 106c3739801SMiguel Ojeda // values to aligned memory slots before dropping them in-place. This is not 107c3739801SMiguel Ojeda // well-documented, but it's hinted at in places like [1] and [2]. However, this 108c3739801SMiguel Ojeda // also means that `T` must be `Sized`; unless something changes, we can never 109c3739801SMiguel Ojeda // support unsized `T`. [3] 110c3739801SMiguel Ojeda // 111c3739801SMiguel Ojeda // [1] https://github.com/rust-lang/rust/issues/54148#issuecomment-420529646 112c3739801SMiguel Ojeda // [2] https://github.com/google/zerocopy/pull/126#discussion_r1018512323 113c3739801SMiguel Ojeda // [3] https://github.com/google/zerocopy/issues/209 114c3739801SMiguel Ojeda #[allow(missing_debug_implementations)] 115c3739801SMiguel Ojeda #[derive(Default, Copy)] 116c3739801SMiguel Ojeda #[cfg_attr(any(feature = "derive", test), derive(Immutable, FromBytes, IntoBytes, Unaligned))] 117c3739801SMiguel Ojeda #[repr(C, packed)] 118c3739801SMiguel Ojeda pub struct Unalign<T>(T); 119c3739801SMiguel Ojeda 120c3739801SMiguel Ojeda // We do not use `derive(KnownLayout)` on `Unalign`, because the derive is not 121c3739801SMiguel Ojeda // smart enough to realize that `Unalign<T>` is always sized and thus emits a 122c3739801SMiguel Ojeda // `KnownLayout` impl bounded on `T: KnownLayout.` This is overly restrictive. 123c3739801SMiguel Ojeda impl_known_layout!(T => Unalign<T>); 124c3739801SMiguel Ojeda 125c3739801SMiguel Ojeda // FIXME(https://github.com/rust-lang/rust-clippy/issues/16087): Move these 126c3739801SMiguel Ojeda // attributes below the comment once this Clippy bug is fixed. 127c3739801SMiguel Ojeda #[cfg_attr( 128c3739801SMiguel Ojeda all(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS, any(feature = "derive", test)), 129c3739801SMiguel Ojeda expect(unused_unsafe) 130c3739801SMiguel Ojeda )] 131c3739801SMiguel Ojeda #[cfg_attr( 132c3739801SMiguel Ojeda all( 133c3739801SMiguel Ojeda not(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), 134c3739801SMiguel Ojeda any(feature = "derive", test) 135c3739801SMiguel Ojeda ), 136c3739801SMiguel Ojeda allow(unused_unsafe) 137c3739801SMiguel Ojeda )] 138c3739801SMiguel Ojeda // SAFETY: 139c3739801SMiguel Ojeda // - `Unalign<T>` promises to have alignment 1, and so we don't require that `T: 140c3739801SMiguel Ojeda // Unaligned`. 141c3739801SMiguel Ojeda // - `Unalign<T>` has the same bit validity as `T`, and so it is `FromZeros`, 142c3739801SMiguel Ojeda // `FromBytes`, or `IntoBytes` exactly when `T` is as well. 143c3739801SMiguel Ojeda // - `Immutable`: `Unalign<T>` has the same fields as `T`, so it permits 144c3739801SMiguel Ojeda // interior mutation exactly when `T` does. 145c3739801SMiguel Ojeda // - `TryFromBytes`: `Unalign<T>` has the same the same bit validity as `T`, so 146c3739801SMiguel Ojeda // `T::is_bit_valid` is a sound implementation of `is_bit_valid`. 147c3739801SMiguel Ojeda // 148c3739801SMiguel Ojeda #[allow(clippy::multiple_unsafe_ops_per_block)] 149c3739801SMiguel Ojeda const _: () = unsafe { 150c3739801SMiguel Ojeda impl_or_verify!(T => Unaligned for Unalign<T>); 151c3739801SMiguel Ojeda impl_or_verify!(T: Immutable => Immutable for Unalign<T>); 152c3739801SMiguel Ojeda impl_or_verify!( 153c3739801SMiguel Ojeda T: TryFromBytes => TryFromBytes for Unalign<T>; 154c3739801SMiguel Ojeda |c| T::is_bit_valid(c.transmute::<_, _, BecauseImmutable>()) 155c3739801SMiguel Ojeda ); 156c3739801SMiguel Ojeda impl_or_verify!(T: FromZeros => FromZeros for Unalign<T>); 157c3739801SMiguel Ojeda impl_or_verify!(T: FromBytes => FromBytes for Unalign<T>); 158c3739801SMiguel Ojeda impl_or_verify!(T: IntoBytes => IntoBytes for Unalign<T>); 159c3739801SMiguel Ojeda }; 160c3739801SMiguel Ojeda 161c3739801SMiguel Ojeda // Note that `Unalign: Clone` only if `T: Copy`. Since the inner `T` may not be 162c3739801SMiguel Ojeda // aligned, there's no way to safely call `T::clone`, and so a `T: Clone` bound 163c3739801SMiguel Ojeda // is not sufficient to implement `Clone` for `Unalign`. 164c3739801SMiguel Ojeda impl<T: Copy> Clone for Unalign<T> { 165c3739801SMiguel Ojeda #[inline(always)] 166c3739801SMiguel Ojeda fn clone(&self) -> Unalign<T> { 167c3739801SMiguel Ojeda *self 168c3739801SMiguel Ojeda } 169c3739801SMiguel Ojeda } 170c3739801SMiguel Ojeda 171c3739801SMiguel Ojeda impl<T> Unalign<T> { 172c3739801SMiguel Ojeda /// Constructs a new `Unalign`. 173c3739801SMiguel Ojeda #[inline(always)] 174c3739801SMiguel Ojeda pub const fn new(val: T) -> Unalign<T> { 175c3739801SMiguel Ojeda Unalign(val) 176c3739801SMiguel Ojeda } 177c3739801SMiguel Ojeda 178c3739801SMiguel Ojeda /// Consumes `self`, returning the inner `T`. 179c3739801SMiguel Ojeda #[inline(always)] 180c3739801SMiguel Ojeda pub const fn into_inner(self) -> T { 181c3739801SMiguel Ojeda // SAFETY: Since `Unalign` is `#[repr(C, packed)]`, it has the same size 182c3739801SMiguel Ojeda // and bit validity as `T`. 183c3739801SMiguel Ojeda // 184c3739801SMiguel Ojeda // We do this instead of just destructuring in order to prevent 185c3739801SMiguel Ojeda // `Unalign`'s `Drop::drop` from being run, since dropping is not 186c3739801SMiguel Ojeda // supported in `const fn`s. 187c3739801SMiguel Ojeda // 188c3739801SMiguel Ojeda // FIXME(https://github.com/rust-lang/rust/issues/73255): Destructure 189c3739801SMiguel Ojeda // instead of using unsafe. 190c3739801SMiguel Ojeda unsafe { crate::util::transmute_unchecked(self) } 191c3739801SMiguel Ojeda } 192c3739801SMiguel Ojeda 193c3739801SMiguel Ojeda /// Attempts to return a reference to the wrapped `T`, failing if `self` is 194c3739801SMiguel Ojeda /// not properly aligned. 195c3739801SMiguel Ojeda /// 196c3739801SMiguel Ojeda /// If `self` does not satisfy `align_of::<T>()`, then `try_deref` returns 197c3739801SMiguel Ojeda /// `Err`. 198c3739801SMiguel Ojeda /// 199c3739801SMiguel Ojeda /// If `T: Unaligned`, then `Unalign<T>` implements [`Deref`], and callers 200c3739801SMiguel Ojeda /// may prefer [`Deref::deref`], which is infallible. 201c3739801SMiguel Ojeda #[inline(always)] 202c3739801SMiguel Ojeda pub fn try_deref(&self) -> Result<&T, AlignmentError<&Self, T>> { 203c3739801SMiguel Ojeda let inner = Ptr::from_ref(self).transmute(); 204c3739801SMiguel Ojeda match inner.try_into_aligned() { 205c3739801SMiguel Ojeda Ok(aligned) => Ok(aligned.as_ref()), 206c3739801SMiguel Ojeda Err(err) => Err(err.map_src( 207c3739801SMiguel Ojeda #[inline(always)] 208c3739801SMiguel Ojeda |src| src.into_unalign().as_ref(), 209c3739801SMiguel Ojeda )), 210c3739801SMiguel Ojeda } 211c3739801SMiguel Ojeda } 212c3739801SMiguel Ojeda 213c3739801SMiguel Ojeda /// Attempts to return a mutable reference to the wrapped `T`, failing if 214c3739801SMiguel Ojeda /// `self` is not properly aligned. 215c3739801SMiguel Ojeda /// 216c3739801SMiguel Ojeda /// If `self` does not satisfy `align_of::<T>()`, then `try_deref` returns 217c3739801SMiguel Ojeda /// `Err`. 218c3739801SMiguel Ojeda /// 219c3739801SMiguel Ojeda /// If `T: Unaligned`, then `Unalign<T>` implements [`DerefMut`], and 220c3739801SMiguel Ojeda /// callers may prefer [`DerefMut::deref_mut`], which is infallible. 221c3739801SMiguel Ojeda #[inline(always)] 222c3739801SMiguel Ojeda pub fn try_deref_mut(&mut self) -> Result<&mut T, AlignmentError<&mut Self, T>> { 223c3739801SMiguel Ojeda let inner = Ptr::from_mut(self).transmute::<_, _, (_, (_, _))>(); 224c3739801SMiguel Ojeda match inner.try_into_aligned() { 225c3739801SMiguel Ojeda Ok(aligned) => Ok(aligned.as_mut()), 226c3739801SMiguel Ojeda Err(err) => Err(err.map_src(|src| src.into_unalign().as_mut())), 227c3739801SMiguel Ojeda } 228c3739801SMiguel Ojeda } 229c3739801SMiguel Ojeda 230c3739801SMiguel Ojeda /// Returns a reference to the wrapped `T` without checking alignment. 231c3739801SMiguel Ojeda /// 232c3739801SMiguel Ojeda /// If `T: Unaligned`, then `Unalign<T>` implements[ `Deref`], and callers 233c3739801SMiguel Ojeda /// may prefer [`Deref::deref`], which is safe. 234c3739801SMiguel Ojeda /// 235c3739801SMiguel Ojeda /// # Safety 236c3739801SMiguel Ojeda /// 237c3739801SMiguel Ojeda /// The caller must guarantee that `self` satisfies `align_of::<T>()`. 238c3739801SMiguel Ojeda #[inline(always)] 239c3739801SMiguel Ojeda pub const unsafe fn deref_unchecked(&self) -> &T { 240c3739801SMiguel Ojeda // SAFETY: `Unalign<T>` is `repr(transparent)`, so there is a valid `T` 241c3739801SMiguel Ojeda // at the same memory location as `self`. It has no alignment guarantee, 242c3739801SMiguel Ojeda // but the caller has promised that `self` is properly aligned, so we 243c3739801SMiguel Ojeda // know that it is sound to create a reference to `T` at this memory 244c3739801SMiguel Ojeda // location. 245c3739801SMiguel Ojeda // 246c3739801SMiguel Ojeda // We use `mem::transmute` instead of `&*self.get_ptr()` because 247c3739801SMiguel Ojeda // dereferencing pointers is not stable in `const` on our current MSRV 248c3739801SMiguel Ojeda // (1.56 as of this writing). 249c3739801SMiguel Ojeda unsafe { mem::transmute(self) } 250c3739801SMiguel Ojeda } 251c3739801SMiguel Ojeda 252c3739801SMiguel Ojeda /// Returns a mutable reference to the wrapped `T` without checking 253c3739801SMiguel Ojeda /// alignment. 254c3739801SMiguel Ojeda /// 255c3739801SMiguel Ojeda /// If `T: Unaligned`, then `Unalign<T>` implements[ `DerefMut`], and 256c3739801SMiguel Ojeda /// callers may prefer [`DerefMut::deref_mut`], which is safe. 257c3739801SMiguel Ojeda /// 258c3739801SMiguel Ojeda /// # Safety 259c3739801SMiguel Ojeda /// 260c3739801SMiguel Ojeda /// The caller must guarantee that `self` satisfies `align_of::<T>()`. 261c3739801SMiguel Ojeda #[inline(always)] 262c3739801SMiguel Ojeda pub unsafe fn deref_mut_unchecked(&mut self) -> &mut T { 263c3739801SMiguel Ojeda // SAFETY: `self.get_mut_ptr()` returns a raw pointer to a valid `T` at 264c3739801SMiguel Ojeda // the same memory location as `self`. It has no alignment guarantee, 265c3739801SMiguel Ojeda // but the caller has promised that `self` is properly aligned, so we 266c3739801SMiguel Ojeda // know that the pointer itself is aligned, and thus that it is sound to 267c3739801SMiguel Ojeda // create a reference to a `T` at this memory location. 268c3739801SMiguel Ojeda unsafe { &mut *self.get_mut_ptr() } 269c3739801SMiguel Ojeda } 270c3739801SMiguel Ojeda 271c3739801SMiguel Ojeda /// Gets an unaligned raw pointer to the inner `T`. 272c3739801SMiguel Ojeda /// 273c3739801SMiguel Ojeda /// # Safety 274c3739801SMiguel Ojeda /// 275c3739801SMiguel Ojeda /// The returned raw pointer is not necessarily aligned to 276c3739801SMiguel Ojeda /// `align_of::<T>()`. Most functions which operate on raw pointers require 277c3739801SMiguel Ojeda /// those pointers to be aligned, so calling those functions with the result 278c3739801SMiguel Ojeda /// of `get_ptr` will result in undefined behavior if alignment is not 279c3739801SMiguel Ojeda /// guaranteed using some out-of-band mechanism. In general, the only 280c3739801SMiguel Ojeda /// functions which are safe to call with this pointer are those which are 281c3739801SMiguel Ojeda /// explicitly documented as being sound to use with an unaligned pointer, 282c3739801SMiguel Ojeda /// such as [`read_unaligned`]. 283c3739801SMiguel Ojeda /// 284c3739801SMiguel Ojeda /// Even if the caller is permitted to mutate `self` (e.g. they have 285c3739801SMiguel Ojeda /// ownership or a mutable borrow), it is not guaranteed to be sound to 286c3739801SMiguel Ojeda /// write through the returned pointer. If writing is required, prefer 287c3739801SMiguel Ojeda /// [`get_mut_ptr`] instead. 288c3739801SMiguel Ojeda /// 289c3739801SMiguel Ojeda /// [`read_unaligned`]: core::ptr::read_unaligned 290c3739801SMiguel Ojeda /// [`get_mut_ptr`]: Unalign::get_mut_ptr 291c3739801SMiguel Ojeda #[inline(always)] 292c3739801SMiguel Ojeda pub const fn get_ptr(&self) -> *const T { 293c3739801SMiguel Ojeda ptr::addr_of!(self.0) 294c3739801SMiguel Ojeda } 295c3739801SMiguel Ojeda 296c3739801SMiguel Ojeda /// Gets an unaligned mutable raw pointer to the inner `T`. 297c3739801SMiguel Ojeda /// 298c3739801SMiguel Ojeda /// # Safety 299c3739801SMiguel Ojeda /// 300c3739801SMiguel Ojeda /// The returned raw pointer is not necessarily aligned to 301c3739801SMiguel Ojeda /// `align_of::<T>()`. Most functions which operate on raw pointers require 302c3739801SMiguel Ojeda /// those pointers to be aligned, so calling those functions with the result 303c3739801SMiguel Ojeda /// of `get_ptr` will result in undefined behavior if alignment is not 304c3739801SMiguel Ojeda /// guaranteed using some out-of-band mechanism. In general, the only 305c3739801SMiguel Ojeda /// functions which are safe to call with this pointer are those which are 306c3739801SMiguel Ojeda /// explicitly documented as being sound to use with an unaligned pointer, 307c3739801SMiguel Ojeda /// such as [`read_unaligned`]. 308c3739801SMiguel Ojeda /// 309c3739801SMiguel Ojeda /// [`read_unaligned`]: core::ptr::read_unaligned 310c3739801SMiguel Ojeda // FIXME(https://github.com/rust-lang/rust/issues/57349): Make this `const`. 311c3739801SMiguel Ojeda #[inline(always)] 312c3739801SMiguel Ojeda pub fn get_mut_ptr(&mut self) -> *mut T { 313c3739801SMiguel Ojeda ptr::addr_of_mut!(self.0) 314c3739801SMiguel Ojeda } 315c3739801SMiguel Ojeda 316c3739801SMiguel Ojeda /// Sets the inner `T`, dropping the previous value. 317c3739801SMiguel Ojeda // FIXME(https://github.com/rust-lang/rust/issues/57349): Make this `const`. 318c3739801SMiguel Ojeda #[inline(always)] 319c3739801SMiguel Ojeda pub fn set(&mut self, t: T) { 320c3739801SMiguel Ojeda *self = Unalign::new(t); 321c3739801SMiguel Ojeda } 322c3739801SMiguel Ojeda 323c3739801SMiguel Ojeda /// Updates the inner `T` by calling a function on it. 324c3739801SMiguel Ojeda /// 325c3739801SMiguel Ojeda /// If [`T: Unaligned`], then `Unalign<T>` implements [`DerefMut`], and that 326c3739801SMiguel Ojeda /// impl should be preferred over this method when performing updates, as it 327c3739801SMiguel Ojeda /// will usually be faster and more ergonomic. 328c3739801SMiguel Ojeda /// 329c3739801SMiguel Ojeda /// For large types, this method may be expensive, as it requires copying 330c3739801SMiguel Ojeda /// `2 * size_of::<T>()` bytes. \[1\] 331c3739801SMiguel Ojeda /// 332c3739801SMiguel Ojeda /// \[1\] Since the inner `T` may not be aligned, it would not be sound to 333c3739801SMiguel Ojeda /// invoke `f` on it directly. Instead, `update` moves it into a 334c3739801SMiguel Ojeda /// properly-aligned location in the local stack frame, calls `f` on it, and 335c3739801SMiguel Ojeda /// then moves it back to its original location in `self`. 336c3739801SMiguel Ojeda /// 337c3739801SMiguel Ojeda /// [`T: Unaligned`]: Unaligned 338c3739801SMiguel Ojeda #[inline] 339c3739801SMiguel Ojeda pub fn update<O, F: FnOnce(&mut T) -> O>(&mut self, f: F) -> O { 340c3739801SMiguel Ojeda if mem::align_of::<T>() == 1 { 341c3739801SMiguel Ojeda // While we advise callers to use `DerefMut` when `T: Unaligned`, 342c3739801SMiguel Ojeda // not all callers will be able to guarantee `T: Unaligned` in all 343c3739801SMiguel Ojeda // cases. In particular, callers who are themselves providing an API 344c3739801SMiguel Ojeda // which is generic over `T` may sometimes be called by *their* 345c3739801SMiguel Ojeda // callers with `T` such that `align_of::<T>() == 1`, but cannot 346c3739801SMiguel Ojeda // guarantee this in the general case. Thus, this optimization may 347c3739801SMiguel Ojeda // sometimes be helpful. 348c3739801SMiguel Ojeda 349c3739801SMiguel Ojeda // SAFETY: Since `T`'s alignment is 1, `self` satisfies its 350c3739801SMiguel Ojeda // alignment by definition. 351c3739801SMiguel Ojeda let t = unsafe { self.deref_mut_unchecked() }; 352c3739801SMiguel Ojeda return f(t); 353c3739801SMiguel Ojeda } 354c3739801SMiguel Ojeda 355c3739801SMiguel Ojeda // On drop, this moves `copy` out of itself and uses `ptr::write` to 356c3739801SMiguel Ojeda // overwrite `slf`. 357c3739801SMiguel Ojeda struct WriteBackOnDrop<T> { 358c3739801SMiguel Ojeda copy: ManuallyDrop<T>, 359c3739801SMiguel Ojeda slf: *mut Unalign<T>, 360c3739801SMiguel Ojeda } 361c3739801SMiguel Ojeda 362c3739801SMiguel Ojeda impl<T> Drop for WriteBackOnDrop<T> { 363c3739801SMiguel Ojeda fn drop(&mut self) { 364c3739801SMiguel Ojeda // SAFETY: We never use `copy` again as required by 365c3739801SMiguel Ojeda // `ManuallyDrop::take`. 366c3739801SMiguel Ojeda let copy = unsafe { ManuallyDrop::take(&mut self.copy) }; 367c3739801SMiguel Ojeda // SAFETY: `slf` is the raw pointer value of `self`. We know it 368c3739801SMiguel Ojeda // is valid for writes and properly aligned because `self` is a 369c3739801SMiguel Ojeda // mutable reference, which guarantees both of these properties. 370c3739801SMiguel Ojeda unsafe { ptr::write(self.slf, Unalign::new(copy)) }; 371c3739801SMiguel Ojeda } 372c3739801SMiguel Ojeda } 373c3739801SMiguel Ojeda 374c3739801SMiguel Ojeda // SAFETY: We know that `self` is valid for reads, properly aligned, and 375c3739801SMiguel Ojeda // points to an initialized `Unalign<T>` because it is a mutable 376c3739801SMiguel Ojeda // reference, which guarantees all of these properties. 377c3739801SMiguel Ojeda // 378c3739801SMiguel Ojeda // Since `T: !Copy`, it would be unsound in the general case to allow 379c3739801SMiguel Ojeda // both the original `Unalign<T>` and the copy to be used by safe code. 380c3739801SMiguel Ojeda // We guarantee that the copy is used to overwrite the original in the 381c3739801SMiguel Ojeda // `Drop::drop` impl of `WriteBackOnDrop`. So long as this `drop` is 382c3739801SMiguel Ojeda // called before any other safe code executes, soundness is upheld. 383c3739801SMiguel Ojeda // While this method can terminate in two ways (by returning normally or 384c3739801SMiguel Ojeda // by unwinding due to a panic in `f`), in both cases, `write_back` is 385c3739801SMiguel Ojeda // dropped - and its `drop` called - before any other safe code can 386c3739801SMiguel Ojeda // execute. 387c3739801SMiguel Ojeda let copy = unsafe { ptr::read(self) }.into_inner(); 388c3739801SMiguel Ojeda let mut write_back = WriteBackOnDrop { copy: ManuallyDrop::new(copy), slf: self }; 389c3739801SMiguel Ojeda 390c3739801SMiguel Ojeda let ret = f(&mut write_back.copy); 391c3739801SMiguel Ojeda 392c3739801SMiguel Ojeda drop(write_back); 393c3739801SMiguel Ojeda ret 394c3739801SMiguel Ojeda } 395c3739801SMiguel Ojeda } 396c3739801SMiguel Ojeda 397c3739801SMiguel Ojeda impl<T: Copy> Unalign<T> { 398c3739801SMiguel Ojeda /// Gets a copy of the inner `T`. 399c3739801SMiguel Ojeda // FIXME(https://github.com/rust-lang/rust/issues/57349): Make this `const`. 400c3739801SMiguel Ojeda #[inline(always)] 401c3739801SMiguel Ojeda pub fn get(&self) -> T { 402c3739801SMiguel Ojeda let Unalign(val) = *self; 403c3739801SMiguel Ojeda val 404c3739801SMiguel Ojeda } 405c3739801SMiguel Ojeda } 406c3739801SMiguel Ojeda 407c3739801SMiguel Ojeda impl<T: Unaligned> Deref for Unalign<T> { 408c3739801SMiguel Ojeda type Target = T; 409c3739801SMiguel Ojeda 410c3739801SMiguel Ojeda #[inline(always)] 411c3739801SMiguel Ojeda fn deref(&self) -> &T { 412c3739801SMiguel Ojeda Ptr::from_ref(self).transmute().bikeshed_recall_aligned().as_ref() 413c3739801SMiguel Ojeda } 414c3739801SMiguel Ojeda } 415c3739801SMiguel Ojeda 416c3739801SMiguel Ojeda impl<T: Unaligned> DerefMut for Unalign<T> { 417c3739801SMiguel Ojeda #[inline(always)] 418c3739801SMiguel Ojeda fn deref_mut(&mut self) -> &mut T { 419c3739801SMiguel Ojeda Ptr::from_mut(self).transmute::<_, _, (_, (_, _))>().bikeshed_recall_aligned().as_mut() 420c3739801SMiguel Ojeda } 421c3739801SMiguel Ojeda } 422c3739801SMiguel Ojeda 423c3739801SMiguel Ojeda impl<T: Unaligned + PartialOrd> PartialOrd<Unalign<T>> for Unalign<T> { 424c3739801SMiguel Ojeda #[inline(always)] 425c3739801SMiguel Ojeda fn partial_cmp(&self, other: &Unalign<T>) -> Option<Ordering> { 426c3739801SMiguel Ojeda PartialOrd::partial_cmp(self.deref(), other.deref()) 427c3739801SMiguel Ojeda } 428c3739801SMiguel Ojeda } 429c3739801SMiguel Ojeda 430c3739801SMiguel Ojeda impl<T: Unaligned + Ord> Ord for Unalign<T> { 431c3739801SMiguel Ojeda #[inline(always)] 432c3739801SMiguel Ojeda fn cmp(&self, other: &Unalign<T>) -> Ordering { 433c3739801SMiguel Ojeda Ord::cmp(self.deref(), other.deref()) 434c3739801SMiguel Ojeda } 435c3739801SMiguel Ojeda } 436c3739801SMiguel Ojeda 437c3739801SMiguel Ojeda impl<T: Unaligned + PartialEq> PartialEq<Unalign<T>> for Unalign<T> { 438c3739801SMiguel Ojeda #[inline(always)] 439c3739801SMiguel Ojeda fn eq(&self, other: &Unalign<T>) -> bool { 440c3739801SMiguel Ojeda PartialEq::eq(self.deref(), other.deref()) 441c3739801SMiguel Ojeda } 442c3739801SMiguel Ojeda } 443c3739801SMiguel Ojeda 444c3739801SMiguel Ojeda impl<T: Unaligned + Eq> Eq for Unalign<T> {} 445c3739801SMiguel Ojeda 446c3739801SMiguel Ojeda impl<T: Unaligned + Hash> Hash for Unalign<T> { 447c3739801SMiguel Ojeda #[inline(always)] 448c3739801SMiguel Ojeda fn hash<H>(&self, state: &mut H) 449c3739801SMiguel Ojeda where 450c3739801SMiguel Ojeda H: Hasher, 451c3739801SMiguel Ojeda { 452c3739801SMiguel Ojeda self.deref().hash(state); 453c3739801SMiguel Ojeda } 454c3739801SMiguel Ojeda } 455c3739801SMiguel Ojeda 456c3739801SMiguel Ojeda impl<T: Unaligned + Debug> Debug for Unalign<T> { 457c3739801SMiguel Ojeda #[inline(always)] 458c3739801SMiguel Ojeda fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 459c3739801SMiguel Ojeda Debug::fmt(self.deref(), f) 460c3739801SMiguel Ojeda } 461c3739801SMiguel Ojeda } 462c3739801SMiguel Ojeda 463c3739801SMiguel Ojeda impl<T: Unaligned + Display> Display for Unalign<T> { 464c3739801SMiguel Ojeda #[inline(always)] 465c3739801SMiguel Ojeda fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 466c3739801SMiguel Ojeda Display::fmt(self.deref(), f) 467c3739801SMiguel Ojeda } 468c3739801SMiguel Ojeda } 469c3739801SMiguel Ojeda 470c3739801SMiguel Ojeda /// A wrapper type to construct uninitialized instances of `T`. 471c3739801SMiguel Ojeda /// 472c3739801SMiguel Ojeda /// `MaybeUninit` is identical to the [standard library 473c3739801SMiguel Ojeda /// `MaybeUninit`][core-maybe-uninit] type except that it supports unsized 474c3739801SMiguel Ojeda /// types. 475c3739801SMiguel Ojeda /// 476c3739801SMiguel Ojeda /// # Layout 477c3739801SMiguel Ojeda /// 478c3739801SMiguel Ojeda /// The same layout guarantees and caveats apply to `MaybeUninit<T>` as apply to 479c3739801SMiguel Ojeda /// the [standard library `MaybeUninit`][core-maybe-uninit] with one exception: 480c3739801SMiguel Ojeda /// for `T: !Sized`, there is no single value for `T`'s size. Instead, for such 481c3739801SMiguel Ojeda /// types, the following are guaranteed: 482c3739801SMiguel Ojeda /// - Every [valid size][valid-size] for `T` is a valid size for 483c3739801SMiguel Ojeda /// `MaybeUninit<T>` and vice versa 484c3739801SMiguel Ojeda /// - Given `t: *const T` and `m: *const MaybeUninit<T>` with identical fat 485c3739801SMiguel Ojeda /// pointer metadata, `t` and `m` address the same number of bytes (and 486c3739801SMiguel Ojeda /// likewise for `*mut`) 487c3739801SMiguel Ojeda /// 488c3739801SMiguel Ojeda /// [core-maybe-uninit]: core::mem::MaybeUninit 489c3739801SMiguel Ojeda /// [valid-size]: crate::KnownLayout#what-is-a-valid-size 490c3739801SMiguel Ojeda #[repr(transparent)] 491c3739801SMiguel Ojeda #[doc(hidden)] 492c3739801SMiguel Ojeda pub struct MaybeUninit<T: ?Sized + KnownLayout>( 493c3739801SMiguel Ojeda // SAFETY: `MaybeUninit<T>` has the same size as `T`, because (by invariant 494c3739801SMiguel Ojeda // on `T::MaybeUninit`) `T::MaybeUninit` has `T::LAYOUT` identical to `T`, 495c3739801SMiguel Ojeda // and because (invariant on `T::LAYOUT`) we can trust that `LAYOUT` 496c3739801SMiguel Ojeda // accurately reflects the layout of `T`. By invariant on `T::MaybeUninit`, 497c3739801SMiguel Ojeda // it admits uninitialized bytes in all positions. Because `MaybeUninit` is 498c3739801SMiguel Ojeda // marked `repr(transparent)`, these properties additionally hold true for 499c3739801SMiguel Ojeda // `Self`. 500c3739801SMiguel Ojeda T::MaybeUninit, 501c3739801SMiguel Ojeda ); 502c3739801SMiguel Ojeda 503c3739801SMiguel Ojeda #[doc(hidden)] 504c3739801SMiguel Ojeda impl<T: ?Sized + KnownLayout> MaybeUninit<T> { 505c3739801SMiguel Ojeda /// Constructs a `MaybeUninit<T>` initialized with the given value. 506c3739801SMiguel Ojeda #[inline(always)] 507c3739801SMiguel Ojeda pub fn new(val: T) -> Self 508c3739801SMiguel Ojeda where 509c3739801SMiguel Ojeda T: Sized, 510c3739801SMiguel Ojeda Self: Sized, 511c3739801SMiguel Ojeda { 512c3739801SMiguel Ojeda // SAFETY: It is valid to transmute `val` to `MaybeUninit<T>` because it 513c3739801SMiguel Ojeda // is both valid to transmute `val` to `T::MaybeUninit`, and it is valid 514c3739801SMiguel Ojeda // to transmute from `T::MaybeUninit` to `MaybeUninit<T>`. 515c3739801SMiguel Ojeda // 516c3739801SMiguel Ojeda // First, it is valid to transmute `val` to `T::MaybeUninit` because, by 517c3739801SMiguel Ojeda // invariant on `T::MaybeUninit`: 518c3739801SMiguel Ojeda // - For `T: Sized`, `T` and `T::MaybeUninit` have the same size. 519c3739801SMiguel Ojeda // - All byte sequences of the correct size are valid values of 520c3739801SMiguel Ojeda // `T::MaybeUninit`. 521c3739801SMiguel Ojeda // 522c3739801SMiguel Ojeda // Second, it is additionally valid to transmute from `T::MaybeUninit` 523c3739801SMiguel Ojeda // to `MaybeUninit<T>`, because `MaybeUninit<T>` is a 524c3739801SMiguel Ojeda // `repr(transparent)` wrapper around `T::MaybeUninit`. 525c3739801SMiguel Ojeda // 526c3739801SMiguel Ojeda // These two transmutes are collapsed into one so we don't need to add a 527c3739801SMiguel Ojeda // `T::MaybeUninit: Sized` bound to this function's `where` clause. 528c3739801SMiguel Ojeda unsafe { crate::util::transmute_unchecked(val) } 529c3739801SMiguel Ojeda } 530c3739801SMiguel Ojeda 531c3739801SMiguel Ojeda /// Constructs an uninitialized `MaybeUninit<T>`. 532c3739801SMiguel Ojeda #[must_use] 533c3739801SMiguel Ojeda #[inline(always)] 534c3739801SMiguel Ojeda pub fn uninit() -> Self 535c3739801SMiguel Ojeda where 536c3739801SMiguel Ojeda T: Sized, 537c3739801SMiguel Ojeda Self: Sized, 538c3739801SMiguel Ojeda { 539c3739801SMiguel Ojeda let uninit = CoreMaybeUninit::<T>::uninit(); 540c3739801SMiguel Ojeda // SAFETY: It is valid to transmute from `CoreMaybeUninit<T>` to 541c3739801SMiguel Ojeda // `MaybeUninit<T>` since they both admit uninitialized bytes in all 542c3739801SMiguel Ojeda // positions, and they have the same size (i.e., that of `T`). 543c3739801SMiguel Ojeda // 544c3739801SMiguel Ojeda // `MaybeUninit<T>` has the same size as `T`, because (by invariant on 545c3739801SMiguel Ojeda // `T::MaybeUninit`) `T::MaybeUninit` has `T::LAYOUT` identical to `T`, 546c3739801SMiguel Ojeda // and because (invariant on `T::LAYOUT`) we can trust that `LAYOUT` 547c3739801SMiguel Ojeda // accurately reflects the layout of `T`. 548c3739801SMiguel Ojeda // 549c3739801SMiguel Ojeda // `CoreMaybeUninit<T>` has the same size as `T` [1] and admits 550c3739801SMiguel Ojeda // uninitialized bytes in all positions. 551c3739801SMiguel Ojeda // 552c3739801SMiguel Ojeda // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: 553c3739801SMiguel Ojeda // 554c3739801SMiguel Ojeda // `MaybeUninit<T>` is guaranteed to have the same size, alignment, 555c3739801SMiguel Ojeda // and ABI as `T` 556c3739801SMiguel Ojeda unsafe { crate::util::transmute_unchecked(uninit) } 557c3739801SMiguel Ojeda } 558c3739801SMiguel Ojeda 559c3739801SMiguel Ojeda /// Creates a `Box<MaybeUninit<T>>`. 560c3739801SMiguel Ojeda /// 561c3739801SMiguel Ojeda /// This function is useful for allocating large, uninit values on the heap 562c3739801SMiguel Ojeda /// without ever creating a temporary instance of `Self` on the stack. 563c3739801SMiguel Ojeda /// 564c3739801SMiguel Ojeda /// # Errors 565c3739801SMiguel Ojeda /// 566c3739801SMiguel Ojeda /// Returns an error on allocation failure. Allocation failure is guaranteed 567c3739801SMiguel Ojeda /// never to cause a panic or an abort. 568c3739801SMiguel Ojeda #[cfg(feature = "alloc")] 569c3739801SMiguel Ojeda #[inline] 570c3739801SMiguel Ojeda pub fn new_boxed_uninit(meta: T::PointerMetadata) -> Result<Box<Self>, AllocError> { 571c3739801SMiguel Ojeda // SAFETY: `alloc::alloc::alloc_zeroed` is a valid argument of 572c3739801SMiguel Ojeda // `new_box`. The referent of the pointer returned by `alloc` (and, 573c3739801SMiguel Ojeda // consequently, the `Box` derived from it) is a valid instance of 574c3739801SMiguel Ojeda // `Self`, because `Self` is `MaybeUninit` and thus admits arbitrary 575c3739801SMiguel Ojeda // (un)initialized bytes. 576c3739801SMiguel Ojeda unsafe { crate::util::new_box(meta, alloc::alloc::alloc) } 577c3739801SMiguel Ojeda } 578c3739801SMiguel Ojeda 579c3739801SMiguel Ojeda /// Extracts the value from the `MaybeUninit<T>` container. 580c3739801SMiguel Ojeda /// 581c3739801SMiguel Ojeda /// # Safety 582c3739801SMiguel Ojeda /// 583c3739801SMiguel Ojeda /// The caller must ensure that `self` is in an bit-valid state. Depending 584c3739801SMiguel Ojeda /// on subsequent use, it may also need to be in a library-valid state. 585c3739801SMiguel Ojeda #[inline(always)] 586c3739801SMiguel Ojeda pub unsafe fn assume_init(self) -> T 587c3739801SMiguel Ojeda where 588c3739801SMiguel Ojeda T: Sized, 589c3739801SMiguel Ojeda Self: Sized, 590c3739801SMiguel Ojeda { 591c3739801SMiguel Ojeda // SAFETY: The caller guarantees that `self` is in an bit-valid state. 592c3739801SMiguel Ojeda unsafe { crate::util::transmute_unchecked(self) } 593c3739801SMiguel Ojeda } 594c3739801SMiguel Ojeda } 595c3739801SMiguel Ojeda 596c3739801SMiguel Ojeda impl<T: ?Sized + KnownLayout> fmt::Debug for MaybeUninit<T> { 597c3739801SMiguel Ojeda #[inline] 598c3739801SMiguel Ojeda fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 599c3739801SMiguel Ojeda f.pad(core::any::type_name::<Self>()) 600c3739801SMiguel Ojeda } 601c3739801SMiguel Ojeda } 602c3739801SMiguel Ojeda 603c3739801SMiguel Ojeda #[allow(unreachable_pub)] // False positive on MSRV 604c3739801SMiguel Ojeda #[doc(hidden)] 605c3739801SMiguel Ojeda pub use read_only_def::*; 606c3739801SMiguel Ojeda mod read_only_def { 607c3739801SMiguel Ojeda /// A read-only wrapper. 608c3739801SMiguel Ojeda /// 609c3739801SMiguel Ojeda /// A `ReadOnly<T>` disables any interior mutability in `T`, ensuring that 610c3739801SMiguel Ojeda /// a `&ReadOnly<T>` is genuinely read-only. Thus, `ReadOnly<T>` is 611c3739801SMiguel Ojeda /// [`Immutable`] regardless of whether `T` is. 612c3739801SMiguel Ojeda /// 613c3739801SMiguel Ojeda /// Note that `&mut ReadOnly<T>` still permits mutation – the read-only 614c3739801SMiguel Ojeda /// property only applies to shared references. 615c3739801SMiguel Ojeda /// 616c3739801SMiguel Ojeda /// [`Immutable`]: crate::Immutable 617c3739801SMiguel Ojeda #[repr(transparent)] 618c3739801SMiguel Ojeda pub struct ReadOnly<T: ?Sized> { 619c3739801SMiguel Ojeda // INVARIANT: `inner` is never mutated through a `&ReadOnly<T>` 620c3739801SMiguel Ojeda // reference. 621c3739801SMiguel Ojeda inner: T, 622c3739801SMiguel Ojeda } 623c3739801SMiguel Ojeda 624c3739801SMiguel Ojeda impl<T> ReadOnly<T> { 625c3739801SMiguel Ojeda /// Creates a new `ReadOnly`. 626c3739801SMiguel Ojeda #[must_use] 627c3739801SMiguel Ojeda #[inline(always)] 628c3739801SMiguel Ojeda pub const fn new(t: T) -> ReadOnly<T> { 629c3739801SMiguel Ojeda ReadOnly { inner: t } 630c3739801SMiguel Ojeda } 631c3739801SMiguel Ojeda 632c3739801SMiguel Ojeda /// Returns the inner value. 633c3739801SMiguel Ojeda #[must_use] 634c3739801SMiguel Ojeda #[inline(always)] 635c3739801SMiguel Ojeda pub fn into_inner(r: ReadOnly<T>) -> T { 636c3739801SMiguel Ojeda r.inner 637c3739801SMiguel Ojeda } 638c3739801SMiguel Ojeda } 639c3739801SMiguel Ojeda 640c3739801SMiguel Ojeda impl<T: ?Sized> ReadOnly<T> { 641c3739801SMiguel Ojeda #[inline(always)] 642c3739801SMiguel Ojeda pub(crate) fn as_mut(r: &mut ReadOnly<T>) -> &mut T { 643c3739801SMiguel Ojeda // SAFETY: `r: &mut ReadOnly`, so this doesn't violate the invariant 644c3739801SMiguel Ojeda // that `inner` is never mutated through a `&ReadOnly<T>` reference. 645c3739801SMiguel Ojeda &mut r.inner 646c3739801SMiguel Ojeda } 647c3739801SMiguel Ojeda 648c3739801SMiguel Ojeda /// # Safety 649c3739801SMiguel Ojeda /// 650c3739801SMiguel Ojeda /// The caller promises not to mutate the referent (i.e., via interior 651c3739801SMiguel Ojeda /// mutation). 652c3739801SMiguel Ojeda pub(crate) const unsafe fn as_ref_unchecked(r: &ReadOnly<T>) -> &T { 653c3739801SMiguel Ojeda // SAFETY: The caller promises not to mutate the referent. 654c3739801SMiguel Ojeda &r.inner 655c3739801SMiguel Ojeda } 656c3739801SMiguel Ojeda } 657c3739801SMiguel Ojeda } 658c3739801SMiguel Ojeda 659c3739801SMiguel Ojeda // SAFETY: `ReadOnly<T>` is a `#[repr(transparent)` wrapper around `T`. 660c3739801SMiguel Ojeda const _: () = unsafe { 661c3739801SMiguel Ojeda unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] ReadOnly<T>); 662c3739801SMiguel Ojeda }; 663c3739801SMiguel Ojeda 664c3739801SMiguel Ojeda #[allow(clippy::multiple_unsafe_ops_per_block)] 665c3739801SMiguel Ojeda // SAFETY: 666c3739801SMiguel Ojeda // - `ReadOnly<T>` has the same alignment as `T`, and so it is `Unaligned` 667c3739801SMiguel Ojeda // exactly when `T` is as well. 668c3739801SMiguel Ojeda // - `ReadOnly<T>` has the same bit validity as `T`, and so this `is_bit_valid` 669c3739801SMiguel Ojeda // implementation is correct, and thus the `TryFromBytes` impl is sound. 670c3739801SMiguel Ojeda // - `ReadOnly<T>` has the same bit validity as `T`, and so it is `FromZeros`, 671c3739801SMiguel Ojeda // `FromBytes`, and `IntoBytes` exactly when `T` is as well. 672c3739801SMiguel Ojeda const _: () = unsafe { 673c3739801SMiguel Ojeda unsafe_impl!(T: ?Sized + Unaligned => Unaligned for ReadOnly<T>); 674c3739801SMiguel Ojeda unsafe_impl!( 675c3739801SMiguel Ojeda T: ?Sized + TryFromBytes => TryFromBytes for ReadOnly<T>; 676c3739801SMiguel Ojeda |c| T::is_bit_valid(c.cast::<_, <ReadOnly<T> as SizeEq<ReadOnly<ReadOnly<T>>>>::CastFrom, _>()) 677c3739801SMiguel Ojeda ); 678c3739801SMiguel Ojeda unsafe_impl!(T: ?Sized + FromZeros => FromZeros for ReadOnly<T>); 679c3739801SMiguel Ojeda unsafe_impl!(T: ?Sized + FromBytes => FromBytes for ReadOnly<T>); 680c3739801SMiguel Ojeda unsafe_impl!(T: ?Sized + IntoBytes => IntoBytes for ReadOnly<T>); 681c3739801SMiguel Ojeda }; 682c3739801SMiguel Ojeda 683c3739801SMiguel Ojeda // SAFETY: By invariant, `inner` is never mutated through a `&ReadOnly<T>` 684c3739801SMiguel Ojeda // reference. 685c3739801SMiguel Ojeda const _: () = unsafe { 686c3739801SMiguel Ojeda unsafe_impl!(T: ?Sized => Immutable for ReadOnly<T>); 687c3739801SMiguel Ojeda }; 688c3739801SMiguel Ojeda 689c3739801SMiguel Ojeda const _: () = { 690c3739801SMiguel Ojeda use crate::pointer::cast::CastExact; 691c3739801SMiguel Ojeda 692c3739801SMiguel Ojeda // SAFETY: `ReadOnly<T>` has the same layout as `T`. 693c3739801SMiguel Ojeda define_cast!(unsafe { pub CastFromReadOnly<T: ?Sized> = ReadOnly<T> => T}); 694c3739801SMiguel Ojeda // SAFETY: `ReadOnly<T>` has the same layout as `T`. 695c3739801SMiguel Ojeda unsafe impl<T: ?Sized> CastExact<ReadOnly<T>, T> for CastFromReadOnly {} 696c3739801SMiguel Ojeda // SAFETY: `ReadOnly<T>` has the same layout as `T`. 697c3739801SMiguel Ojeda define_cast!(unsafe { pub CastToReadOnly<T: ?Sized> = T => ReadOnly<T>}); 698c3739801SMiguel Ojeda // SAFETY: `ReadOnly<T>` has the same layout as `T`. 699c3739801SMiguel Ojeda unsafe impl<T: ?Sized> CastExact<T, ReadOnly<T>> for CastToReadOnly {} 700c3739801SMiguel Ojeda 701c3739801SMiguel Ojeda impl<T: ?Sized> SizeEq<ReadOnly<T>> for T { 702c3739801SMiguel Ojeda type CastFrom = CastFromReadOnly; 703c3739801SMiguel Ojeda } 704c3739801SMiguel Ojeda 705c3739801SMiguel Ojeda impl<T: ?Sized> SizeEq<T> for ReadOnly<T> { 706c3739801SMiguel Ojeda type CastFrom = CastToReadOnly; 707c3739801SMiguel Ojeda } 708c3739801SMiguel Ojeda }; 709c3739801SMiguel Ojeda 710c3739801SMiguel Ojeda // SAFETY: `ReadOnly<T>` is a `#[repr(transparent)]` wrapper around `T`, and so 711c3739801SMiguel Ojeda // it has the same bit validity as `T`. 712c3739801SMiguel Ojeda unsafe impl<T: ?Sized> TransmuteFrom<T, Valid, Valid> for ReadOnly<T> {} 713c3739801SMiguel Ojeda 714c3739801SMiguel Ojeda // SAFETY: `ReadOnly<T>` is a `#[repr(transparent)]` wrapper around `T`, and so 715c3739801SMiguel Ojeda // it has the same bit validity as `T`. 716c3739801SMiguel Ojeda unsafe impl<T: ?Sized> TransmuteFrom<ReadOnly<T>, Valid, Valid> for T {} 717c3739801SMiguel Ojeda 718c3739801SMiguel Ojeda impl<'a, T: ?Sized + Immutable> From<&'a T> for &'a ReadOnly<T> { 719c3739801SMiguel Ojeda #[inline(always)] 720c3739801SMiguel Ojeda fn from(t: &'a T) -> &'a ReadOnly<T> { 721c3739801SMiguel Ojeda let ro = Ptr::from_ref(t).transmute::<_, _, (_, _)>(); 722c3739801SMiguel Ojeda // SAFETY: `ReadOnly<T>` has the same alignment as `T`, and 723c3739801SMiguel Ojeda // `Ptr::from_ref` produces an aligned `Ptr`. 724c3739801SMiguel Ojeda let ro = unsafe { ro.assume_alignment() }; 725c3739801SMiguel Ojeda ro.as_ref() 726c3739801SMiguel Ojeda } 727c3739801SMiguel Ojeda } 728c3739801SMiguel Ojeda 729c3739801SMiguel Ojeda impl<T: ?Sized + Immutable> Deref for ReadOnly<T> { 730c3739801SMiguel Ojeda type Target = T; 731c3739801SMiguel Ojeda 732c3739801SMiguel Ojeda #[inline(always)] 733c3739801SMiguel Ojeda fn deref(&self) -> &Self::Target { 734c3739801SMiguel Ojeda // SAFETY: By `T: Immutable`, `&T` doesn't permit interior mutation. 735c3739801SMiguel Ojeda unsafe { ReadOnly::as_ref_unchecked(self) } 736c3739801SMiguel Ojeda } 737c3739801SMiguel Ojeda } 738c3739801SMiguel Ojeda 739c3739801SMiguel Ojeda impl<T: ?Sized + Immutable> DerefMut for ReadOnly<T> { 740c3739801SMiguel Ojeda #[inline(always)] 741c3739801SMiguel Ojeda fn deref_mut(&mut self) -> &mut Self::Target { 742c3739801SMiguel Ojeda ReadOnly::as_mut(self) 743c3739801SMiguel Ojeda } 744c3739801SMiguel Ojeda } 745c3739801SMiguel Ojeda 746c3739801SMiguel Ojeda impl<T: ?Sized + Immutable + Debug> Debug for ReadOnly<T> { 747c3739801SMiguel Ojeda #[inline(always)] 748c3739801SMiguel Ojeda fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 749c3739801SMiguel Ojeda self.deref().fmt(f) 750c3739801SMiguel Ojeda } 751c3739801SMiguel Ojeda } 752c3739801SMiguel Ojeda 753c3739801SMiguel Ojeda // SAFETY: See safety comment on `ProjectToTag`. 754c3739801SMiguel Ojeda unsafe impl<T: HasTag + ?Sized> HasTag for ReadOnly<T> { 755c3739801SMiguel Ojeda #[allow(clippy::missing_inline_in_public_items)] 756c3739801SMiguel Ojeda fn only_derive_is_allowed_to_implement_this_trait() 757c3739801SMiguel Ojeda where 758c3739801SMiguel Ojeda Self: Sized, 759c3739801SMiguel Ojeda { 760c3739801SMiguel Ojeda } 761c3739801SMiguel Ojeda 762c3739801SMiguel Ojeda type Tag = T::Tag; 763c3739801SMiguel Ojeda 764c3739801SMiguel Ojeda // SAFETY: `<T as SizeEq<ReadOnly<T>>>::CastFrom` is a no-op projection that 765c3739801SMiguel Ojeda // produces a pointer with the same referent. By invariant, for any `Ptr<'_, 766c3739801SMiguel Ojeda // T, I>` it is sound to use `T::ProjectToTag` to project to a `Ptr<'_, 767c3739801SMiguel Ojeda // T::Tag, I>`. Since `ReadOnly<T>` has the same layout and validity as `T`, 768c3739801SMiguel Ojeda // the same is true of projecting from a `Ptr<'_, ReadOnly<T>, I>`. 769c3739801SMiguel Ojeda type ProjectToTag = crate::pointer::cast::TransitiveProject< 770c3739801SMiguel Ojeda T, 771c3739801SMiguel Ojeda <T as SizeEq<ReadOnly<T>>>::CastFrom, 772c3739801SMiguel Ojeda T::ProjectToTag, 773c3739801SMiguel Ojeda >; 774c3739801SMiguel Ojeda } 775c3739801SMiguel Ojeda 776c3739801SMiguel Ojeda // SAFETY: `ReadOnly<T>` is a `#[repr(transparent)]` wrapper around `T`, and so 777c3739801SMiguel Ojeda // has the same fields at the same offsets. Thus, it satisfies the safety 778c3739801SMiguel Ojeda // invariants of `HasField<Field, VARIANT_ID, FIELD_ID>` for field `f` exactly 779c3739801SMiguel Ojeda // when `T` does, as guaranteed by the `T: HasField` bound: 780c3739801SMiguel Ojeda // - If `VARIANT_ID` is `STRUCT_VARIANT_ID` or `UNION_VARIANT_ID`, then `T` has 781c3739801SMiguel Ojeda // the layout of a struct or union type. Since `ReadOnly<T>` is a transparent 782c3739801SMiguel Ojeda // wrapper around `T`, it does too. Otherwise, if `VARIANT_ID` is an enum 783c3739801SMiguel Ojeda // variant index, then `T` has the layout of an enum type, and `ReadOnly<T>` 784c3739801SMiguel Ojeda // does too. 785c3739801SMiguel Ojeda // - By `T: HasField<_, _, FIELD_ID>`: 786c3739801SMiguel Ojeda // - `T` has a field `f` with name `n` such that 787c3739801SMiguel Ojeda // `FIELD_ID = zerocopy::ident_id!(n)` or at index `i` such that 788c3739801SMiguel Ojeda // `FIELD_ID = zerocopy::ident_id!(i)`. 789c3739801SMiguel Ojeda // - `Field` has the same visibility as `f`. 790c3739801SMiguel Ojeda // - `T::Type` has the same type as `f`. Thus, `ReadOnly<T::Type>` has the 791c3739801SMiguel Ojeda // same type as `f`, wrapped in `ReadOnly`. 792c3739801SMiguel Ojeda // 793c3739801SMiguel Ojeda // `project` satisfies its post-condition – namely, that the returned pointer 794c3739801SMiguel Ojeda // refers to a non-strict subset of the bytes of `slf`'s referent, and has the 795c3739801SMiguel Ojeda // same provenance as `slf` – because all intermediate operations satisfy those 796c3739801SMiguel Ojeda // same conditions. 797c3739801SMiguel Ojeda unsafe impl<T, Field, const VARIANT_ID: i128, const FIELD_ID: i128> 798c3739801SMiguel Ojeda HasField<Field, VARIANT_ID, FIELD_ID> for ReadOnly<T> 799c3739801SMiguel Ojeda where 800c3739801SMiguel Ojeda T: HasField<Field, VARIANT_ID, FIELD_ID> + ?Sized, 801c3739801SMiguel Ojeda { 802c3739801SMiguel Ojeda #[allow(clippy::missing_inline_in_public_items)] 803c3739801SMiguel Ojeda fn only_derive_is_allowed_to_implement_this_trait() 804c3739801SMiguel Ojeda where 805c3739801SMiguel Ojeda Self: Sized, 806c3739801SMiguel Ojeda { 807c3739801SMiguel Ojeda } 808c3739801SMiguel Ojeda 809c3739801SMiguel Ojeda type Type = ReadOnly<T::Type>; 810c3739801SMiguel Ojeda 811c3739801SMiguel Ojeda #[inline(always)] 812c3739801SMiguel Ojeda fn project(slf: PtrInner<'_, Self>) -> *mut ReadOnly<T::Type> { 813c3739801SMiguel Ojeda slf.project::<_, <T as SizeEq<ReadOnly<T>>>::CastFrom>() 814c3739801SMiguel Ojeda .project::<_, crate::pointer::cast::Projection<Field, VARIANT_ID, FIELD_ID>>() 815c3739801SMiguel Ojeda .project::<_, <ReadOnly<T::Type> as SizeEq<T::Type>>::CastFrom>() 816c3739801SMiguel Ojeda .as_non_null() 817c3739801SMiguel Ojeda .as_ptr() 818c3739801SMiguel Ojeda } 819c3739801SMiguel Ojeda } 820c3739801SMiguel Ojeda 821c3739801SMiguel Ojeda // SAFETY: `ReadOnly<T>` is a `#[repr(transparent)]` wrapper around `T`, and so 822c3739801SMiguel Ojeda // has the same fields at the same offsets. `is_projectable` simply delegates to 823c3739801SMiguel Ojeda // `T::is_projectable`, which is sound because a `Ptr<'_, ReadOnly<T>, I>` will 824c3739801SMiguel Ojeda // be projectable exactly when a `Ptr<'_, T, I>` referent is. 825c3739801SMiguel Ojeda unsafe impl<T, Field, I, const VARIANT_ID: i128, const FIELD_ID: i128> 826c3739801SMiguel Ojeda ProjectField<Field, I, VARIANT_ID, FIELD_ID> for ReadOnly<T> 827c3739801SMiguel Ojeda where 828c3739801SMiguel Ojeda T: ProjectField<Field, I, VARIANT_ID, FIELD_ID> + ?Sized, 829c3739801SMiguel Ojeda I: invariant::Invariants, 830c3739801SMiguel Ojeda { 831c3739801SMiguel Ojeda #[allow(clippy::missing_inline_in_public_items)] 832c3739801SMiguel Ojeda fn only_derive_is_allowed_to_implement_this_trait() 833c3739801SMiguel Ojeda where 834c3739801SMiguel Ojeda Self: Sized, 835c3739801SMiguel Ojeda { 836c3739801SMiguel Ojeda } 837c3739801SMiguel Ojeda 838c3739801SMiguel Ojeda type Invariants = T::Invariants; 839c3739801SMiguel Ojeda 840c3739801SMiguel Ojeda type Error = T::Error; 841c3739801SMiguel Ojeda 842c3739801SMiguel Ojeda #[inline(always)] 843c3739801SMiguel Ojeda fn is_projectable<'a>(ptr: Ptr<'a, Self::Tag, I>) -> Result<(), Self::Error> { 844c3739801SMiguel Ojeda T::is_projectable(ptr) 845c3739801SMiguel Ojeda } 846c3739801SMiguel Ojeda } 847c3739801SMiguel Ojeda 848c3739801SMiguel Ojeda #[cfg(test)] 849c3739801SMiguel Ojeda mod tests { 850c3739801SMiguel Ojeda use core::panic::AssertUnwindSafe; 851c3739801SMiguel Ojeda 852c3739801SMiguel Ojeda use super::*; 853c3739801SMiguel Ojeda use crate::util::testutil::*; 854c3739801SMiguel Ojeda 855c3739801SMiguel Ojeda #[test] 856c3739801SMiguel Ojeda fn test_unalign() { 857c3739801SMiguel Ojeda // Test methods that don't depend on alignment. 858c3739801SMiguel Ojeda let mut u = Unalign::new(AU64(123)); 859c3739801SMiguel Ojeda assert_eq!(u.get(), AU64(123)); 860c3739801SMiguel Ojeda assert_eq!(u.into_inner(), AU64(123)); 861c3739801SMiguel Ojeda assert_eq!(u.get_ptr(), <*const _>::cast::<AU64>(&u)); 862c3739801SMiguel Ojeda assert_eq!(u.get_mut_ptr(), <*mut _>::cast::<AU64>(&mut u)); 863c3739801SMiguel Ojeda u.set(AU64(321)); 864c3739801SMiguel Ojeda assert_eq!(u.get(), AU64(321)); 865c3739801SMiguel Ojeda 866c3739801SMiguel Ojeda // Test methods that depend on alignment (when alignment is satisfied). 867c3739801SMiguel Ojeda let mut u: Align<_, AU64> = Align::new(Unalign::new(AU64(123))); 868c3739801SMiguel Ojeda assert_eq!(u.t.try_deref().unwrap(), &AU64(123)); 869c3739801SMiguel Ojeda assert_eq!(u.t.try_deref_mut().unwrap(), &mut AU64(123)); 870c3739801SMiguel Ojeda // SAFETY: The `Align<_, AU64>` guarantees proper alignment. 871c3739801SMiguel Ojeda assert_eq!(unsafe { u.t.deref_unchecked() }, &AU64(123)); 872c3739801SMiguel Ojeda // SAFETY: The `Align<_, AU64>` guarantees proper alignment. 873c3739801SMiguel Ojeda assert_eq!(unsafe { u.t.deref_mut_unchecked() }, &mut AU64(123)); 874c3739801SMiguel Ojeda *u.t.try_deref_mut().unwrap() = AU64(321); 875c3739801SMiguel Ojeda assert_eq!(u.t.get(), AU64(321)); 876c3739801SMiguel Ojeda 877c3739801SMiguel Ojeda // Test methods that depend on alignment (when alignment is not 878c3739801SMiguel Ojeda // satisfied). 879c3739801SMiguel Ojeda let mut u: ForceUnalign<_, AU64> = ForceUnalign::new(Unalign::new(AU64(123))); 880c3739801SMiguel Ojeda assert!(matches!(u.t.try_deref(), Err(AlignmentError { .. }))); 881c3739801SMiguel Ojeda assert!(matches!(u.t.try_deref_mut(), Err(AlignmentError { .. }))); 882c3739801SMiguel Ojeda 883c3739801SMiguel Ojeda // Test methods that depend on `T: Unaligned`. 884c3739801SMiguel Ojeda let mut u = Unalign::new(123u8); 885c3739801SMiguel Ojeda assert_eq!(u.try_deref(), Ok(&123)); 886c3739801SMiguel Ojeda assert_eq!(u.try_deref_mut(), Ok(&mut 123)); 887c3739801SMiguel Ojeda assert_eq!(u.deref(), &123); 888c3739801SMiguel Ojeda assert_eq!(u.deref_mut(), &mut 123); 889c3739801SMiguel Ojeda *u = 21; 890c3739801SMiguel Ojeda assert_eq!(u.get(), 21); 891c3739801SMiguel Ojeda 892c3739801SMiguel Ojeda // Test that some `Unalign` functions and methods are `const`. 893c3739801SMiguel Ojeda const _UNALIGN: Unalign<u64> = Unalign::new(0); 894c3739801SMiguel Ojeda const _UNALIGN_PTR: *const u64 = _UNALIGN.get_ptr(); 895c3739801SMiguel Ojeda const _U64: u64 = _UNALIGN.into_inner(); 896c3739801SMiguel Ojeda // Make sure all code is considered "used". 897c3739801SMiguel Ojeda // 898c3739801SMiguel Ojeda // FIXME(https://github.com/rust-lang/rust/issues/104084): Remove this 899c3739801SMiguel Ojeda // attribute. 900c3739801SMiguel Ojeda #[allow(dead_code)] 901c3739801SMiguel Ojeda const _: () = { 902c3739801SMiguel Ojeda let x: Align<_, AU64> = Align::new(Unalign::new(AU64(123))); 903c3739801SMiguel Ojeda // Make sure that `deref_unchecked` is `const`. 904c3739801SMiguel Ojeda // 905c3739801SMiguel Ojeda // SAFETY: The `Align<_, AU64>` guarantees proper alignment. 906c3739801SMiguel Ojeda let au64 = unsafe { x.t.deref_unchecked() }; 907c3739801SMiguel Ojeda match au64 { 908c3739801SMiguel Ojeda AU64(123) => {} 909c3739801SMiguel Ojeda _ => const_unreachable!(), 910c3739801SMiguel Ojeda } 911c3739801SMiguel Ojeda }; 912c3739801SMiguel Ojeda } 913c3739801SMiguel Ojeda 914c3739801SMiguel Ojeda #[test] 915c3739801SMiguel Ojeda fn test_unalign_update() { 916c3739801SMiguel Ojeda let mut u = Unalign::new(AU64(123)); 917c3739801SMiguel Ojeda u.update(|a| a.0 += 1); 918c3739801SMiguel Ojeda assert_eq!(u.get(), AU64(124)); 919c3739801SMiguel Ojeda 920c3739801SMiguel Ojeda // Test that, even if the callback panics, the original is still 921c3739801SMiguel Ojeda // correctly overwritten. Use a `Box` so that Miri is more likely to 922c3739801SMiguel Ojeda // catch any unsoundness (which would likely result in two `Box`es for 923c3739801SMiguel Ojeda // the same heap object, which is the sort of thing that Miri would 924c3739801SMiguel Ojeda // probably catch). 925c3739801SMiguel Ojeda let mut u = Unalign::new(Box::new(AU64(123))); 926c3739801SMiguel Ojeda let res = std::panic::catch_unwind(AssertUnwindSafe(|| { 927c3739801SMiguel Ojeda u.update(|a| { 928c3739801SMiguel Ojeda a.0 += 1; 929c3739801SMiguel Ojeda panic!(); 930c3739801SMiguel Ojeda }) 931c3739801SMiguel Ojeda })); 932c3739801SMiguel Ojeda assert!(res.is_err()); 933c3739801SMiguel Ojeda assert_eq!(u.into_inner(), Box::new(AU64(124))); 934c3739801SMiguel Ojeda 935c3739801SMiguel Ojeda // Test the align_of::<T>() == 1 optimization. 936c3739801SMiguel Ojeda let mut u = Unalign::new([0u8, 1]); 937c3739801SMiguel Ojeda u.update(|a| a[0] += 1); 938c3739801SMiguel Ojeda assert_eq!(u.get(), [1u8, 1]); 939c3739801SMiguel Ojeda } 940c3739801SMiguel Ojeda 941c3739801SMiguel Ojeda #[test] 942c3739801SMiguel Ojeda fn test_unalign_copy_clone() { 943c3739801SMiguel Ojeda // Test that `Copy` and `Clone` do not cause soundness issues. This test 944c3739801SMiguel Ojeda // is mainly meant to exercise UB that would be caught by Miri. 945c3739801SMiguel Ojeda 946c3739801SMiguel Ojeda // `u.t` is definitely not validly-aligned for `AU64`'s alignment of 8. 947c3739801SMiguel Ojeda let u = ForceUnalign::<_, AU64>::new(Unalign::new(AU64(123))); 948c3739801SMiguel Ojeda #[allow(clippy::clone_on_copy)] 949c3739801SMiguel Ojeda let v = u.t.clone(); 950c3739801SMiguel Ojeda let w = u.t; 951c3739801SMiguel Ojeda assert_eq!(u.t.get(), v.get()); 952c3739801SMiguel Ojeda assert_eq!(u.t.get(), w.get()); 953c3739801SMiguel Ojeda assert_eq!(v.get(), w.get()); 954c3739801SMiguel Ojeda } 955c3739801SMiguel Ojeda 956c3739801SMiguel Ojeda #[test] 957c3739801SMiguel Ojeda fn test_unalign_trait_impls() { 958c3739801SMiguel Ojeda let zero = Unalign::new(0u8); 959c3739801SMiguel Ojeda let one = Unalign::new(1u8); 960c3739801SMiguel Ojeda 961c3739801SMiguel Ojeda assert!(zero < one); 962c3739801SMiguel Ojeda assert_eq!(PartialOrd::partial_cmp(&zero, &one), Some(Ordering::Less)); 963c3739801SMiguel Ojeda assert_eq!(Ord::cmp(&zero, &one), Ordering::Less); 964c3739801SMiguel Ojeda 965c3739801SMiguel Ojeda assert_ne!(zero, one); 966c3739801SMiguel Ojeda assert_eq!(zero, zero); 967c3739801SMiguel Ojeda assert!(!PartialEq::eq(&zero, &one)); 968c3739801SMiguel Ojeda assert!(PartialEq::eq(&zero, &zero)); 969c3739801SMiguel Ojeda 970c3739801SMiguel Ojeda fn hash<T: Hash>(t: &T) -> u64 { 971c3739801SMiguel Ojeda let mut h = std::collections::hash_map::DefaultHasher::new(); 972c3739801SMiguel Ojeda t.hash(&mut h); 973c3739801SMiguel Ojeda h.finish() 974c3739801SMiguel Ojeda } 975c3739801SMiguel Ojeda 976c3739801SMiguel Ojeda assert_eq!(hash(&zero), hash(&0u8)); 977c3739801SMiguel Ojeda assert_eq!(hash(&one), hash(&1u8)); 978c3739801SMiguel Ojeda 979c3739801SMiguel Ojeda assert_eq!(format!("{:?}", zero), format!("{:?}", 0u8)); 980c3739801SMiguel Ojeda assert_eq!(format!("{:?}", one), format!("{:?}", 1u8)); 981c3739801SMiguel Ojeda assert_eq!(format!("{}", zero), format!("{}", 0u8)); 982c3739801SMiguel Ojeda assert_eq!(format!("{}", one), format!("{}", 1u8)); 983c3739801SMiguel Ojeda } 984c3739801SMiguel Ojeda 985c3739801SMiguel Ojeda #[test] 986c3739801SMiguel Ojeda #[allow(clippy::as_conversions)] 987c3739801SMiguel Ojeda fn test_maybe_uninit() { 988c3739801SMiguel Ojeda // int 989c3739801SMiguel Ojeda { 990c3739801SMiguel Ojeda let input = 42; 991c3739801SMiguel Ojeda let uninit = MaybeUninit::new(input); 992c3739801SMiguel Ojeda // SAFETY: `uninit` is in an initialized state 993c3739801SMiguel Ojeda let output = unsafe { uninit.assume_init() }; 994c3739801SMiguel Ojeda assert_eq!(input, output); 995c3739801SMiguel Ojeda } 996c3739801SMiguel Ojeda 997c3739801SMiguel Ojeda // thin ref 998c3739801SMiguel Ojeda { 999c3739801SMiguel Ojeda let input = 42; 1000c3739801SMiguel Ojeda let uninit = MaybeUninit::new(&input); 1001c3739801SMiguel Ojeda // SAFETY: `uninit` is in an initialized state 1002c3739801SMiguel Ojeda let output = unsafe { uninit.assume_init() }; 1003c3739801SMiguel Ojeda assert_eq!(&input as *const _, output as *const _); 1004c3739801SMiguel Ojeda assert_eq!(input, *output); 1005c3739801SMiguel Ojeda } 1006c3739801SMiguel Ojeda 1007c3739801SMiguel Ojeda // wide ref 1008c3739801SMiguel Ojeda { 1009c3739801SMiguel Ojeda let input = [1, 2, 3, 4]; 1010c3739801SMiguel Ojeda let uninit = MaybeUninit::new(&input[..]); 1011c3739801SMiguel Ojeda // SAFETY: `uninit` is in an initialized state 1012c3739801SMiguel Ojeda let output = unsafe { uninit.assume_init() }; 1013c3739801SMiguel Ojeda assert_eq!(&input[..] as *const _, output as *const _); 1014c3739801SMiguel Ojeda assert_eq!(input, *output); 1015c3739801SMiguel Ojeda } 1016c3739801SMiguel Ojeda } 1017c3739801SMiguel Ojeda #[test] 1018c3739801SMiguel Ojeda fn test_maybe_uninit_uninit() { 1019c3739801SMiguel Ojeda let _uninit = MaybeUninit::<u8>::uninit(); 1020c3739801SMiguel Ojeda // Cannot check value, but can check it compiles and runs 1021c3739801SMiguel Ojeda } 1022c3739801SMiguel Ojeda 1023c3739801SMiguel Ojeda #[test] 1024c3739801SMiguel Ojeda #[cfg(feature = "alloc")] 1025c3739801SMiguel Ojeda fn test_maybe_uninit_new_boxed_uninit() { 1026c3739801SMiguel Ojeda let _boxed = MaybeUninit::<u8>::new_boxed_uninit(()).unwrap(); 1027c3739801SMiguel Ojeda } 1028c3739801SMiguel Ojeda 1029c3739801SMiguel Ojeda #[test] 1030c3739801SMiguel Ojeda fn test_maybe_uninit_debug() { 1031c3739801SMiguel Ojeda let uninit = MaybeUninit::<u8>::uninit(); 1032c3739801SMiguel Ojeda assert!(format!("{:?}", uninit).contains("MaybeUninit")); 1033c3739801SMiguel Ojeda } 1034c3739801SMiguel Ojeda } 1035