1*c3739801SMiguel Ojeda // Copyright 2024 The Fuchsia Authors 2*c3739801SMiguel Ojeda // 3*c3739801SMiguel Ojeda // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 4*c3739801SMiguel Ojeda // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT 5*c3739801SMiguel Ojeda // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. 6*c3739801SMiguel Ojeda // This file may not be copied, modified, or distributed except according to 7*c3739801SMiguel Ojeda // those terms. 8*c3739801SMiguel Ojeda 9*c3739801SMiguel Ojeda use core::{marker::PhantomData, ops::Range, ptr::NonNull}; 10*c3739801SMiguel Ojeda 11*c3739801SMiguel Ojeda pub use _def::PtrInner; 12*c3739801SMiguel Ojeda 13*c3739801SMiguel Ojeda #[allow(unused_imports)] 14*c3739801SMiguel Ojeda use crate::util::polyfills::NumExt as _; 15*c3739801SMiguel Ojeda use crate::{ 16*c3739801SMiguel Ojeda layout::{CastType, MetadataCastError}, 17*c3739801SMiguel Ojeda pointer::cast, 18*c3739801SMiguel Ojeda util::AsAddress, 19*c3739801SMiguel Ojeda AlignmentError, CastError, KnownLayout, MetadataOf, SizeError, SplitAt, 20*c3739801SMiguel Ojeda }; 21*c3739801SMiguel Ojeda 22*c3739801SMiguel Ojeda mod _def { 23*c3739801SMiguel Ojeda use super::*; 24*c3739801SMiguel Ojeda /// The inner pointer stored inside a [`Ptr`][crate::Ptr]. 25*c3739801SMiguel Ojeda /// 26*c3739801SMiguel Ojeda /// `PtrInner<'a, T>` is [covariant] in `'a` and invariant in `T`. 27*c3739801SMiguel Ojeda /// 28*c3739801SMiguel Ojeda /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html 29*c3739801SMiguel Ojeda #[allow(missing_debug_implementations)] 30*c3739801SMiguel Ojeda pub struct PtrInner<'a, T> 31*c3739801SMiguel Ojeda where 32*c3739801SMiguel Ojeda T: ?Sized, 33*c3739801SMiguel Ojeda { 34*c3739801SMiguel Ojeda /// # Invariants 35*c3739801SMiguel Ojeda /// 36*c3739801SMiguel Ojeda /// 0. If `ptr`'s referent is not zero sized, then `ptr` has valid 37*c3739801SMiguel Ojeda /// provenance for its referent, which is entirely contained in some 38*c3739801SMiguel Ojeda /// Rust allocation, `A`. 39*c3739801SMiguel Ojeda /// 1. If `ptr`'s referent is not zero sized, `A` is guaranteed to live 40*c3739801SMiguel Ojeda /// for at least `'a`. 41*c3739801SMiguel Ojeda /// 42*c3739801SMiguel Ojeda /// # Postconditions 43*c3739801SMiguel Ojeda /// 44*c3739801SMiguel Ojeda /// By virtue of these invariants, code may assume the following, which 45*c3739801SMiguel Ojeda /// are logical implications of the invariants: 46*c3739801SMiguel Ojeda /// - `ptr`'s referent is not larger than `isize::MAX` bytes \[1\] 47*c3739801SMiguel Ojeda /// - `ptr`'s referent does not wrap around the address space \[1\] 48*c3739801SMiguel Ojeda /// 49*c3739801SMiguel Ojeda /// \[1\] Per <https://doc.rust-lang.org/1.85.0/std/ptr/index.html#allocated-object>: 50*c3739801SMiguel Ojeda /// 51*c3739801SMiguel Ojeda /// For any allocated object with `base` address, `size`, and a set of 52*c3739801SMiguel Ojeda /// `addresses`, the following are guaranteed: 53*c3739801SMiguel Ojeda /// ... 54*c3739801SMiguel Ojeda /// - `size <= isize::MAX` 55*c3739801SMiguel Ojeda /// 56*c3739801SMiguel Ojeda /// As a consequence of these guarantees, given any address `a` within 57*c3739801SMiguel Ojeda /// the set of addresses of an allocated object: 58*c3739801SMiguel Ojeda /// ... 59*c3739801SMiguel Ojeda /// - It is guaranteed that, given `o = a - base` (i.e., the offset of 60*c3739801SMiguel Ojeda /// `a` within the allocated object), `base + o` will not wrap 61*c3739801SMiguel Ojeda /// around the address space (in other words, will not overflow 62*c3739801SMiguel Ojeda /// `usize`) 63*c3739801SMiguel Ojeda ptr: NonNull<T>, 64*c3739801SMiguel Ojeda // SAFETY: `&'a UnsafeCell<T>` is covariant in `'a` and invariant in `T` 65*c3739801SMiguel Ojeda // [1]. We use this construction rather than the equivalent `&mut T`, 66*c3739801SMiguel Ojeda // because our MSRV of 1.65 prohibits `&mut` types in const contexts. 67*c3739801SMiguel Ojeda // 68*c3739801SMiguel Ojeda // [1] https://doc.rust-lang.org/1.81.0/reference/subtyping.html#variance 69*c3739801SMiguel Ojeda _marker: PhantomData<&'a core::cell::UnsafeCell<T>>, 70*c3739801SMiguel Ojeda } 71*c3739801SMiguel Ojeda 72*c3739801SMiguel Ojeda impl<'a, T: 'a + ?Sized> Copy for PtrInner<'a, T> {} 73*c3739801SMiguel Ojeda impl<'a, T: 'a + ?Sized> Clone for PtrInner<'a, T> { 74*c3739801SMiguel Ojeda #[inline(always)] 75*c3739801SMiguel Ojeda fn clone(&self) -> PtrInner<'a, T> { 76*c3739801SMiguel Ojeda // SAFETY: None of the invariants on `ptr` are affected by having 77*c3739801SMiguel Ojeda // multiple copies of a `PtrInner`. 78*c3739801SMiguel Ojeda *self 79*c3739801SMiguel Ojeda } 80*c3739801SMiguel Ojeda } 81*c3739801SMiguel Ojeda 82*c3739801SMiguel Ojeda impl<'a, T: 'a + ?Sized> PtrInner<'a, T> { 83*c3739801SMiguel Ojeda /// Constructs a `Ptr` from a [`NonNull`]. 84*c3739801SMiguel Ojeda /// 85*c3739801SMiguel Ojeda /// # Safety 86*c3739801SMiguel Ojeda /// 87*c3739801SMiguel Ojeda /// The caller promises that: 88*c3739801SMiguel Ojeda /// 89*c3739801SMiguel Ojeda /// 0. If `ptr`'s referent is not zero sized, then `ptr` has valid 90*c3739801SMiguel Ojeda /// provenance for its referent, which is entirely contained in some 91*c3739801SMiguel Ojeda /// Rust allocation, `A`. 92*c3739801SMiguel Ojeda /// 1. If `ptr`'s referent is not zero sized, `A` is guaranteed to live 93*c3739801SMiguel Ojeda /// for at least `'a`. 94*c3739801SMiguel Ojeda #[inline(always)] 95*c3739801SMiguel Ojeda #[must_use] 96*c3739801SMiguel Ojeda pub const unsafe fn new(ptr: NonNull<T>) -> PtrInner<'a, T> { 97*c3739801SMiguel Ojeda // SAFETY: The caller has promised to satisfy all safety invariants 98*c3739801SMiguel Ojeda // of `PtrInner`. 99*c3739801SMiguel Ojeda Self { ptr, _marker: PhantomData } 100*c3739801SMiguel Ojeda } 101*c3739801SMiguel Ojeda 102*c3739801SMiguel Ojeda /// Converts this `PtrInner<T>` to a [`NonNull<T>`]. 103*c3739801SMiguel Ojeda /// 104*c3739801SMiguel Ojeda /// Note that this method does not consume `self`. The caller should 105*c3739801SMiguel Ojeda /// watch out for `unsafe` code which uses the returned `NonNull` in a 106*c3739801SMiguel Ojeda /// way that violates the safety invariants of `self`. 107*c3739801SMiguel Ojeda #[inline(always)] 108*c3739801SMiguel Ojeda #[must_use] 109*c3739801SMiguel Ojeda pub const fn as_non_null(&self) -> NonNull<T> { 110*c3739801SMiguel Ojeda self.ptr 111*c3739801SMiguel Ojeda } 112*c3739801SMiguel Ojeda 113*c3739801SMiguel Ojeda /// Converts this `PtrInner<T>` to a [`*mut T`]. 114*c3739801SMiguel Ojeda /// 115*c3739801SMiguel Ojeda /// Note that this method does not consume `self`. The caller should 116*c3739801SMiguel Ojeda /// watch out for `unsafe` code which uses the returned `*mut T` in a 117*c3739801SMiguel Ojeda /// way that violates the safety invariants of `self`. 118*c3739801SMiguel Ojeda #[inline(always)] 119*c3739801SMiguel Ojeda #[must_use] 120*c3739801SMiguel Ojeda pub const fn as_ptr(&self) -> *mut T { 121*c3739801SMiguel Ojeda self.ptr.as_ptr() 122*c3739801SMiguel Ojeda } 123*c3739801SMiguel Ojeda } 124*c3739801SMiguel Ojeda } 125*c3739801SMiguel Ojeda 126*c3739801SMiguel Ojeda impl<'a, T: ?Sized> PtrInner<'a, T> { 127*c3739801SMiguel Ojeda /// Constructs a `PtrInner` from a reference. 128*c3739801SMiguel Ojeda #[inline] 129*c3739801SMiguel Ojeda pub fn from_ref(ptr: &'a T) -> Self { 130*c3739801SMiguel Ojeda let ptr = NonNull::from(ptr); 131*c3739801SMiguel Ojeda // SAFETY: 132*c3739801SMiguel Ojeda // 0. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on 133*c3739801SMiguel Ojeda // `&'a T` [1], has valid provenance for its referent, which is 134*c3739801SMiguel Ojeda // entirely contained in some Rust allocation, `A`. 135*c3739801SMiguel Ojeda // 1. If `ptr`'s referent is not zero sized, then `A`, by invariant on 136*c3739801SMiguel Ojeda // `&'a T`, is guaranteed to live for at least `'a`. 137*c3739801SMiguel Ojeda // 138*c3739801SMiguel Ojeda // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety: 139*c3739801SMiguel Ojeda // 140*c3739801SMiguel Ojeda // For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, 141*c3739801SMiguel Ojeda // when such values cross an API boundary, the following invariants 142*c3739801SMiguel Ojeda // must generally be upheld: 143*c3739801SMiguel Ojeda // ... 144*c3739801SMiguel Ojeda // - if `size_of_val(t) > 0`, then `t` is dereferenceable for 145*c3739801SMiguel Ojeda // `size_of_val(t)` many bytes 146*c3739801SMiguel Ojeda // 147*c3739801SMiguel Ojeda // If `t` points at address `a`, being “dereferenceable” for N bytes 148*c3739801SMiguel Ojeda // means that the memory range `[a, a + N)` is all contained within a 149*c3739801SMiguel Ojeda // single allocated object. 150*c3739801SMiguel Ojeda unsafe { Self::new(ptr) } 151*c3739801SMiguel Ojeda } 152*c3739801SMiguel Ojeda 153*c3739801SMiguel Ojeda /// Constructs a `PtrInner` from a mutable reference. 154*c3739801SMiguel Ojeda #[inline] 155*c3739801SMiguel Ojeda pub fn from_mut(ptr: &'a mut T) -> Self { 156*c3739801SMiguel Ojeda let ptr = NonNull::from(ptr); 157*c3739801SMiguel Ojeda // SAFETY: 158*c3739801SMiguel Ojeda // 0. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on 159*c3739801SMiguel Ojeda // `&'a mut T` [1], has valid provenance for its referent, which is 160*c3739801SMiguel Ojeda // entirely contained in some Rust allocation, `A`. 161*c3739801SMiguel Ojeda // 1. If `ptr`'s referent is not zero sized, then `A`, by invariant on 162*c3739801SMiguel Ojeda // `&'a mut T`, is guaranteed to live for at least `'a`. 163*c3739801SMiguel Ojeda // 164*c3739801SMiguel Ojeda // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety: 165*c3739801SMiguel Ojeda // 166*c3739801SMiguel Ojeda // For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, 167*c3739801SMiguel Ojeda // when such values cross an API boundary, the following invariants 168*c3739801SMiguel Ojeda // must generally be upheld: 169*c3739801SMiguel Ojeda // ... 170*c3739801SMiguel Ojeda // - if `size_of_val(t) > 0`, then `t` is dereferenceable for 171*c3739801SMiguel Ojeda // `size_of_val(t)` many bytes 172*c3739801SMiguel Ojeda // 173*c3739801SMiguel Ojeda // If `t` points at address `a`, being “dereferenceable” for N bytes 174*c3739801SMiguel Ojeda // means that the memory range `[a, a + N)` is all contained within a 175*c3739801SMiguel Ojeda // single allocated object. 176*c3739801SMiguel Ojeda unsafe { Self::new(ptr) } 177*c3739801SMiguel Ojeda } 178*c3739801SMiguel Ojeda 179*c3739801SMiguel Ojeda /// # Safety 180*c3739801SMiguel Ojeda /// 181*c3739801SMiguel Ojeda /// The caller may assume that the resulting `PtrInner` addresses the subset 182*c3739801SMiguel Ojeda /// of the bytes of `self`'s referent addressed by `C::project(self)`. 183*c3739801SMiguel Ojeda #[must_use] 184*c3739801SMiguel Ojeda #[inline(always)] 185*c3739801SMiguel Ojeda pub fn project<U: ?Sized, C: cast::Project<T, U>>(self) -> PtrInner<'a, U> { 186*c3739801SMiguel Ojeda let projected_raw = C::project(self); 187*c3739801SMiguel Ojeda 188*c3739801SMiguel Ojeda // SAFETY: `self`'s referent lives at a `NonNull` address, and is either 189*c3739801SMiguel Ojeda // zero-sized or lives in an allocation. In either case, it does not 190*c3739801SMiguel Ojeda // wrap around the address space [1], and so none of the addresses 191*c3739801SMiguel Ojeda // contained in it or one-past-the-end of it are null. 192*c3739801SMiguel Ojeda // 193*c3739801SMiguel Ojeda // By invariant on `C: Project`, `C::project` is a provenance-preserving 194*c3739801SMiguel Ojeda // projection which preserves or shrinks the set of referent bytes, so 195*c3739801SMiguel Ojeda // `projected_raw` references a subset of `self`'s referent, and so it 196*c3739801SMiguel Ojeda // cannot be null. 197*c3739801SMiguel Ojeda // 198*c3739801SMiguel Ojeda // [1] https://doc.rust-lang.org/1.92.0/std/ptr/index.html#allocation 199*c3739801SMiguel Ojeda let projected_non_null = unsafe { NonNull::new_unchecked(projected_raw) }; 200*c3739801SMiguel Ojeda 201*c3739801SMiguel Ojeda // SAFETY: As described in the preceding safety comment, `projected_raw`, 202*c3739801SMiguel Ojeda // and thus `projected_non_null`, addresses a subset of `self`'s 203*c3739801SMiguel Ojeda // referent. Thus, `projected_non_null` either: 204*c3739801SMiguel Ojeda // - Addresses zero bytes or, 205*c3739801SMiguel Ojeda // - Addresses a subset of the referent of `self`. In this case, `self` 206*c3739801SMiguel Ojeda // has provenance for its referent, which lives in an allocation. 207*c3739801SMiguel Ojeda // Since `projected_non_null` was constructed using a sequence of 208*c3739801SMiguel Ojeda // provenance-preserving operations, it also has provenance for its 209*c3739801SMiguel Ojeda // referent and that referent lives in an allocation. By invariant on 210*c3739801SMiguel Ojeda // `self`, that allocation lives for `'a`. 211*c3739801SMiguel Ojeda unsafe { PtrInner::new(projected_non_null) } 212*c3739801SMiguel Ojeda } 213*c3739801SMiguel Ojeda } 214*c3739801SMiguel Ojeda 215*c3739801SMiguel Ojeda #[allow(clippy::needless_lifetimes)] 216*c3739801SMiguel Ojeda impl<'a, T> PtrInner<'a, T> 217*c3739801SMiguel Ojeda where 218*c3739801SMiguel Ojeda T: ?Sized + KnownLayout, 219*c3739801SMiguel Ojeda { 220*c3739801SMiguel Ojeda /// Extracts the metadata of this `ptr`. 221*c3739801SMiguel Ojeda #[inline] 222*c3739801SMiguel Ojeda #[must_use] 223*c3739801SMiguel Ojeda pub fn meta(self) -> MetadataOf<T> { 224*c3739801SMiguel Ojeda let meta = T::pointer_to_metadata(self.as_ptr()); 225*c3739801SMiguel Ojeda // SAFETY: By invariant on `PtrInner`, `self.as_non_null()` addresses no 226*c3739801SMiguel Ojeda // more than `isize::MAX` bytes. 227*c3739801SMiguel Ojeda unsafe { MetadataOf::new_unchecked(meta) } 228*c3739801SMiguel Ojeda } 229*c3739801SMiguel Ojeda 230*c3739801SMiguel Ojeda /// Produces a `PtrInner` with the same address and provenance as `self` but 231*c3739801SMiguel Ojeda /// the given `meta`. 232*c3739801SMiguel Ojeda /// 233*c3739801SMiguel Ojeda /// # Safety 234*c3739801SMiguel Ojeda /// 235*c3739801SMiguel Ojeda /// The caller promises that if `self`'s referent is not zero sized, then 236*c3739801SMiguel Ojeda /// a pointer constructed from its address with the given `meta` metadata 237*c3739801SMiguel Ojeda /// will address a subset of the allocation pointed to by `self`. 238*c3739801SMiguel Ojeda #[inline] 239*c3739801SMiguel Ojeda #[must_use] 240*c3739801SMiguel Ojeda pub unsafe fn with_meta(self, meta: T::PointerMetadata) -> Self 241*c3739801SMiguel Ojeda where 242*c3739801SMiguel Ojeda T: KnownLayout, 243*c3739801SMiguel Ojeda { 244*c3739801SMiguel Ojeda let raw = T::raw_from_ptr_len(self.as_non_null().cast(), meta); 245*c3739801SMiguel Ojeda 246*c3739801SMiguel Ojeda // SAFETY: 247*c3739801SMiguel Ojeda // 248*c3739801SMiguel Ojeda // Lemma 0: `raw` either addresses zero bytes, or addresses a subset of 249*c3739801SMiguel Ojeda // the allocation pointed to by `self` and has the same 250*c3739801SMiguel Ojeda // provenance as `self`. Proof: `raw` is constructed using 251*c3739801SMiguel Ojeda // provenance-preserving operations, and the caller has 252*c3739801SMiguel Ojeda // promised that, if `self`'s referent is not zero-sized, the 253*c3739801SMiguel Ojeda // resulting pointer addresses a subset of the allocation 254*c3739801SMiguel Ojeda // pointed to by `self`. 255*c3739801SMiguel Ojeda // 256*c3739801SMiguel Ojeda // 0. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not 257*c3739801SMiguel Ojeda // zero sized, then `ptr` is derived from some valid Rust allocation, 258*c3739801SMiguel Ojeda // `A`. 259*c3739801SMiguel Ojeda // 1. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not 260*c3739801SMiguel Ojeda // zero sized, then `ptr` has valid provenance for `A`. 261*c3739801SMiguel Ojeda // 2. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not 262*c3739801SMiguel Ojeda // zero sized, then `ptr` addresses a byte range which is entirely 263*c3739801SMiguel Ojeda // contained in `A`. 264*c3739801SMiguel Ojeda // 3. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte 265*c3739801SMiguel Ojeda // range whose length fits in an `isize`. 266*c3739801SMiguel Ojeda // 4. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte 267*c3739801SMiguel Ojeda // range which does not wrap around the address space. 268*c3739801SMiguel Ojeda // 5. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not 269*c3739801SMiguel Ojeda // zero sized, then `A` is guaranteed to live for at least `'a`. 270*c3739801SMiguel Ojeda unsafe { PtrInner::new(raw) } 271*c3739801SMiguel Ojeda } 272*c3739801SMiguel Ojeda } 273*c3739801SMiguel Ojeda 274*c3739801SMiguel Ojeda #[allow(clippy::needless_lifetimes)] 275*c3739801SMiguel Ojeda impl<'a, T> PtrInner<'a, T> 276*c3739801SMiguel Ojeda where 277*c3739801SMiguel Ojeda T: ?Sized + KnownLayout<PointerMetadata = usize>, 278*c3739801SMiguel Ojeda { 279*c3739801SMiguel Ojeda /// Splits `T` in two. 280*c3739801SMiguel Ojeda /// 281*c3739801SMiguel Ojeda /// # Safety 282*c3739801SMiguel Ojeda /// 283*c3739801SMiguel Ojeda /// The caller promises that: 284*c3739801SMiguel Ojeda /// - `l_len.get() <= self.meta()`. 285*c3739801SMiguel Ojeda /// 286*c3739801SMiguel Ojeda /// ## (Non-)Overlap 287*c3739801SMiguel Ojeda /// 288*c3739801SMiguel Ojeda /// Given `let (left, right) = ptr.split_at(l_len)`, it is guaranteed that 289*c3739801SMiguel Ojeda /// `left` and `right` are contiguous and non-overlapping if 290*c3739801SMiguel Ojeda /// `l_len.padding_needed_for() == 0`. This is true for all `[T]`. 291*c3739801SMiguel Ojeda /// 292*c3739801SMiguel Ojeda /// If `l_len.padding_needed_for() != 0`, then the left pointer will overlap 293*c3739801SMiguel Ojeda /// the right pointer to satisfy `T`'s padding requirements. 294*c3739801SMiguel Ojeda #[inline] 295*c3739801SMiguel Ojeda #[must_use] 296*c3739801SMiguel Ojeda pub unsafe fn split_at_unchecked( 297*c3739801SMiguel Ojeda self, 298*c3739801SMiguel Ojeda l_len: crate::util::MetadataOf<T>, 299*c3739801SMiguel Ojeda ) -> (Self, PtrInner<'a, [T::Elem]>) 300*c3739801SMiguel Ojeda where 301*c3739801SMiguel Ojeda T: SplitAt, 302*c3739801SMiguel Ojeda { 303*c3739801SMiguel Ojeda let l_len = l_len.get(); 304*c3739801SMiguel Ojeda 305*c3739801SMiguel Ojeda // SAFETY: The caller promises that `l_len.get() <= self.meta()`. 306*c3739801SMiguel Ojeda // Trivially, `0 <= l_len`. 307*c3739801SMiguel Ojeda let left = unsafe { self.with_meta(l_len) }; 308*c3739801SMiguel Ojeda 309*c3739801SMiguel Ojeda let right = self.trailing_slice(); 310*c3739801SMiguel Ojeda // SAFETY: The caller promises that `l_len <= self.meta() = slf.meta()`. 311*c3739801SMiguel Ojeda // Trivially, `slf.meta() <= slf.meta()`. 312*c3739801SMiguel Ojeda let right = unsafe { right.slice_unchecked(l_len..self.meta().get()) }; 313*c3739801SMiguel Ojeda 314*c3739801SMiguel Ojeda // SAFETY: If `l_len.padding_needed_for() == 0`, then `left` and `right` 315*c3739801SMiguel Ojeda // are non-overlapping. Proof: `left` is constructed `slf` with `l_len` 316*c3739801SMiguel Ojeda // as its (exclusive) upper bound. If `l_len.padding_needed_for() == 0`, 317*c3739801SMiguel Ojeda // then `left` requires no trailing padding following its final element. 318*c3739801SMiguel Ojeda // Since `right` is constructed from `slf`'s trailing slice with `l_len` 319*c3739801SMiguel Ojeda // as its (inclusive) lower bound, no byte is referred to by both 320*c3739801SMiguel Ojeda // pointers. 321*c3739801SMiguel Ojeda // 322*c3739801SMiguel Ojeda // Conversely, `l_len.padding_needed_for() == N`, where `N 323*c3739801SMiguel Ojeda // > 0`, `left` requires `N` bytes of trailing padding following its 324*c3739801SMiguel Ojeda // final element. Since `right` is constructed from the trailing slice 325*c3739801SMiguel Ojeda // of `slf` with `l_len` as its (inclusive) lower bound, the first `N` 326*c3739801SMiguel Ojeda // bytes of `right` are aliased by `left`. 327*c3739801SMiguel Ojeda (left, right) 328*c3739801SMiguel Ojeda } 329*c3739801SMiguel Ojeda 330*c3739801SMiguel Ojeda /// Produces the trailing slice of `self`. 331*c3739801SMiguel Ojeda #[inline] 332*c3739801SMiguel Ojeda #[must_use] 333*c3739801SMiguel Ojeda pub fn trailing_slice(self) -> PtrInner<'a, [T::Elem]> 334*c3739801SMiguel Ojeda where 335*c3739801SMiguel Ojeda T: SplitAt, 336*c3739801SMiguel Ojeda { 337*c3739801SMiguel Ojeda let offset = crate::trailing_slice_layout::<T>().offset; 338*c3739801SMiguel Ojeda 339*c3739801SMiguel Ojeda let bytes = self.as_non_null().cast::<u8>().as_ptr(); 340*c3739801SMiguel Ojeda 341*c3739801SMiguel Ojeda // SAFETY: 342*c3739801SMiguel Ojeda // - By invariant on `T: KnownLayout`, `T::LAYOUT` describes `T`'s 343*c3739801SMiguel Ojeda // layout. `offset` is the offset of the trailing slice within `T`, 344*c3739801SMiguel Ojeda // which is by definition in-bounds or one byte past the end of any 345*c3739801SMiguel Ojeda // `T`, regardless of metadata. By invariant on `PtrInner`, `self` 346*c3739801SMiguel Ojeda // (and thus `bytes`) points to a byte range of size `<= isize::MAX`, 347*c3739801SMiguel Ojeda // and so `offset <= isize::MAX`. Since `size_of::<u8>() == 1`, 348*c3739801SMiguel Ojeda // `offset * size_of::<u8>() <= isize::MAX`. 349*c3739801SMiguel Ojeda // - If `offset > 0`, then by invariant on `PtrInner`, `self` (and thus 350*c3739801SMiguel Ojeda // `bytes`) points to a byte range entirely contained within the same 351*c3739801SMiguel Ojeda // allocated object as `self`. As explained above, this offset results 352*c3739801SMiguel Ojeda // in a pointer to or one byte past the end of this allocated object. 353*c3739801SMiguel Ojeda let bytes = unsafe { bytes.add(offset) }; 354*c3739801SMiguel Ojeda 355*c3739801SMiguel Ojeda // SAFETY: By the preceding safety argument, `bytes` is within or one 356*c3739801SMiguel Ojeda // byte past the end of the same allocated object as `self`, which 357*c3739801SMiguel Ojeda // ensures that it is non-null. 358*c3739801SMiguel Ojeda let bytes = unsafe { NonNull::new_unchecked(bytes) }; 359*c3739801SMiguel Ojeda 360*c3739801SMiguel Ojeda let ptr = KnownLayout::raw_from_ptr_len(bytes, self.meta().get()); 361*c3739801SMiguel Ojeda 362*c3739801SMiguel Ojeda // SAFETY: 363*c3739801SMiguel Ojeda // 0. If `ptr`'s referent is not zero sized, then `ptr` is derived from 364*c3739801SMiguel Ojeda // some valid Rust allocation, `A`, because `ptr` is derived from 365*c3739801SMiguel Ojeda // the same allocated object as `self`. 366*c3739801SMiguel Ojeda // 1. If `ptr`'s referent is not zero sized, then `ptr` has valid 367*c3739801SMiguel Ojeda // provenance for `A` because `raw` is derived from the same 368*c3739801SMiguel Ojeda // allocated object as `self` via provenance-preserving operations. 369*c3739801SMiguel Ojeda // 2. If `ptr`'s referent is not zero sized, then `ptr` addresses a byte 370*c3739801SMiguel Ojeda // range which is entirely contained in `A`, by previous safety proof 371*c3739801SMiguel Ojeda // on `bytes`. 372*c3739801SMiguel Ojeda // 3. `ptr` addresses a byte range whose length fits in an `isize`, by 373*c3739801SMiguel Ojeda // consequence of #2. 374*c3739801SMiguel Ojeda // 4. `ptr` addresses a byte range which does not wrap around the 375*c3739801SMiguel Ojeda // address space, by consequence of #2. 376*c3739801SMiguel Ojeda // 5. If `ptr`'s referent is not zero sized, then `A` is guaranteed to 377*c3739801SMiguel Ojeda // live for at least `'a`, because `ptr` is derived from `self`. 378*c3739801SMiguel Ojeda unsafe { PtrInner::new(ptr) } 379*c3739801SMiguel Ojeda } 380*c3739801SMiguel Ojeda } 381*c3739801SMiguel Ojeda 382*c3739801SMiguel Ojeda #[allow(clippy::needless_lifetimes)] 383*c3739801SMiguel Ojeda impl<'a, T> PtrInner<'a, [T]> { 384*c3739801SMiguel Ojeda /// Creates a pointer which addresses the given `range` of self. 385*c3739801SMiguel Ojeda /// 386*c3739801SMiguel Ojeda /// # Safety 387*c3739801SMiguel Ojeda /// 388*c3739801SMiguel Ojeda /// `range` is a valid range (`start <= end`) and `end <= self.meta()`. 389*c3739801SMiguel Ojeda #[inline] 390*c3739801SMiguel Ojeda #[must_use] 391*c3739801SMiguel Ojeda pub unsafe fn slice_unchecked(self, range: Range<usize>) -> Self { 392*c3739801SMiguel Ojeda let base = self.as_non_null().cast::<T>().as_ptr(); 393*c3739801SMiguel Ojeda 394*c3739801SMiguel Ojeda // SAFETY: The caller promises that `start <= end <= self.meta()`. By 395*c3739801SMiguel Ojeda // invariant, if `self`'s referent is not zero-sized, then `self` refers 396*c3739801SMiguel Ojeda // to a byte range which is contained within a single allocation, which 397*c3739801SMiguel Ojeda // is no more than `isize::MAX` bytes long, and which does not wrap 398*c3739801SMiguel Ojeda // around the address space. Thus, this pointer arithmetic remains 399*c3739801SMiguel Ojeda // in-bounds of the same allocation, and does not wrap around the 400*c3739801SMiguel Ojeda // address space. The offset (in bytes) does not overflow `isize`. 401*c3739801SMiguel Ojeda // 402*c3739801SMiguel Ojeda // If `self`'s referent is zero-sized, then these conditions are 403*c3739801SMiguel Ojeda // trivially satisfied. 404*c3739801SMiguel Ojeda let base = unsafe { base.add(range.start) }; 405*c3739801SMiguel Ojeda 406*c3739801SMiguel Ojeda // SAFETY: The caller promises that `start <= end`, and so this will not 407*c3739801SMiguel Ojeda // underflow. 408*c3739801SMiguel Ojeda #[allow(unstable_name_collisions)] 409*c3739801SMiguel Ojeda let len = unsafe { range.end.unchecked_sub(range.start) }; 410*c3739801SMiguel Ojeda 411*c3739801SMiguel Ojeda let ptr = core::ptr::slice_from_raw_parts_mut(base, len); 412*c3739801SMiguel Ojeda 413*c3739801SMiguel Ojeda // SAFETY: By invariant, `self`'s referent is either a ZST or lives 414*c3739801SMiguel Ojeda // entirely in an allocation. `ptr` points inside of or one byte past 415*c3739801SMiguel Ojeda // the end of that referent. Thus, in either case, `ptr` is non-null. 416*c3739801SMiguel Ojeda let ptr = unsafe { NonNull::new_unchecked(ptr) }; 417*c3739801SMiguel Ojeda 418*c3739801SMiguel Ojeda // SAFETY: 419*c3739801SMiguel Ojeda // 420*c3739801SMiguel Ojeda // Lemma 0: `ptr` addresses a subset of the bytes addressed by `self`, 421*c3739801SMiguel Ojeda // and has the same provenance. Proof: The caller guarantees 422*c3739801SMiguel Ojeda // that `start <= end <= self.meta()`. Thus, `base` is 423*c3739801SMiguel Ojeda // in-bounds of `self`, and `base + (end - start)` is also 424*c3739801SMiguel Ojeda // in-bounds of self. Finally, `ptr` is constructed using 425*c3739801SMiguel Ojeda // provenance-preserving operations. 426*c3739801SMiguel Ojeda // 427*c3739801SMiguel Ojeda // 0. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not 428*c3739801SMiguel Ojeda // zero sized, then `ptr` has valid provenance for its referent, 429*c3739801SMiguel Ojeda // which is entirely contained in some Rust allocation, `A`. 430*c3739801SMiguel Ojeda // 1. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not 431*c3739801SMiguel Ojeda // zero sized, then `A` is guaranteed to live for at least `'a`. 432*c3739801SMiguel Ojeda unsafe { PtrInner::new(ptr) } 433*c3739801SMiguel Ojeda } 434*c3739801SMiguel Ojeda 435*c3739801SMiguel Ojeda /// Iteratively projects the elements `PtrInner<T>` from `PtrInner<[T]>`. 436*c3739801SMiguel Ojeda #[inline] 437*c3739801SMiguel Ojeda pub fn iter(&self) -> impl Iterator<Item = PtrInner<'a, T>> { 438*c3739801SMiguel Ojeda // FIXME(#429): Once `NonNull::cast` documents that it preserves 439*c3739801SMiguel Ojeda // provenance, cite those docs. 440*c3739801SMiguel Ojeda let base = self.as_non_null().cast::<T>().as_ptr(); 441*c3739801SMiguel Ojeda (0..self.meta().get()).map(move |i| { 442*c3739801SMiguel Ojeda // FIXME(https://github.com/rust-lang/rust/issues/74265): Use 443*c3739801SMiguel Ojeda // `NonNull::get_unchecked_mut`. 444*c3739801SMiguel Ojeda 445*c3739801SMiguel Ojeda // SAFETY: If the following conditions are not satisfied 446*c3739801SMiguel Ojeda // `pointer::cast` may induce Undefined Behavior [1]: 447*c3739801SMiguel Ojeda // 448*c3739801SMiguel Ojeda // > - The computed offset, `count * size_of::<T>()` bytes, must not 449*c3739801SMiguel Ojeda // > overflow `isize``. 450*c3739801SMiguel Ojeda // > - If the computed offset is non-zero, then `self` must be 451*c3739801SMiguel Ojeda // > derived from a pointer to some allocated object, and the 452*c3739801SMiguel Ojeda // > entire memory range between `self` and the result must be in 453*c3739801SMiguel Ojeda // > bounds of that allocated object. In particular, this range 454*c3739801SMiguel Ojeda // > must not “wrap around” the edge of the address space. 455*c3739801SMiguel Ojeda // 456*c3739801SMiguel Ojeda // [1] https://doc.rust-lang.org/std/primitive.pointer.html#method.add 457*c3739801SMiguel Ojeda // 458*c3739801SMiguel Ojeda // We satisfy both of these conditions here: 459*c3739801SMiguel Ojeda // - By invariant on `Ptr`, `self` addresses a byte range whose 460*c3739801SMiguel Ojeda // length fits in an `isize`. Since `elem` is contained in `self`, 461*c3739801SMiguel Ojeda // the computed offset of `elem` must fit within `isize.` 462*c3739801SMiguel Ojeda // - If the computed offset is non-zero, then this means that the 463*c3739801SMiguel Ojeda // referent is not zero-sized. In this case, `base` points to an 464*c3739801SMiguel Ojeda // allocated object (by invariant on `self`). Thus: 465*c3739801SMiguel Ojeda // - By contract, `self.meta()` accurately reflects the number of 466*c3739801SMiguel Ojeda // elements in the slice. `i` is in bounds of `c.meta()` by 467*c3739801SMiguel Ojeda // construction, and so the result of this addition cannot 468*c3739801SMiguel Ojeda // overflow past the end of the allocation referred to by `c`. 469*c3739801SMiguel Ojeda // - By invariant on `Ptr`, `self` addresses a byte range which 470*c3739801SMiguel Ojeda // does not wrap around the address space. Since `elem` is 471*c3739801SMiguel Ojeda // contained in `self`, the computed offset of `elem` must wrap 472*c3739801SMiguel Ojeda // around the address space. 473*c3739801SMiguel Ojeda // 474*c3739801SMiguel Ojeda // FIXME(#429): Once `pointer::add` documents that it preserves 475*c3739801SMiguel Ojeda // provenance, cite those docs. 476*c3739801SMiguel Ojeda let elem = unsafe { base.add(i) }; 477*c3739801SMiguel Ojeda 478*c3739801SMiguel Ojeda // SAFETY: `elem` must not be null. `base` is constructed from a 479*c3739801SMiguel Ojeda // `NonNull` pointer, and the addition that produces `elem` must not 480*c3739801SMiguel Ojeda // overflow or wrap around, so `elem >= base > 0`. 481*c3739801SMiguel Ojeda // 482*c3739801SMiguel Ojeda // FIXME(#429): Once `NonNull::new_unchecked` documents that it 483*c3739801SMiguel Ojeda // preserves provenance, cite those docs. 484*c3739801SMiguel Ojeda let elem = unsafe { NonNull::new_unchecked(elem) }; 485*c3739801SMiguel Ojeda 486*c3739801SMiguel Ojeda // SAFETY: The safety invariants of `Ptr::new` (see definition) are 487*c3739801SMiguel Ojeda // satisfied: 488*c3739801SMiguel Ojeda // 0. If `elem`'s referent is not zero sized, then `elem` has valid 489*c3739801SMiguel Ojeda // provenance for its referent, because it derived from `self` 490*c3739801SMiguel Ojeda // using a series of provenance-preserving operations, and 491*c3739801SMiguel Ojeda // because `self` has valid provenance for its referent. By the 492*c3739801SMiguel Ojeda // same argument, `elem`'s referent is entirely contained within 493*c3739801SMiguel Ojeda // the same allocated object as `self`'s referent. 494*c3739801SMiguel Ojeda // 1. If `elem`'s referent is not zero sized, then the allocation of 495*c3739801SMiguel Ojeda // `elem` is guaranteed to live for at least `'a`, because `elem` 496*c3739801SMiguel Ojeda // is entirely contained in `self`, which lives for at least `'a` 497*c3739801SMiguel Ojeda // by invariant on `Ptr`. 498*c3739801SMiguel Ojeda unsafe { PtrInner::new(elem) } 499*c3739801SMiguel Ojeda }) 500*c3739801SMiguel Ojeda } 501*c3739801SMiguel Ojeda } 502*c3739801SMiguel Ojeda 503*c3739801SMiguel Ojeda impl<'a, T, const N: usize> PtrInner<'a, [T; N]> { 504*c3739801SMiguel Ojeda /// Casts this pointer-to-array into a slice. 505*c3739801SMiguel Ojeda /// 506*c3739801SMiguel Ojeda /// # Safety 507*c3739801SMiguel Ojeda /// 508*c3739801SMiguel Ojeda /// Callers may assume that the returned `PtrInner` references the same 509*c3739801SMiguel Ojeda /// address and length as `self`. 510*c3739801SMiguel Ojeda #[allow(clippy::wrong_self_convention)] 511*c3739801SMiguel Ojeda #[inline] 512*c3739801SMiguel Ojeda #[must_use] 513*c3739801SMiguel Ojeda pub fn as_slice(self) -> PtrInner<'a, [T]> { 514*c3739801SMiguel Ojeda let start = self.as_non_null().cast::<T>().as_ptr(); 515*c3739801SMiguel Ojeda let slice = core::ptr::slice_from_raw_parts_mut(start, N); 516*c3739801SMiguel Ojeda // SAFETY: `slice` is not null, because it is derived from `start` 517*c3739801SMiguel Ojeda // which is non-null. 518*c3739801SMiguel Ojeda let slice = unsafe { NonNull::new_unchecked(slice) }; 519*c3739801SMiguel Ojeda // SAFETY: Lemma: In the following safety arguments, note that `slice` 520*c3739801SMiguel Ojeda // is derived from `self` in two steps: first, by casting `self: [T; N]` 521*c3739801SMiguel Ojeda // to `start: T`, then by constructing a pointer to a slice starting at 522*c3739801SMiguel Ojeda // `start` of length `N`. As a result, `slice` references exactly the 523*c3739801SMiguel Ojeda // same allocation as `self`, if any. 524*c3739801SMiguel Ojeda // 525*c3739801SMiguel Ojeda // 0. By the above lemma, if `slice`'s referent is not zero sized, then 526*c3739801SMiguel Ojeda // `slice` has the same referent as `self`. By invariant on `self`, 527*c3739801SMiguel Ojeda // this referent is entirely contained within some allocation, `A`. 528*c3739801SMiguel Ojeda // Because `slice` was constructed using provenance-preserving 529*c3739801SMiguel Ojeda // operations, it has provenance for its entire referent. 530*c3739801SMiguel Ojeda // 1. By the above lemma, if `slice`'s referent is not zero sized, then 531*c3739801SMiguel Ojeda // `A` is guaranteed to live for at least `'a`, because it is derived 532*c3739801SMiguel Ojeda // from the same allocation as `self`, which, by invariant on 533*c3739801SMiguel Ojeda // `PtrInner`, lives for at least `'a`. 534*c3739801SMiguel Ojeda unsafe { PtrInner::new(slice) } 535*c3739801SMiguel Ojeda } 536*c3739801SMiguel Ojeda } 537*c3739801SMiguel Ojeda 538*c3739801SMiguel Ojeda impl<'a> PtrInner<'a, [u8]> { 539*c3739801SMiguel Ojeda /// Attempts to cast `self` to a `U` using the given cast type. 540*c3739801SMiguel Ojeda /// 541*c3739801SMiguel Ojeda /// If `U` is a slice DST and pointer metadata (`meta`) is provided, then 542*c3739801SMiguel Ojeda /// the cast will only succeed if it would produce an object with the given 543*c3739801SMiguel Ojeda /// metadata. 544*c3739801SMiguel Ojeda /// 545*c3739801SMiguel Ojeda /// Returns `None` if the resulting `U` would be invalidly-aligned, if no 546*c3739801SMiguel Ojeda /// `U` can fit in `self`, or if the provided pointer metadata describes an 547*c3739801SMiguel Ojeda /// invalid instance of `U`. On success, returns a pointer to the 548*c3739801SMiguel Ojeda /// largest-possible `U` which fits in `self`. 549*c3739801SMiguel Ojeda /// 550*c3739801SMiguel Ojeda /// # Safety 551*c3739801SMiguel Ojeda /// 552*c3739801SMiguel Ojeda /// The caller may assume that this implementation is correct, and may rely 553*c3739801SMiguel Ojeda /// on that assumption for the soundness of their code. In particular, the 554*c3739801SMiguel Ojeda /// caller may assume that, if `try_cast_into` returns `Some((ptr, 555*c3739801SMiguel Ojeda /// remainder))`, then `ptr` and `remainder` refer to non-overlapping byte 556*c3739801SMiguel Ojeda /// ranges within `self`, and that `ptr` and `remainder` entirely cover 557*c3739801SMiguel Ojeda /// `self`. Finally: 558*c3739801SMiguel Ojeda /// - If this is a prefix cast, `ptr` has the same address as `self`. 559*c3739801SMiguel Ojeda /// - If this is a suffix cast, `remainder` has the same address as `self`. 560*c3739801SMiguel Ojeda #[inline] 561*c3739801SMiguel Ojeda pub fn try_cast_into<U>( 562*c3739801SMiguel Ojeda self, 563*c3739801SMiguel Ojeda cast_type: CastType, 564*c3739801SMiguel Ojeda meta: Option<U::PointerMetadata>, 565*c3739801SMiguel Ojeda ) -> Result<(PtrInner<'a, U>, PtrInner<'a, [u8]>), CastError<Self, U>> 566*c3739801SMiguel Ojeda where 567*c3739801SMiguel Ojeda U: 'a + ?Sized + KnownLayout, 568*c3739801SMiguel Ojeda { 569*c3739801SMiguel Ojeda // PANICS: By invariant, the byte range addressed by 570*c3739801SMiguel Ojeda // `self.as_non_null()` does not wrap around the address space. This 571*c3739801SMiguel Ojeda // implies that the sum of the address (represented as a `usize`) and 572*c3739801SMiguel Ojeda // length do not overflow `usize`, as required by 573*c3739801SMiguel Ojeda // `validate_cast_and_convert_metadata`. Thus, this call to 574*c3739801SMiguel Ojeda // `validate_cast_and_convert_metadata` will only panic if `U` is a DST 575*c3739801SMiguel Ojeda // whose trailing slice element is zero-sized. 576*c3739801SMiguel Ojeda let maybe_metadata = MetadataOf::<U>::validate_cast_and_convert_metadata( 577*c3739801SMiguel Ojeda AsAddress::addr(self.as_ptr()), 578*c3739801SMiguel Ojeda self.meta(), 579*c3739801SMiguel Ojeda cast_type, 580*c3739801SMiguel Ojeda meta, 581*c3739801SMiguel Ojeda ); 582*c3739801SMiguel Ojeda 583*c3739801SMiguel Ojeda let (elems, split_at) = match maybe_metadata { 584*c3739801SMiguel Ojeda Ok((elems, split_at)) => (elems, split_at), 585*c3739801SMiguel Ojeda Err(MetadataCastError::Alignment) => { 586*c3739801SMiguel Ojeda // SAFETY: Since `validate_cast_and_convert_metadata` returned 587*c3739801SMiguel Ojeda // an alignment error, `U` must have an alignment requirement 588*c3739801SMiguel Ojeda // greater than one. 589*c3739801SMiguel Ojeda let err = unsafe { AlignmentError::<_, U>::new_unchecked(self) }; 590*c3739801SMiguel Ojeda return Err(CastError::Alignment(err)); 591*c3739801SMiguel Ojeda } 592*c3739801SMiguel Ojeda Err(MetadataCastError::Size) => return Err(CastError::Size(SizeError::new(self))), 593*c3739801SMiguel Ojeda }; 594*c3739801SMiguel Ojeda 595*c3739801SMiguel Ojeda // SAFETY: `validate_cast_and_convert_metadata` promises to return 596*c3739801SMiguel Ojeda // `split_at <= self.meta()`. 597*c3739801SMiguel Ojeda // 598*c3739801SMiguel Ojeda // Lemma 0: `l_slice` and `r_slice` are non-overlapping. Proof: By 599*c3739801SMiguel Ojeda // contract on `PtrInner::split_at_unchecked`, the produced `PtrInner`s 600*c3739801SMiguel Ojeda // are always non-overlapping if `self` is a `[T]`; here it is a `[u8]`. 601*c3739801SMiguel Ojeda let (l_slice, r_slice) = unsafe { self.split_at_unchecked(split_at) }; 602*c3739801SMiguel Ojeda 603*c3739801SMiguel Ojeda let (target, remainder) = match cast_type { 604*c3739801SMiguel Ojeda CastType::Prefix => (l_slice, r_slice), 605*c3739801SMiguel Ojeda CastType::Suffix => (r_slice, l_slice), 606*c3739801SMiguel Ojeda }; 607*c3739801SMiguel Ojeda 608*c3739801SMiguel Ojeda let base = target.as_non_null().cast::<u8>(); 609*c3739801SMiguel Ojeda 610*c3739801SMiguel Ojeda let ptr = U::raw_from_ptr_len(base, elems.get()); 611*c3739801SMiguel Ojeda 612*c3739801SMiguel Ojeda // SAFETY: 613*c3739801SMiguel Ojeda // 0. By invariant, if `target`'s referent is not zero sized, then 614*c3739801SMiguel Ojeda // `target` has provenance valid for some Rust allocation, `A`. 615*c3739801SMiguel Ojeda // Because `ptr` is derived from `target` via provenance-preserving 616*c3739801SMiguel Ojeda // operations, `ptr` will also have provenance valid for its entire 617*c3739801SMiguel Ojeda // referent. 618*c3739801SMiguel Ojeda // 1. `validate_cast_and_convert_metadata` promises that the object 619*c3739801SMiguel Ojeda // described by `elems` and `split_at` lives at a byte range which is 620*c3739801SMiguel Ojeda // a subset of the input byte range. Thus, by invariant, if 621*c3739801SMiguel Ojeda // `target`'s referent is not zero sized, then `target` refers to an 622*c3739801SMiguel Ojeda // allocation which is guaranteed to live for at least `'a`, and thus 623*c3739801SMiguel Ojeda // so does `ptr`. 624*c3739801SMiguel Ojeda Ok((unsafe { PtrInner::new(ptr) }, remainder)) 625*c3739801SMiguel Ojeda } 626*c3739801SMiguel Ojeda } 627*c3739801SMiguel Ojeda 628*c3739801SMiguel Ojeda #[cfg(test)] 629*c3739801SMiguel Ojeda mod tests { 630*c3739801SMiguel Ojeda use super::*; 631*c3739801SMiguel Ojeda use crate::*; 632*c3739801SMiguel Ojeda 633*c3739801SMiguel Ojeda #[test] 634*c3739801SMiguel Ojeda fn test_meta() { 635*c3739801SMiguel Ojeda let arr = [1; 16]; 636*c3739801SMiguel Ojeda let dst = <[u8]>::ref_from_bytes(&arr[..]).unwrap(); 637*c3739801SMiguel Ojeda let ptr = PtrInner::from_ref(dst); 638*c3739801SMiguel Ojeda assert_eq!(ptr.meta().get(), 16); 639*c3739801SMiguel Ojeda 640*c3739801SMiguel Ojeda // SAFETY: 8 is less than 16 641*c3739801SMiguel Ojeda let ptr = unsafe { ptr.with_meta(8) }; 642*c3739801SMiguel Ojeda 643*c3739801SMiguel Ojeda assert_eq!(ptr.meta().get(), 8); 644*c3739801SMiguel Ojeda } 645*c3739801SMiguel Ojeda 646*c3739801SMiguel Ojeda #[test] 647*c3739801SMiguel Ojeda fn test_split_at() { 648*c3739801SMiguel Ojeda fn test_split_at<const OFFSET: usize, const BUFFER_SIZE: usize>() { 649*c3739801SMiguel Ojeda #[derive(FromBytes, KnownLayout, SplitAt, Immutable)] 650*c3739801SMiguel Ojeda #[repr(C)] 651*c3739801SMiguel Ojeda struct SliceDst<const OFFSET: usize> { 652*c3739801SMiguel Ojeda prefix: [u8; OFFSET], 653*c3739801SMiguel Ojeda trailing: [u8], 654*c3739801SMiguel Ojeda } 655*c3739801SMiguel Ojeda 656*c3739801SMiguel Ojeda let n: usize = BUFFER_SIZE - OFFSET; 657*c3739801SMiguel Ojeda let arr = [1; BUFFER_SIZE]; 658*c3739801SMiguel Ojeda let dst = SliceDst::<OFFSET>::ref_from_bytes(&arr[..]).unwrap(); 659*c3739801SMiguel Ojeda let ptr = PtrInner::from_ref(dst); 660*c3739801SMiguel Ojeda for i in 0..=n { 661*c3739801SMiguel Ojeda assert_eq!(ptr.meta().get(), n); 662*c3739801SMiguel Ojeda // SAFETY: `i` is in bounds by construction. 663*c3739801SMiguel Ojeda let i = unsafe { MetadataOf::new_unchecked(i) }; 664*c3739801SMiguel Ojeda // SAFETY: `i` is in bounds by construction. 665*c3739801SMiguel Ojeda let (l, r) = unsafe { ptr.split_at_unchecked(i) }; 666*c3739801SMiguel Ojeda // SAFETY: Points to a valid value by construction. 667*c3739801SMiguel Ojeda #[allow(clippy::undocumented_unsafe_blocks, clippy::as_conversions)] 668*c3739801SMiguel Ojeda // Clippy false positive 669*c3739801SMiguel Ojeda let l_sum: usize = l 670*c3739801SMiguel Ojeda .trailing_slice() 671*c3739801SMiguel Ojeda .iter() 672*c3739801SMiguel Ojeda .map( 673*c3739801SMiguel Ojeda #[inline(always)] 674*c3739801SMiguel Ojeda |ptr| unsafe { core::ptr::read_unaligned(ptr.as_ptr()) } as usize, 675*c3739801SMiguel Ojeda ) 676*c3739801SMiguel Ojeda .sum(); 677*c3739801SMiguel Ojeda // SAFETY: Points to a valid value by construction. 678*c3739801SMiguel Ojeda #[allow(clippy::undocumented_unsafe_blocks, clippy::as_conversions)] 679*c3739801SMiguel Ojeda // Clippy false positive 680*c3739801SMiguel Ojeda let r_sum: usize = r 681*c3739801SMiguel Ojeda .iter() 682*c3739801SMiguel Ojeda .map( 683*c3739801SMiguel Ojeda #[inline(always)] 684*c3739801SMiguel Ojeda |ptr| unsafe { core::ptr::read_unaligned(ptr.as_ptr()) } as usize, 685*c3739801SMiguel Ojeda ) 686*c3739801SMiguel Ojeda .sum(); 687*c3739801SMiguel Ojeda assert_eq!(l_sum, i.get()); 688*c3739801SMiguel Ojeda assert_eq!(r_sum, n - i.get()); 689*c3739801SMiguel Ojeda assert_eq!(l_sum + r_sum, n); 690*c3739801SMiguel Ojeda } 691*c3739801SMiguel Ojeda } 692*c3739801SMiguel Ojeda 693*c3739801SMiguel Ojeda test_split_at::<0, 16>(); 694*c3739801SMiguel Ojeda test_split_at::<1, 17>(); 695*c3739801SMiguel Ojeda test_split_at::<2, 18>(); 696*c3739801SMiguel Ojeda } 697*c3739801SMiguel Ojeda 698*c3739801SMiguel Ojeda #[test] 699*c3739801SMiguel Ojeda fn test_trailing_slice() { 700*c3739801SMiguel Ojeda fn test_trailing_slice<const OFFSET: usize, const BUFFER_SIZE: usize>() { 701*c3739801SMiguel Ojeda #[derive(FromBytes, KnownLayout, SplitAt, Immutable)] 702*c3739801SMiguel Ojeda #[repr(C)] 703*c3739801SMiguel Ojeda struct SliceDst<const OFFSET: usize> { 704*c3739801SMiguel Ojeda prefix: [u8; OFFSET], 705*c3739801SMiguel Ojeda trailing: [u8], 706*c3739801SMiguel Ojeda } 707*c3739801SMiguel Ojeda 708*c3739801SMiguel Ojeda let n: usize = BUFFER_SIZE - OFFSET; 709*c3739801SMiguel Ojeda let arr = [1; BUFFER_SIZE]; 710*c3739801SMiguel Ojeda let dst = SliceDst::<OFFSET>::ref_from_bytes(&arr[..]).unwrap(); 711*c3739801SMiguel Ojeda let ptr = PtrInner::from_ref(dst); 712*c3739801SMiguel Ojeda 713*c3739801SMiguel Ojeda assert_eq!(ptr.meta().get(), n); 714*c3739801SMiguel Ojeda let trailing = ptr.trailing_slice(); 715*c3739801SMiguel Ojeda assert_eq!(trailing.meta().get(), n); 716*c3739801SMiguel Ojeda 717*c3739801SMiguel Ojeda assert_eq!( 718*c3739801SMiguel Ojeda // SAFETY: We assume this to be sound for the sake of this test, 719*c3739801SMiguel Ojeda // which will fail, here, in miri, if the safety precondition of 720*c3739801SMiguel Ojeda // `offset_of` is not satisfied. 721*c3739801SMiguel Ojeda unsafe { 722*c3739801SMiguel Ojeda #[allow(clippy::as_conversions)] 723*c3739801SMiguel Ojeda let offset = (trailing.as_ptr() as *mut u8).offset_from(ptr.as_ptr() as *mut _); 724*c3739801SMiguel Ojeda offset 725*c3739801SMiguel Ojeda }, 726*c3739801SMiguel Ojeda isize::try_from(OFFSET).unwrap(), 727*c3739801SMiguel Ojeda ); 728*c3739801SMiguel Ojeda 729*c3739801SMiguel Ojeda // SAFETY: Points to a valid value by construction. 730*c3739801SMiguel Ojeda #[allow(clippy::undocumented_unsafe_blocks, clippy::as_conversions)] 731*c3739801SMiguel Ojeda // Clippy false positive 732*c3739801SMiguel Ojeda let trailing: usize = trailing 733*c3739801SMiguel Ojeda .iter() 734*c3739801SMiguel Ojeda .map(|ptr| unsafe { core::ptr::read_unaligned(ptr.as_ptr()) } as usize) 735*c3739801SMiguel Ojeda .sum(); 736*c3739801SMiguel Ojeda 737*c3739801SMiguel Ojeda assert_eq!(trailing, n); 738*c3739801SMiguel Ojeda } 739*c3739801SMiguel Ojeda 740*c3739801SMiguel Ojeda test_trailing_slice::<0, 16>(); 741*c3739801SMiguel Ojeda test_trailing_slice::<1, 17>(); 742*c3739801SMiguel Ojeda test_trailing_slice::<2, 18>(); 743*c3739801SMiguel Ojeda } 744*c3739801SMiguel Ojeda #[test] 745*c3739801SMiguel Ojeda fn test_ptr_inner_clone() { 746*c3739801SMiguel Ojeda let mut x = 0u8; 747*c3739801SMiguel Ojeda let p = PtrInner::from_mut(&mut x); 748*c3739801SMiguel Ojeda #[allow(clippy::clone_on_copy)] 749*c3739801SMiguel Ojeda let p2 = p.clone(); 750*c3739801SMiguel Ojeda assert_eq!(p.as_non_null(), p2.as_non_null()); 751*c3739801SMiguel Ojeda } 752*c3739801SMiguel Ojeda } 753