entwine 0.1.0

Generic slice-like interface for operating on multiple slices at the same time
Documentation
//! Low-level traits and operations
//!
//! This module contains low-level traits that are generally `unsafe` to implement,
//! upon which the safe [`Entwine`](super::Entwine) interface is built. Users generally
//! do not need to import or implement these traits directly.

#![allow(clippy::missing_safety_doc)]

use core::hash::Hash;
use core::ops::RangeBounds;

use crate::{RefMutT, RefT};

/// Basic slice operations.
pub unsafe trait EntwineCore {
    /// Constructor of types related to elements.
    type ElementCtor: ElementCtor;

    /// Mutable view type into a range.
    type RangeMut<'a>: EntwineCore<ElementCtor = Self::ElementCtor>
    where
        Self: 'a;

    /// Returns the number of elements in the slice.
    ///
    /// # Examples
    ///
    /// ```
    /// let a = [1, 2, 3];
    /// assert_eq!(a.len(), 3);
    /// ```
    fn len(&self) -> usize;

    /// Returns `true` if the slice has a length of 0.
    ///
    /// # Examples
    ///
    /// ```
    /// let a = [1, 2, 3];
    /// assert!(!a.is_empty());
    /// ```
    fn is_empty(&self) -> bool {
        self.len() == 0
    }

    fn range_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<Self::RangeMut<'_>>;

    /// Splits the slice into a slice of `N`-element arrays,
    /// starting at the beginning of the slice,
    /// and a remainder slice with length strictly less than `N`.
    ///
    /// # Panics
    ///
    /// Panics if `N` is 0. This check will most probably get changed to a compile time
    /// error before this method gets stabilized.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(slice_as_chunks)]
    /// let v = &mut [0, 0, 0, 0, 0];
    /// let mut count = 1;
    ///
    /// let (chunks, remainder) = v.as_chunks_mut();
    /// remainder[0] = 9;
    /// for chunk in chunks {
    ///     *chunk = [count; 2];
    ///     count += 1;
    /// }
    /// assert_eq!(v, &[1, 1, 2, 2, 9]);
    /// ```
    fn split_at_mut(&mut self, mid: usize) -> (Self::RangeMut<'_>, Self::RangeMut<'_>);

    /// Reverses the order of elements in the slice, in place.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut v = [1, 2, 3];
    /// v.reverse();
    /// assert!(v == [3, 2, 1]);
    /// ```
    fn reverse(&mut self);

    /// Returns a reference to an element, without doing bounds checking.
    ///
    /// For a safe alternative see [`Entwine::get`].
    ///
    /// # Safety
    ///
    /// Calling this method with an out-of-bounds index is *[undefined behavior]*
    /// even if the resulting reference is not used.
    ///
    /// [`Entwine::get`]: crate::Entwine::get
    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
    ///
    /// # Examples
    ///
    /// ```
    /// let x = &[1, 2, 4];
    ///
    /// unsafe {
    ///     assert_eq!(x.get_unchecked(1), &2);
    /// }
    /// ```
    unsafe fn get_unchecked(&self, idx: usize) -> RefT<'_, Self>;

    /// Returns a mutable reference to an element, without doing bounds checking.
    ///
    /// For a safe alternative see [`Entwine::get_mut`].
    ///
    /// # Safety
    ///
    /// Calling this method with an out-of-bounds index is *[undefined behavior]*
    /// even if the resulting reference is not used.
    ///
    /// [`Entwine::get_mut`]: crate::Entwine::get_mut
    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
    ///
    /// # Examples
    ///
    /// ```
    /// let x = &mut [1, 2, 4];
    ///
    /// unsafe {
    ///     let elem = x.get_unchecked_mut(1);
    ///     *elem = 13;
    /// }
    /// assert_eq!(x, &[1, 13, 4]);
    /// ```
    unsafe fn get_unchecked_mut(&mut self, idx: usize) -> RefMutT<'_, Self>;
}

unsafe impl<'e, E> EntwineCore for &'e mut E
where
    E: EntwineCore + ?Sized,
{
    type ElementCtor = E::ElementCtor;

    type RangeMut<'a>
    where
        Self: 'a,
    = E::RangeMut<'a>;

    fn len(&self) -> usize {
        E::len(self)
    }

    fn range_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<Self::RangeMut<'_>> {
        E::range_mut(self, range)
    }

    fn split_at_mut(&mut self, mid: usize) -> (Self::RangeMut<'_>, Self::RangeMut<'_>) {
        E::split_at_mut(self, mid)
    }

    fn reverse(&mut self) {
        E::reverse(self)
    }

    unsafe fn get_unchecked(&self, idx: usize) -> RefT<'_, Self> {
        E::get_unchecked(self, idx)
    }

    unsafe fn get_unchecked_mut(&mut self, idx: usize) -> RefMutT<'_, Self> {
        E::get_unchecked_mut(self, idx)
    }

    fn is_empty(&self) -> bool {
        E::is_empty(self)
    }
}

/// Constructor of types related to elements.
pub trait ElementCtor: Sized {
    type Value: Value<Self>;

    type Ref<'a>: Ref<'a, Self>
    where
        Self: 'a;

    type RefMut<'a>: RefMut<'a, Self>
    where
        Self: 'a;

    type Ptr: Ptr<Self>;
    type PtrMut: PtrMut<Self>;
}

/// Owned element values, like `T`.
pub unsafe trait Value<T: ElementCtor> {
    fn is_zero_sized() -> bool;
    fn as_ref(&self) -> T::Ref<'_>;
    fn as_mut(&mut self) -> T::RefMut<'_>;
}

/// References to elements, like `&T`.
pub unsafe trait Ref<'a, T: ElementCtor>: Clone {
    fn reborrow<'r>(self) -> T::Ref<'r>
    where
        'a: 'r;
    fn to_ptr(&self) -> T::Ptr;
}

/// Mutable references to elements, like `&mut T`.
pub unsafe trait RefMut<'a, T: ElementCtor> {
    fn reborrow_mut<'r>(self) -> T::RefMut<'r>
    where
        'a: 'r;
    fn to_ref(&self) -> T::Ref<'_>;
    fn to_mut_ptr(&mut self) -> T::PtrMut;
}

/// Raw pointers to elements, like `*const T`.
pub unsafe trait Ptr<T: ElementCtor>: Eq + Hash + Clone {
    unsafe fn deref<'r>(&self) -> T::Ref<'r>;

    fn null() -> Self;

    unsafe fn add(&self, count: usize) -> Self;
    unsafe fn offset(&self, count: isize) -> Self;

    // Returns the number of elements between pointers `l` (inclusive) and `r` (exclusive).
    fn width(l: &Self, r: &Self) -> usize;

    unsafe fn read(src: &Self) -> T::Value;
}

/// Raw mutable pointers to elements, like `*mut T`.
pub unsafe trait PtrMut<T: ElementCtor>: Eq + Hash + Clone {
    unsafe fn deref_mut<'r>(&self) -> T::RefMut<'r>;
    unsafe fn to_const(&self) -> T::Ptr;

    fn null_mut() -> Self;

    unsafe fn add(&self, count: usize) -> Self;
    unsafe fn offset(&self, count: isize) -> Self;

    // Returns the number of elements between pointers `l` (inclusive) and `r` (exclusive).
    fn width(l: &Self, r: &Self) -> usize;

    unsafe fn write(dst: &Self, src: T::Value);
    unsafe fn copy_nonoverlapping(src: &T::Ptr, dst: &Self, n: usize);
    unsafe fn swap(a: &Self, b: &Self);
}