use core::ops::{
Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
};
use crate::{ImplBound, Ref};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ChunksMutNotSupported;
impl core::fmt::Display for ChunksMutNotSupported {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "try_chunks_mut is not supported on subslices")
}
}
impl core::error::Error for ChunksMutNotSupported {}
#[inline(always)]
fn assert_index(index: usize, len: usize) {
assert!(
index < len,
"index out of bounds: the len is {len} but the index is {index}",
);
}
#[inline(always)]
fn assert_range(range: &impl ComposeRange, len: usize) {
assert!(
range.is_valid(len),
"range {range:?} out of range for slice of length {len}",
);
}
pub trait SliceByValue {
type Value;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn index_value(&self, index: usize) -> Self::Value {
assert_index(index, self.len());
unsafe { self.get_value_unchecked(index) }
}
unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value;
fn get_value(&self, index: usize) -> Option<Self::Value> {
if index < self.len() {
let value = unsafe { self.get_value_unchecked(index) };
Some(value)
} else {
None
}
}
}
impl<S: SliceByValue + ?Sized> SliceByValue for &S {
type Value = S::Value;
#[inline]
fn len(&self) -> usize {
(**self).len()
}
fn get_value(&self, index: usize) -> Option<Self::Value> {
(**self).get_value(index)
}
fn index_value(&self, index: usize) -> Self::Value {
(**self).index_value(index)
}
unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
unsafe { (**self).get_value_unchecked(index) }
}
}
impl<S: SliceByValue + ?Sized> SliceByValue for &mut S {
type Value = S::Value;
#[inline]
fn len(&self) -> usize {
(**self).len()
}
fn get_value(&self, index: usize) -> Option<Self::Value> {
(**self).get_value(index)
}
fn index_value(&self, index: usize) -> Self::Value {
(**self).index_value(index)
}
unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
unsafe { (**self).get_value_unchecked(index) }
}
}
pub trait SliceByValueMut: SliceByValue {
unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value);
fn set_value(&mut self, index: usize, value: Self::Value) {
assert_index(index, self.len());
unsafe {
self.set_value_unchecked(index, value);
}
}
unsafe fn replace_value_unchecked(&mut self, index: usize, value: Self::Value) -> Self::Value {
let old_value = unsafe { self.get_value_unchecked(index) };
unsafe { self.set_value_unchecked(index, value) };
old_value
}
fn replace_value(&mut self, index: usize, value: Self::Value) -> Self::Value {
assert_index(index, self.len());
unsafe { self.replace_value_unchecked(index, value) }
}
fn copy(&self, from: usize, dst: &mut Self, to: usize, len: usize) {
let len = Ord::min(
Ord::min(len, dst.len().saturating_sub(to)),
self.len().saturating_sub(from),
);
for i in 0..len {
dst.set_value(to + i, self.index_value(from + i));
}
}
unsafe fn apply_in_place_unchecked<F>(&mut self, mut f: F)
where
F: FnMut(Self::Value) -> Self::Value,
{
for idx in 0..self.len() {
let value = unsafe { self.get_value_unchecked(idx) };
let new_value = f(value);
unsafe { self.set_value_unchecked(idx, new_value) };
}
}
fn apply_in_place<F>(&mut self, mut f: F)
where
F: FnMut(Self::Value) -> Self::Value,
{
for idx in 0..self.len() {
let value = unsafe { self.get_value_unchecked(idx) };
let new_value = f(value);
unsafe { self.set_value_unchecked(idx, new_value) };
}
}
type ChunksMut<'a>: Iterator<Item: SliceByValueMut<Value = Self::Value>>
where
Self: 'a;
type ChunksMutError: core::fmt::Debug;
fn try_chunks_mut(
&mut self,
chunk_size: usize,
) -> Result<Self::ChunksMut<'_>, Self::ChunksMutError>;
}
impl<S: SliceByValueMut + ?Sized> SliceByValueMut for &mut S {
fn set_value(&mut self, index: usize, value: Self::Value) {
(**self).set_value(index, value);
}
unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value) {
unsafe {
(**self).set_value_unchecked(index, value);
}
}
fn replace_value(&mut self, index: usize, value: Self::Value) -> Self::Value {
(**self).replace_value(index, value)
}
unsafe fn replace_value_unchecked(&mut self, index: usize, value: Self::Value) -> Self::Value {
unsafe { (**self).replace_value_unchecked(index, value) }
}
type ChunksMut<'a>
= S::ChunksMut<'a>
where
Self: 'a;
type ChunksMutError = S::ChunksMutError;
fn try_chunks_mut(
&mut self,
chunk_size: usize,
) -> Result<Self::ChunksMut<'_>, Self::ChunksMutError> {
(**self).try_chunks_mut(chunk_size)
}
}
pub trait ComposeRange: RangeBounds<usize> + core::fmt::Debug {
fn is_valid(&self, len: usize) -> bool;
fn compose(&self, base: Range<usize>) -> Range<usize>;
}
impl ComposeRange for Range<usize> {
fn is_valid(&self, len: usize) -> bool {
self.start <= len && self.end <= len && self.start <= self.end
}
fn compose(&self, base: Range<usize>) -> Range<usize> {
(base.start + self.start)..(base.start + self.end)
}
}
impl ComposeRange for RangeFrom<usize> {
fn is_valid(&self, len: usize) -> bool {
self.start <= len
}
fn compose(&self, base: Range<usize>) -> Range<usize> {
(base.start + self.start)..base.end
}
}
impl ComposeRange for RangeFull {
fn is_valid(&self, _len: usize) -> bool {
true
}
fn compose(&self, base: Range<usize>) -> Range<usize> {
base
}
}
impl ComposeRange for RangeInclusive<usize> {
fn is_valid(&self, len: usize) -> bool {
*self.start() < len && *self.end() < len && self.start() <= self.end()
}
fn compose(&self, base: Range<usize>) -> Range<usize> {
(base.start + self.start())..(base.start + self.end() + 1)
}
}
impl ComposeRange for RangeTo<usize> {
fn is_valid(&self, len: usize) -> bool {
self.end <= len
}
fn compose(&self, base: Range<usize>) -> Range<usize> {
base.start..(base.start + self.end)
}
}
impl ComposeRange for RangeToInclusive<usize> {
fn is_valid(&self, len: usize) -> bool {
self.end < len
}
fn compose(&self, base: Range<usize>) -> Range<usize> {
base.start..(base.start + self.end + 1)
}
}
pub trait SliceByValueSubsliceGat<'a, __Implicit: ImplBound = Ref<'a, Self>>: SliceByValue {
type Subslice: 'a + SliceByValue<Value = Self::Value> + SliceByValueSubslice;
}
#[allow(type_alias_bounds)] pub type Subslice<'a, T: SliceByValueSubsliceGat<'a>> =
<T as SliceByValueSubsliceGat<'a>>::Subslice;
impl<'a, T: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for &T {
type Subslice = T::Subslice;
}
impl<'a, T: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for &mut T {
type Subslice = T::Subslice;
}
pub trait SliceByValueSubsliceRange<R: ComposeRange>: for<'a> SliceByValueSubsliceGat<'a> {
fn index_subslice(&self, range: R) -> Subslice<'_, Self> {
assert_range(&range, self.len());
unsafe {
self.get_subslice_unchecked(range)
}
}
unsafe fn get_subslice_unchecked(&self, range: R) -> Subslice<'_, Self>;
fn get_subslice(&self, range: R) -> Option<Subslice<'_, Self>> {
if range.is_valid(self.len()) {
let subslice = unsafe { self.get_subslice_unchecked(range) };
Some(subslice)
} else {
None
}
}
}
impl<R: ComposeRange, S: SliceByValueSubsliceRange<R> + ?Sized> SliceByValueSubsliceRange<R>
for &S
{
fn get_subslice(&self, range: R) -> Option<Subslice<'_, Self>> {
(**self).get_subslice(range)
}
fn index_subslice(&self, range: R) -> Subslice<'_, Self> {
(**self).index_subslice(range)
}
unsafe fn get_subslice_unchecked(&self, range: R) -> Subslice<'_, Self> {
unsafe { (**self).get_subslice_unchecked(range) }
}
}
impl<R: ComposeRange, S: SliceByValueSubsliceRange<R> + ?Sized> SliceByValueSubsliceRange<R>
for &mut S
{
fn get_subslice(&self, range: R) -> Option<Subslice<'_, Self>> {
(**self).get_subslice(range)
}
fn index_subslice(&self, range: R) -> Subslice<'_, Self> {
(**self).index_subslice(range)
}
unsafe fn get_subslice_unchecked(&self, range: R) -> Subslice<'_, Self> {
unsafe { (**self).get_subslice_unchecked(range) }
}
}
pub trait SliceByValueSubsliceGatMut<'a, __Implicit: ImplBound = Ref<'a, Self>>:
SliceByValueMut
{
type SubsliceMut: 'a
+ SliceByValueMut<Value = Self::Value>
+ SliceByValueSubsliceGatMut<'a, SubsliceMut = Self::SubsliceMut> + SliceByValueSubsliceMut;
}
#[allow(type_alias_bounds)] pub type SubsliceMut<'a, T: SliceByValueSubsliceGatMut<'a>> =
<T as SliceByValueSubsliceGatMut<'a>>::SubsliceMut;
impl<'a, T: SliceByValueSubsliceGatMut<'a> + ?Sized> SliceByValueSubsliceGatMut<'a> for &mut T {
type SubsliceMut = T::SubsliceMut;
}
pub trait SliceByValueSubsliceRangeMut<R: ComposeRange>:
for<'a> SliceByValueSubsliceGatMut<'a>
{
fn index_subslice_mut(&mut self, range: R) -> SubsliceMut<'_, Self> {
assert_range(&range, self.len());
unsafe {
self.get_subslice_unchecked_mut(range)
}
}
unsafe fn get_subslice_unchecked_mut(&mut self, range: R) -> SubsliceMut<'_, Self>;
fn get_subslice_mut(&mut self, range: R) -> Option<SubsliceMut<'_, Self>> {
if range.is_valid(self.len()) {
let subslice_mut = unsafe { self.get_subslice_unchecked_mut(range) };
Some(subslice_mut)
} else {
None
}
}
}
impl<R: ComposeRange, S: SliceByValueSubsliceRangeMut<R> + ?Sized> SliceByValueSubsliceRangeMut<R>
for &mut S
{
fn get_subslice_mut(&mut self, range: R) -> Option<SubsliceMut<'_, Self>> {
(**self).get_subslice_mut(range)
}
fn index_subslice_mut(&mut self, range: R) -> SubsliceMut<'_, Self> {
(**self).index_subslice_mut(range)
}
unsafe fn get_subslice_unchecked_mut(&mut self, range: R) -> SubsliceMut<'_, Self> {
unsafe { (**self).get_subslice_unchecked_mut(range) }
}
}
pub trait SliceByValueSubslice:
SliceByValueSubsliceRange<Range<usize>>
+ SliceByValueSubsliceRange<RangeFrom<usize>>
+ SliceByValueSubsliceRange<RangeFull>
+ SliceByValueSubsliceRange<RangeInclusive<usize>>
+ SliceByValueSubsliceRange<RangeTo<usize>>
+ SliceByValueSubsliceRange<RangeToInclusive<usize>>
{
}
impl<U> SliceByValueSubslice for U
where
U: SliceByValueSubsliceRange<Range<usize>>,
U: SliceByValueSubsliceRange<RangeFrom<usize>>,
U: SliceByValueSubsliceRange<RangeFull>,
U: SliceByValueSubsliceRange<RangeInclusive<usize>>,
U: SliceByValueSubsliceRange<RangeTo<usize>>,
U: SliceByValueSubsliceRange<RangeToInclusive<usize>>,
{
}
pub trait SliceByValueSubsliceMut:
SliceByValueSubsliceRangeMut<Range<usize>>
+ SliceByValueSubsliceRangeMut<RangeFrom<usize>>
+ SliceByValueSubsliceRangeMut<RangeFull>
+ SliceByValueSubsliceRangeMut<RangeInclusive<usize>>
+ SliceByValueSubsliceRangeMut<RangeTo<usize>>
+ SliceByValueSubsliceRangeMut<RangeToInclusive<usize>>
{
}
impl<U> SliceByValueSubsliceMut for U
where
U: SliceByValueSubsliceRangeMut<Range<usize>>,
U: SliceByValueSubsliceRangeMut<RangeFrom<usize>>,
U: SliceByValueSubsliceRangeMut<RangeFull>,
U: SliceByValueSubsliceRangeMut<RangeInclusive<usize>>,
U: SliceByValueSubsliceRangeMut<RangeTo<usize>>,
U: SliceByValueSubsliceRangeMut<RangeToInclusive<usize>>,
{
}
#[cfg(feature = "alloc")]
mod alloc_impls {
use super::*;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
impl<S: SliceByValue + ?Sized> SliceByValue for Box<S> {
type Value = S::Value;
#[inline]
fn len(&self) -> usize {
(**self).len()
}
fn get_value(&self, index: usize) -> Option<Self::Value> {
(**self).get_value(index)
}
fn index_value(&self, index: usize) -> Self::Value {
(**self).index_value(index)
}
unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
unsafe { (**self).get_value_unchecked(index) }
}
}
impl<S: SliceByValueMut + ?Sized> SliceByValueMut for Box<S> {
fn set_value(&mut self, index: usize, value: Self::Value) {
(**self).set_value(index, value);
}
unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value) {
unsafe {
(**self).set_value_unchecked(index, value);
}
}
fn replace_value(&mut self, index: usize, value: Self::Value) -> Self::Value {
(**self).replace_value(index, value)
}
unsafe fn replace_value_unchecked(
&mut self,
index: usize,
value: Self::Value,
) -> Self::Value {
unsafe { (**self).replace_value_unchecked(index, value) }
}
type ChunksMut<'a>
= S::ChunksMut<'a>
where
Self: 'a;
type ChunksMutError = S::ChunksMutError;
fn try_chunks_mut(
&mut self,
chunk_size: usize,
) -> Result<Self::ChunksMut<'_>, Self::ChunksMutError> {
(**self).try_chunks_mut(chunk_size)
}
}
impl<'a, S: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for Box<S> {
type Subslice = S::Subslice;
}
impl<'a, S: SliceByValueSubsliceGatMut<'a> + ?Sized> SliceByValueSubsliceGatMut<'a> for Box<S> {
type SubsliceMut = S::SubsliceMut;
}
macro_rules! impl_range_alloc {
($range:ty) => {
impl<S: SliceByValueSubsliceRange<$range> + ?Sized> SliceByValueSubsliceRange<$range>
for Box<S>
{
#[inline]
fn get_subslice(&self, index: $range) -> Option<Subslice<'_, Self>> {
(**self).get_subslice(index)
}
#[inline]
fn index_subslice(&self, index: $range) -> Subslice<'_, Self> {
(**self).index_subslice(index)
}
#[inline]
unsafe fn get_subslice_unchecked(&self, index: $range) -> Subslice<'_, Self> {
unsafe { (**self).get_subslice_unchecked(index) }
}
}
impl<S: SliceByValueSubsliceRangeMut<$range> + ?Sized>
SliceByValueSubsliceRangeMut<$range> for Box<S>
{
#[inline]
fn get_subslice_mut(&mut self, index: $range) -> Option<SubsliceMut<'_, Self>> {
(**self).get_subslice_mut(index)
}
#[inline]
fn index_subslice_mut(&mut self, index: $range) -> SubsliceMut<'_, Self> {
(**self).index_subslice_mut(index)
}
#[inline]
unsafe fn get_subslice_unchecked_mut(
&mut self,
index: $range,
) -> SubsliceMut<'_, Self> {
unsafe { (**self).get_subslice_unchecked_mut(index) }
}
}
};
}
impl_range_alloc!(RangeFull);
impl_range_alloc!(RangeFrom<usize>);
impl_range_alloc!(RangeTo<usize>);
impl_range_alloc!(Range<usize>);
impl_range_alloc!(RangeInclusive<usize>);
impl_range_alloc!(RangeToInclusive<usize>);
}
#[cfg(feature = "std")]
mod std_impls {
use super::*;
use std::{rc::Rc, sync::Arc};
impl<S: SliceByValue + ?Sized> SliceByValue for Arc<S> {
type Value = S::Value;
#[inline]
fn len(&self) -> usize {
(**self).len()
}
fn get_value(&self, index: usize) -> Option<Self::Value> {
(**self).get_value(index)
}
fn index_value(&self, index: usize) -> Self::Value {
(**self).index_value(index)
}
unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
unsafe { (**self).get_value_unchecked(index) }
}
}
impl<'a, S: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for Arc<S> {
type Subslice = S::Subslice;
}
impl<S: SliceByValue + ?Sized> SliceByValue for Rc<S> {
type Value = S::Value;
#[inline]
fn len(&self) -> usize {
(**self).len()
}
fn get_value(&self, index: usize) -> Option<Self::Value> {
(**self).get_value(index)
}
fn index_value(&self, index: usize) -> Self::Value {
(**self).index_value(index)
}
unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
unsafe { (**self).get_value_unchecked(index) }
}
}
impl<'a, S: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for Rc<S> {
type Subslice = S::Subslice;
}
macro_rules! impl_range_arc_and_rc {
($range:ty) => {
impl<S: SliceByValueSubsliceRange<$range> + ?Sized> SliceByValueSubsliceRange<$range>
for Rc<S>
{
#[inline]
fn get_subslice(&self, index: $range) -> Option<Subslice<'_, Self>> {
(**self).get_subslice(index)
}
#[inline]
fn index_subslice(&self, index: $range) -> Subslice<'_, Self> {
(**self).index_subslice(index)
}
#[inline]
unsafe fn get_subslice_unchecked(&self, index: $range) -> Subslice<'_, Self> {
unsafe { (**self).get_subslice_unchecked(index) }
}
}
impl<S: SliceByValueSubsliceRange<$range> + ?Sized> SliceByValueSubsliceRange<$range>
for Arc<S>
{
#[inline]
fn get_subslice(&self, index: $range) -> Option<Subslice<'_, Self>> {
(**self).get_subslice(index)
}
#[inline]
fn index_subslice(&self, index: $range) -> Subslice<'_, Self> {
(**self).index_subslice(index)
}
#[inline]
unsafe fn get_subslice_unchecked(&self, index: $range) -> Subslice<'_, Self> {
unsafe { (**self).get_subslice_unchecked(index) }
}
}
};
}
impl_range_arc_and_rc!(RangeFull);
impl_range_arc_and_rc!(RangeFrom<usize>);
impl_range_arc_and_rc!(RangeTo<usize>);
impl_range_arc_and_rc!(Range<usize>);
impl_range_arc_and_rc!(RangeInclusive<usize>);
impl_range_arc_and_rc!(RangeToInclusive<usize>);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[allow(clippy::reversed_empty_ranges)]
fn test_good_ranges() {
assert!((0..1).is_valid(1));
assert!(!(1..0).is_valid(1));
assert!(!(0..1).is_valid(0));
assert!((0..).is_valid(1));
assert!((1..).is_valid(1));
assert!(!(2..).is_valid(1));
assert!((..).is_valid(0));
assert!((..).is_valid(1));
assert!((0..=1).is_valid(2));
assert!(!(1..=0).is_valid(2));
assert!(!(0..=1).is_valid(1));
assert!((..0).is_valid(1));
assert!((..1).is_valid(1));
assert!(!(..2).is_valid(1));
assert!((..=0).is_valid(2));
assert!((..=1).is_valid(2));
assert!(!(..=2).is_valid(2));
}
}