1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
use core::{ fmt::Debug, marker::PhantomData, ops::{Deref, DerefMut}, slice, }; use super::StableLayout; // General Safety Note: The soundness of the `UniqueSlice` type is centered // around the fact that the fields are all private, and so *safe rust* must // construct values of the type from an existing valid slice. However, because // the type is `repr(C)` it can of course be constructed with unsafe rust, or // even by foreign code. It is the responsibility of _the other code_ to ensure // that the actual fields are valid for being turned into a slice. /// A struct for **unique** slices with a stable layout. /// /// This is a `repr(C)` variant of `&mut [T]`. If you want a variant of `&[T]` /// then you should use [`SharedSlice`](crate::SharedSlice) instead. /// /// Rationale for using this type is given in the crate level docs. /// /// ## Unsafety /// /// Because this type is primarily intended to help _unsafe_ Rust we should /// discuss the precise guarantees offered: /// * **Validity Invariants** /// * The data layout is a `*mut T` and then a `usize`. /// * **Soundness Invariants** /// * The `*mut T` must point to the start of a valid `&mut [T]`. /// * The `usize` must be the correct length of that valid `&mut [T]`. /// * For as long as the `UniqueSlice` exists the memory in question has a /// unique borrow over it (tracked via `PhantomData`). /// /// When you use this type with the C ABI, remember that the C ABI **does not** /// support generic types or `repr(Rust)` types! /// /// If you select a particular type for `T` that is compatible with the C ABI, /// such as `u8` or `i32`, then that particular monomorphization of /// `UniqueSlice` will be C ABI compatible as well. For example, if your /// element type were `u8` then it would be equivalent layout to the following C /// declaration: /// /// ```c /// #include <stdint.h> /// // Identical layout to `UniqueSlice<'a, u8>` /// typedef struct { /// uint8_t *ptr; /// uintptr_t len; /// } UniqueSlice_u8; /// ``` #[repr(C)] pub struct UniqueSlice<'a, T> where T: StableLayout, { ptr: *mut T, len: usize, life: PhantomData<&'a mut [T]>, } unsafe impl<'a, T: StableLayout> StableLayout for UniqueSlice<'a, T> {} impl<'a, T: Debug> Debug for UniqueSlice<'a, T> where T: StableLayout, { /// Debug prints as a slice would. fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { Debug::fmt(self.deref(), f) } } impl<'a, T> Default for UniqueSlice<'a, T> where T: StableLayout, { /// Defaults to an empty slice. /// /// ```rust /// # use chromium::*; /// let unique: UniqueSlice<'static, i32> = UniqueSlice::default(); /// assert_eq!(unique.len(), 0); /// ``` #[inline(always)] fn default() -> Self { let life = PhantomData; let len = 0; let ptr = core::ptr::NonNull::dangling().as_ptr(); Self { ptr, len, life } } } impl<'a, T> Deref for UniqueSlice<'a, T> where T: StableLayout, { type Target = [T]; #[inline(always)] fn deref(&self) -> &[T] { // Safety: See note at the top of the module. unsafe { slice::from_raw_parts(self.ptr, self.len) } } } impl<'a, T> DerefMut for UniqueSlice<'a, T> where T: StableLayout, { #[inline(always)] fn deref_mut(&mut self) -> &mut [T] { // Safety: See note at the top of the module. unsafe { slice::from_raw_parts_mut(self.ptr, self.len) } } } impl<'a, T> From<&'a mut [T]> for UniqueSlice<'a, T> where T: StableLayout, { #[inline(always)] fn from(sli: &'a mut [T]) -> Self { let life = PhantomData; let len = sli.len(); let ptr = sli.as_mut_ptr(); Self { ptr, len, life } } } impl<'a, T> From<UniqueSlice<'a, T>> for &'a mut [T] where T: StableLayout, { #[inline(always)] fn from(unique: UniqueSlice<'a, T>) -> Self { // Safety: See note at the top of the module. unsafe { slice::from_raw_parts_mut(unique.ptr, unique.len) } } }