zerocopy/pointer/inner.rs
1// Copyright 2024 The Fuchsia Authors
2//
3// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
4// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
5// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
6// This file may not be copied, modified, or distributed except according to
7// those terms.
8
9use core::{marker::PhantomData, ops::Range, ptr::NonNull};
10
11#[allow(unused_imports)]
12use crate::util::polyfills::NumExt as _;
13use crate::{
14 layout::{CastType, DstLayout, MetadataCastError},
15 util::AsAddress,
16 AlignmentError, CastError, KnownLayout, PointerMetadata, SizeError,
17};
18
19pub(crate) use _def::PtrInner;
20
21mod _def {
22 use super::*;
23 /// The inner pointer stored inside a [`Ptr`][crate::Ptr].
24 ///
25 /// `PtrInner<'a, T>` is [covariant] in `'a` and invariant in `T`.
26 ///
27 /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
28 pub(crate) struct PtrInner<'a, T>
29 where
30 T: ?Sized,
31 {
32 /// # Invariants
33 ///
34 /// 0. If `ptr`'s referent is not zero sized, then `ptr` is derived from
35 /// some valid Rust allocation, `A`.
36 /// 1. If `ptr`'s referent is not zero sized, then `ptr` has valid
37 /// provenance for `A`.
38 /// 2. If `ptr`'s referent is not zero sized, then `ptr` addresses a
39 /// byte range which is entirely contained in `A`.
40 /// 3. `ptr` addresses a byte range whose length fits in an `isize`.
41 /// 4. `ptr` addresses a byte range which does not wrap around the
42 /// address space.
43 /// 5. If `ptr`'s referent is not zero sized,`A` is guaranteed to live
44 /// for at least `'a`.
45 ptr: NonNull<T>,
46 // SAFETY: `&'a UnsafeCell<T>` is covariant in `'a` and invariant in `T`
47 // [1]. We use this construction rather than the equivalent `&mut T`,
48 // because our MSRV of 1.65 prohibits `&mut` types in const contexts.
49 //
50 // [1] https://doc.rust-lang.org/1.81.0/reference/subtyping.html#variance
51 _marker: PhantomData<&'a core::cell::UnsafeCell<T>>,
52 }
53
54 impl<'a, T: 'a + ?Sized> Copy for PtrInner<'a, T> {}
55 impl<'a, T: 'a + ?Sized> Clone for PtrInner<'a, T> {
56 fn clone(&self) -> PtrInner<'a, T> {
57 // SAFETY: None of the invariants on `ptr` are affected by having
58 // multiple copies of a `PtrInner`.
59 *self
60 }
61 }
62
63 impl<'a, T: 'a + ?Sized> PtrInner<'a, T> {
64 /// Constructs a `Ptr` from a [`NonNull`].
65 ///
66 /// # Safety
67 ///
68 /// The caller promises that:
69 ///
70 /// 0. If `ptr`'s referent is not zero sized, then `ptr` is derived from
71 /// some valid Rust allocation, `A`.
72 /// 1. If `ptr`'s referent is not zero sized, then `ptr` has valid
73 /// provenance for `A`.
74 /// 2. If `ptr`'s referent is not zero sized, then `ptr` addresses a
75 /// byte range which is entirely contained in `A`.
76 /// 3. `ptr` addresses a byte range whose length fits in an `isize`.
77 /// 4. `ptr` addresses a byte range which does not wrap around the
78 /// address space.
79 /// 5. If `ptr`'s referent is not zero sized, then `A` is guaranteed to
80 /// live for at least `'a`.
81 pub(crate) const unsafe fn new(ptr: NonNull<T>) -> PtrInner<'a, T> {
82 // SAFETY: The caller has promised to satisfy all safety invariants
83 // of `PtrInner`.
84 Self { ptr, _marker: PhantomData }
85 }
86
87 /// Converts this `PtrInner<T>` to a [`NonNull<T>`].
88 ///
89 /// Note that this method does not consume `self`. The caller should
90 /// watch out for `unsafe` code which uses the returned `NonNull` in a
91 /// way that violates the safety invariants of `self`.
92 pub(crate) const fn as_non_null(&self) -> NonNull<T> {
93 self.ptr
94 }
95 }
96}
97
98impl<'a, T: ?Sized> PtrInner<'a, T> {
99 /// Constructs a `PtrInner` from a reference.
100 #[inline]
101 pub(crate) fn from_ref(ptr: &'a T) -> Self {
102 let ptr = NonNull::from(ptr);
103 // SAFETY:
104 // 0. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on
105 // `&'a T`, is derived from some valid Rust allocation, `A`.
106 // 1. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on
107 // `&'a T`, has valid provenance for `A`.
108 // 2. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on
109 // `&'a T`, addresses a byte range which is entirely contained in
110 // `A`.
111 // 3. `ptr`, by invariant on `&'a T`, addresses a byte range whose
112 // length fits in an `isize`.
113 // 4. `ptr`, by invariant on `&'a T`, addresses a byte range which does
114 // not wrap around the address space.
115 // 5. If `ptr`'s referent is not zero sized, then `A`, by invariant on
116 // `&'a T`, is guaranteed to live for at least `'a`.
117 unsafe { Self::new(ptr) }
118 }
119
120 /// Constructs a `PtrInner` from a mutable reference.
121 #[inline]
122 pub(crate) fn from_mut(ptr: &'a mut T) -> Self {
123 let ptr = NonNull::from(ptr);
124 // SAFETY:
125 // 0. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on
126 // `&'a mut T`, is derived from some valid Rust allocation, `A`.
127 // 1. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on
128 // `&'a mut T`, has valid provenance for `A`.
129 // 2. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on
130 // `&'a mut T`, addresses a byte range which is entirely contained in
131 // `A`.
132 // 3. `ptr`, by invariant on `&'a mut T`, addresses a byte range whose
133 // length fits in an `isize`.
134 // 4. `ptr`, by invariant on `&'a mut T`, addresses a byte range which
135 // does not wrap around the address space.
136 // 5. If `ptr`'s referent is not zero sized, then `A`, by invariant on
137 // `&'a mut T`, is guaranteed to live for at least `'a`.
138 unsafe { Self::new(ptr) }
139 }
140}
141
142#[allow(clippy::needless_lifetimes)]
143impl<'a, T> PtrInner<'a, [T]> {
144 /// Creates a pointer which addresses the given `range` of self.
145 ///
146 /// # Safety
147 ///
148 /// `range` is a valid range (`start <= end`) and `end <= self.len()`.
149 pub(crate) unsafe fn slice_unchecked(self, range: Range<usize>) -> Self {
150 let base = self.as_non_null().cast::<T>().as_ptr();
151
152 // SAFETY: The caller promises that `start <= end <= self.len()`. By
153 // invariant, if `self`'s referent is not zero-sized, then `self` refers
154 // to a byte range which is contained within a single allocation, which
155 // is no more than `isize::MAX` bytes long, and which does not wrap
156 // around the address space. Thus, this pointer arithmetic remains
157 // in-bounds of the same allocation, and does not wrap around the
158 // address space. The offset (in bytes) does not overflow `isize`.
159 //
160 // If `self`'s referent is zero-sized, then these conditions are
161 // trivially satisfied.
162 let base = unsafe { base.add(range.start) };
163
164 // SAFETY: The caller promises that `start <= end`, and so this will not
165 // underflow.
166 #[allow(unstable_name_collisions, clippy::incompatible_msrv)]
167 let len = unsafe { range.end.unchecked_sub(range.start) };
168
169 let ptr = core::ptr::slice_from_raw_parts_mut(base, len);
170
171 // SAFETY: By invariant, `self`'s address is non-null and its range does
172 // not wrap around the address space. Since, by the preceding lemma,
173 // `ptr` addresses a range within that addressed by `self`, `ptr` is
174 // non-null.
175 let ptr = unsafe { NonNull::new_unchecked(ptr) };
176
177 // SAFETY:
178 //
179 // Lemma 0: `ptr` addresses a subset of the bytes addressed by `self`,
180 // and has the same provenance. Proof: The caller guarantees
181 // that `start <= end <= self.len()`. Thus, `base` is in-bounds of
182 // `self`, and `base + (end - start)` is also in-bounds of self.
183 // Finally, `ptr` is constructed using provenance-preserving
184 // operations.
185 //
186 // 0. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
187 // zero sized, then `ptr` is derived from some valid Rust allocation,
188 // `A`.
189 // 1. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
190 // zero sized, then `ptr` has valid provenance for `A`.
191 // 2. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
192 // zero sized, then `ptr` addresses a byte range which is entirely
193 // contained in `A`.
194 // 3. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte
195 // range whose length fits in an `isize`.
196 // 4. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte
197 // range which does not wrap around the address space.
198 // 5. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
199 // zero sized, then `A` is guaranteed to live for at least `'a`.
200 unsafe { PtrInner::new(ptr) }
201 }
202
203 /// Splits the slice in two.
204 ///
205 /// # Safety
206 ///
207 /// The caller promises that `l_len <= self.len()`.
208 ///
209 /// Given `let (left, right) = ptr.split_at(l_len)`, it is guaranteed
210 /// that `left` and `right` are contiguous and non-overlapping.
211 pub(crate) unsafe fn split_at(self, l_len: usize) -> (Self, Self) {
212 // SAFETY: The caller promises that `l_len <= self.len()`.
213 // Trivially, `0 <= l_len`.
214 let left = unsafe { self.slice_unchecked(0..l_len) };
215
216 // SAFETY: The caller promises that `l_len <= self.len() =
217 // slf.len()`. Trivially, `slf.len() <= slf.len()`.
218 let right = unsafe { self.slice_unchecked(l_len..self.len()) };
219
220 // SAFETY: `left` and `right` are non-overlapping. Proof: `left` is
221 // constructed from `slf` with `l_len` as its (exclusive) upper
222 // bound, while `right` is constructed from `slf` with `l_len` as
223 // its (inclusive) lower bound. Thus, no index is a member of both
224 // ranges.
225 (left, right)
226 }
227
228 /// Iteratively projects the elements `PtrInner<T>` from `PtrInner<[T]>`.
229 pub(crate) fn iter(&self) -> impl Iterator<Item = PtrInner<'a, T>> {
230 // TODO(#429): Once `NonNull::cast` documents that it preserves
231 // provenance, cite those docs.
232 let base = self.as_non_null().cast::<T>().as_ptr();
233 (0..self.len()).map(move |i| {
234 // TODO(https://github.com/rust-lang/rust/issues/74265): Use
235 // `NonNull::get_unchecked_mut`.
236
237 // SAFETY: If the following conditions are not satisfied
238 // `pointer::cast` may induce Undefined Behavior [1]:
239 //
240 // > - The computed offset, `count * size_of::<T>()` bytes, must not
241 // > overflow `isize``.
242 // > - If the computed offset is non-zero, then `self` must be
243 // > derived from a pointer to some allocated object, and the
244 // > entire memory range between `self` and the result must be in
245 // > bounds of that allocated object. In particular, this range
246 // > must not “wrap around” the edge of the address space.
247 //
248 // [1] https://doc.rust-lang.org/std/primitive.pointer.html#method.add
249 //
250 // We satisfy both of these conditions here:
251 // - By invariant on `Ptr`, `self` addresses a byte range whose
252 // length fits in an `isize`. Since `elem` is contained in `self`,
253 // the computed offset of `elem` must fit within `isize.`
254 // - If the computed offset is non-zero, then this means that the
255 // referent is not zero-sized. In this case, `base` points to an
256 // allocated object (by invariant on `self`). Thus:
257 // - By contract, `self.len()` accurately reflects the number of
258 // elements in the slice. `i` is in bounds of `c.len()` by
259 // construction, and so the result of this addition cannot
260 // overflow past the end of the allocation referred to by `c`.
261 // - By invariant on `Ptr`, `self` addresses a byte range which
262 // does not wrap around the address space. Since `elem` is
263 // contained in `self`, the computed offset of `elem` must wrap
264 // around the address space.
265 //
266 // TODO(#429): Once `pointer::add` documents that it preserves
267 // provenance, cite those docs.
268 let elem = unsafe { base.add(i) };
269
270 // SAFETY:
271 // - `elem` must not be null. `base` is constructed from a
272 // `NonNull` pointer, and the addition that produces `elem` must
273 // not overflow or wrap around, so `elem >= base > 0`.
274 //
275 // TODO(#429): Once `NonNull::new_unchecked` documents that it
276 // preserves provenance, cite those docs.
277 let elem = unsafe { NonNull::new_unchecked(elem) };
278
279 // SAFETY: The safety invariants of `Ptr::new` (see definition) are
280 // satisfied:
281 // 0. If `elem`'s referent is not zero sized, then `elem` is derived
282 // from a valid Rust allocation, because `self` is derived from a
283 // valid Rust allocation, by invariant on `Ptr`.
284 // 1. If `elem`'s referent is not zero sized, then `elem` has valid
285 // provenance for `self`, because it derived from `self` using a
286 // series of provenance-preserving operations.
287 // 2. If `elem`'s referent is not zero sized, then `elem` is
288 // entirely contained in the allocation of `self` (see above).
289 // 3. `elem` addresses a byte range whose length fits in an `isize`
290 // (see above).
291 // 4. `elem` addresses a byte range which does not wrap around the
292 // address space (see above).
293 // 5. If `elem`'s referent is not zero sized, then the allocation of
294 // `elem` is guaranteed to live for at least `'a`, because `elem`
295 // is entirely contained in `self`, which lives for at least `'a`
296 // by invariant on `Ptr`.
297 unsafe { PtrInner::new(elem) }
298 })
299 }
300
301 /// The number of slice elements in the object referenced by `self`.
302 ///
303 /// # Safety
304 ///
305 /// Unsafe code my rely on `len` satisfying the above contract.
306 pub(crate) fn len(&self) -> usize {
307 self.trailing_slice_len()
308 }
309}
310
311#[allow(clippy::needless_lifetimes)]
312impl<'a, T> PtrInner<'a, T>
313where
314 T: ?Sized + KnownLayout<PointerMetadata = usize>,
315{
316 /// The number of trailing slice elements in the object referenced by
317 /// `self`.
318 ///
319 /// # Safety
320 ///
321 /// Unsafe code my rely on `trailing_slice_len` satisfying the above
322 /// contract.
323 pub(super) fn trailing_slice_len(&self) -> usize {
324 T::pointer_to_metadata(self.as_non_null().as_ptr())
325 }
326}
327
328impl<'a, T, const N: usize> PtrInner<'a, [T; N]> {
329 /// Casts this pointer-to-array into a slice.
330 ///
331 /// # Safety
332 ///
333 /// Callers may assume that the returned `PtrInner` references the same
334 /// address and length as `self`.
335 #[allow(clippy::wrong_self_convention)]
336 pub(crate) fn as_slice(self) -> PtrInner<'a, [T]> {
337 let start = self.as_non_null().cast::<T>().as_ptr();
338 let slice = core::ptr::slice_from_raw_parts_mut(start, N);
339 // SAFETY: `slice` is not null, because it is derived from `start`
340 // which is non-null.
341 let slice = unsafe { NonNull::new_unchecked(slice) };
342 // SAFETY: Lemma: In the following safety arguments, note that `slice`
343 // is derived from `self` in two steps: first, by casting `self: [T; N]`
344 // to `start: T`, then by constructing a pointer to a slice starting at
345 // `start` of length `N`. As a result, `slice` references exactly the
346 // same allocation as `self`, if any.
347 //
348 // 0. By the above lemma, if `slice`'s referent is not zero sized, then
349 // `slice` is derived from the same allocation as `self`, which, by
350 // invariant on `Ptr`, is valid.
351 // 1. By the above lemma, if `slice`'s referent is not zero sized, then
352 // , `slice` has valid provenance for `A`, since it is derived from
353 // the pointer `self`, which, by invariant on `Ptr`, has valid
354 // provenance for `A`.
355 // 2. By the above lemma, if `slice`'s referent is not zero sized, then
356 // `slice` addresses a byte range which is entirely contained in `A`,
357 // because it references exactly the same byte range as `self`,
358 // which, by invariant on `Ptr`, is entirely contained in `A`.
359 // 3. By the above lemma, `slice` addresses a byte range whose length
360 // fits in an `isize`, since it addresses exactly the same byte range
361 // as `self`, which, by invariant on `Ptr`, has a length that fits in
362 // an `isize`.
363 // 4. By the above lemma, `slice` addresses a byte range which does not
364 // wrap around the address space, since it addresses exactly the same
365 // byte range as `self`, which, by invariant on `Ptr`, does not wrap
366 // around the address space.
367 // 5. By the above lemma, if `slice`'s referent is not zero sized, then
368 // `A` is guaranteed to live for at least `'a`, because it is derived
369 // from the same allocation as `self`, which, by invariant on `Ptr`,
370 // lives for at least `'a`.
371 unsafe { PtrInner::new(slice) }
372 }
373}
374
375impl<'a> PtrInner<'a, [u8]> {
376 /// Attempts to cast `self` to a `U` using the given cast type.
377 ///
378 /// If `U` is a slice DST and pointer metadata (`meta`) is provided, then
379 /// the cast will only succeed if it would produce an object with the given
380 /// metadata.
381 ///
382 /// Returns `None` if the resulting `U` would be invalidly-aligned, if no
383 /// `U` can fit in `self`, or if the provided pointer metadata describes an
384 /// invalid instance of `U`. On success, returns a pointer to the
385 /// largest-possible `U` which fits in `self`.
386 ///
387 /// # Safety
388 ///
389 /// The caller may assume that this implementation is correct, and may rely
390 /// on that assumption for the soundness of their code. In particular, the
391 /// caller may assume that, if `try_cast_into` returns `Some((ptr,
392 /// remainder))`, then `ptr` and `remainder` refer to non-overlapping byte
393 /// ranges within `self`, and that `ptr` and `remainder` entirely cover
394 /// `self`. Finally:
395 /// - If this is a prefix cast, `ptr` has the same address as `self`.
396 /// - If this is a suffix cast, `remainder` has the same address as `self`.
397 pub(crate) fn try_cast_into<U>(
398 self,
399 cast_type: CastType,
400 meta: Option<U::PointerMetadata>,
401 ) -> Result<(PtrInner<'a, U>, PtrInner<'a, [u8]>), CastError<Self, U>>
402 where
403 U: 'a + ?Sized + KnownLayout,
404 {
405 let layout = match meta {
406 None => U::LAYOUT,
407 // This can return `None` if the metadata describes an object
408 // which can't fit in an `isize`.
409 Some(meta) => {
410 let size = match meta.size_for_metadata(U::LAYOUT) {
411 Some(size) => size,
412 None => return Err(CastError::Size(SizeError::new(self))),
413 };
414 DstLayout { align: U::LAYOUT.align, size_info: crate::SizeInfo::Sized { size } }
415 }
416 };
417 // PANICS: By invariant, the byte range addressed by
418 // `self.as_non_null()` does not wrap around the address space. This
419 // implies that the sum of the address (represented as a `usize`) and
420 // length do not overflow `usize`, as required by
421 // `validate_cast_and_convert_metadata`. Thus, this call to
422 // `validate_cast_and_convert_metadata` will only panic if `U` is a DST
423 // whose trailing slice element is zero-sized.
424 let maybe_metadata = layout.validate_cast_and_convert_metadata(
425 AsAddress::addr(self.as_non_null().as_ptr()),
426 self.len(),
427 cast_type,
428 );
429
430 let (elems, split_at) = match maybe_metadata {
431 Ok((elems, split_at)) => (elems, split_at),
432 Err(MetadataCastError::Alignment) => {
433 // SAFETY: Since `validate_cast_and_convert_metadata` returned
434 // an alignment error, `U` must have an alignment requirement
435 // greater than one.
436 let err = unsafe { AlignmentError::<_, U>::new_unchecked(self) };
437 return Err(CastError::Alignment(err));
438 }
439 Err(MetadataCastError::Size) => return Err(CastError::Size(SizeError::new(self))),
440 };
441
442 // SAFETY: `validate_cast_and_convert_metadata` promises to return
443 // `split_at <= self.len()`.
444 let (l_slice, r_slice) = unsafe { self.split_at(split_at) };
445
446 let (target, remainder) = match cast_type {
447 CastType::Prefix => (l_slice, r_slice),
448 CastType::Suffix => (r_slice, l_slice),
449 };
450
451 let base = target.as_non_null().cast::<u8>();
452
453 let elems = <U as KnownLayout>::PointerMetadata::from_elem_count(elems);
454 // For a slice DST type, if `meta` is `Some(elems)`, then we synthesize
455 // `layout` to describe a sized type whose size is equal to the size of
456 // the instance that we are asked to cast. For sized types,
457 // `validate_cast_and_convert_metadata` returns `elems == 0`. Thus, in
458 // this case, we need to use the `elems` passed by the caller, not the
459 // one returned by `validate_cast_and_convert_metadata`.
460 let elems = meta.unwrap_or(elems);
461
462 let ptr = U::raw_from_ptr_len(base, elems);
463
464 // SAFETY:
465 // 0. By invariant, if `target`'s referent is not zero sized, then
466 // `target` is derived from some valid Rust allocation, `A`. By
467 // contract on `cast`, `ptr` is derived from `self`, and thus from
468 // the same valid Rust allocation, `A`.
469 // 1. By invariant, if `target`'s referent is not zero sized, then
470 // `target` has provenance valid for some Rust allocation, `A`.
471 // Because `ptr` is derived from `target` via provenance-preserving
472 // operations, `ptr` will also have provenance valid for `A`.
473 // - `validate_cast_and_convert_metadata` promises that the object
474 // described by `elems` and `split_at` lives at a byte range which is
475 // a subset of the input byte range. Thus:
476 // 2. Since, by invariant, if `target`'s referent is not zero sized,
477 // then `target` addresses a byte range which is entirely
478 // contained in `A`, so does `ptr`.
479 // 3. Since, by invariant, `target` addresses a byte range whose
480 // length fits in an `isize`, so does `ptr`.
481 // 4. Since, by invariant, `target` addresses a byte range which does
482 // not wrap around the address space, so does `ptr`.
483 // 5. Since, by invariant, if `target`'s referent is not zero sized,
484 // then `target` refers to an allocation which is guaranteed to
485 // live for at least `'a`, so does `ptr`.
486 Ok((unsafe { PtrInner::new(ptr) }, remainder))
487 }
488}
489
490#[allow(clippy::needless_lifetimes)]
491impl<'a, T> PtrInner<'a, T> {
492 /// Performs an unaligned read of `self`'s referent.
493 ///
494 /// # Safety
495 ///
496 /// `self` must point to a properly initialized value of type `T`, and
497 /// reading a copy of `T` must not violate `T`'s safety invariants.
498 ///
499 /// `self`'s referent must not be concurrently modified during this call.
500 pub(crate) unsafe fn read_unaligned(self) -> T {
501 let raw = self.as_non_null().as_ptr();
502 // SAFETY: The caller promises that `self` points to a bit-valid `T` and
503 // that reading a copy of it won't violate `T`'s safety invariants. The
504 // caller promises that `self`'s referent won't be concurrently modified
505 // during this operation.
506 //
507 // `raw` is valid for reads:
508 // - `self.as_non_null()` returns a `NonNull`, which is guaranteed to be
509 // non-null.
510 // - By invariant on `PtrInner`, `raw` is is either zero-sized or:
511 // - ...is within bounds of a single allocated object which lives for
512 // at least `'a`.
513 // - ...has valid provenance for that object.
514 unsafe { core::ptr::read_unaligned(raw) }
515 }
516}
517
518#[cfg(test)]
519mod tests {
520 use super::*;
521
522 #[test]
523 fn test_split_at() {
524 const N: usize = 16;
525 let arr = [1; N];
526 let ptr = PtrInner::from_ref(&arr).as_slice();
527 for i in 0..=N {
528 assert_eq!(ptr.len(), N);
529 // SAFETY: `i` is in bounds by construction.
530 let (l, r) = unsafe { ptr.split_at(i) };
531 // SAFETY: Points to a valid value by construction.
532 let l_sum: usize = l.iter().map(|ptr| unsafe { ptr.read_unaligned() }).sum();
533 // SAFETY: Points to a valid value by construction.
534 let r_sum: usize = r.iter().map(|ptr| unsafe { ptr.read_unaligned() }).sum();
535 assert_eq!(l_sum, i);
536 assert_eq!(r_sum, N - i);
537 assert_eq!(l_sum + r_sum, N);
538 }
539 }
540}