shared_bytes 0.1.0-beta.4

Owned string and byte slices.
Documentation
use super::length::Length;
use std::ops::Range;

pub(crate) trait Slice<Output: ?Sized>: TryIndexRange<Output> + Length {}

impl<S, O> Slice<O> for S
where
    S: TryIndexRange<O> + Length + ?Sized,
    O: ?Sized,
{
}

pub(crate) trait TryIndexRange<Output: ?Sized> {
    fn try_index(&self, index: Range<usize>) -> Option<&Output>;

    fn index(&self, index: Range<usize>) -> &Output {
        self.try_index(index.clone())
            .unwrap_or_else(|| panic!("index {index:?} is invalid"))
    }

    /// Returns a reference to a subslice without any checks.
    ///
    /// # Safety
    /// Safe, if calling try_index instead, would return [`Some`].
    ///
    /// See [`str::get_unchecked`] and [`slice::get_unchecked`].
    unsafe fn index_unchecked(&self, index: Range<usize>) -> &Output;
}

impl<T> TryIndexRange<[T]> for [T] {
    fn try_index(&self, index: Range<usize>) -> Option<&[T]> {
        self.get(index)
    }

    fn index(&self, index: Range<usize>) -> &[T] {
        &self[index]
    }

    unsafe fn index_unchecked(&self, index: Range<usize>) -> &[T] {
        // SAFETY: requirements match Self::try_index
        self.get_unchecked(index)
    }
}

impl TryIndexRange<str> for [u8] {
    fn try_index(&self, index: Range<usize>) -> Option<&str> {
        std::str::from_utf8(self.get(index)?).ok()
    }

    unsafe fn index_unchecked(&self, index: Range<usize>) -> &str {
        // SAFETY: requirements match Self::try_index
        std::str::from_utf8_unchecked(self.get_unchecked(index))
    }
}

impl TryIndexRange<[u8]> for str {
    fn try_index(&self, index: Range<usize>) -> Option<&[u8]> {
        self.as_bytes().get(index)
    }

    fn index(&self, index: Range<usize>) -> &[u8] {
        &self.as_bytes()[index]
    }

    unsafe fn index_unchecked(&self, index: Range<usize>) -> &[u8] {
        // SAFETY: requirements match Self::try_index
        self.as_bytes().get_unchecked(index)
    }
}

impl TryIndexRange<str> for str {
    fn try_index(&self, index: Range<usize>) -> Option<&str> {
        self.get(index)
    }

    fn index(&self, index: Range<usize>) -> &str {
        &self[index]
    }

    unsafe fn index_unchecked(&self, index: Range<usize>) -> &str {
        // SAFETY: requirements match Self::try_index
        self.get_unchecked(index)
    }
}