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) }
  }
}