#[cfg(any(feature = "alloc", feature = "std"))]
mod boxed;
#[cfg(any(feature = "alloc", feature = "std"))]
mod concat;
#[cfg(any(feature = "alloc", feature = "std"))]
mod join;
mod slice_index;
use core::{
cmp::Ordering,
fmt,
marker::PhantomData,
ops,
slice::{
Chunks, ChunksExact, ChunksExactMut, ChunksMut, Iter, IterMut, RChunks, RChunksExact,
RChunksExactMut, RChunksMut, RSplit, RSplitMut, RSplitN, RSplitNMut, Split, SplitMut,
SplitN, SplitNMut, Windows,
},
};
#[cfg(any(feature = "alloc", feature = "std"))]
use alloc::{borrow::ToOwned, boxed::Box};
#[cfg(feature = "serde")]
use serde::ser::{Serialize, Serializer};
use crate::{Index, TiEnumerated, TiRangeBounds, TiSliceKeys, TiSliceMutMap, TiSliceRefMap};
#[cfg(any(feature = "alloc", feature = "std"))]
use crate::TiVec;
#[cfg(any(feature = "alloc", feature = "std"))]
use concat::Concat;
#[cfg(any(feature = "alloc", feature = "std"))]
use join::Join;
pub use slice_index::TiSliceIndex;
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
use typed_index_collections::TiSlice;
use derive_more::{From, Into};
#[derive(From, Into)]
struct FooId(usize);
let mut foos_raw = [1, 2, 5, 8];
let foos: &mut TiSlice<FooId, usize> = TiSlice::from_mut(&mut foos_raw);
foos[FooId(2)] = 4;
assert_eq!(foos[FooId(2)], 4);
```
"#
)]
#[derive(Eq, Hash, Ord, PartialOrd)]
pub struct TiSlice<K, V> {
_marker: PhantomData<fn(K) -> K>,
pub raw: [V],
}
impl<K, V> TiSlice<K, V> {
#[allow(trivial_casts)]
#[inline]
pub fn from_ref(raw: &[V]) -> &Self {
unsafe { &*(raw as *const [V] as *const Self) }
}
#[allow(trivial_casts)]
#[inline]
pub fn from_mut(raw: &mut [V]) -> &mut Self {
unsafe { &mut *(raw as *mut [V] as *mut Self) }
}
#[inline]
pub fn len(&self) -> usize {
self.raw.len()
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Eq, Debug, From, Into, PartialEq)]
pub struct Id(usize);
let slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[1, 2, 4]);
assert_eq!(slice.next_key(), Id(3));
```
"#
)]
#[inline]
pub fn next_key(&self) -> K
where
K: Index,
{
Index::from_usize(self.raw.len())
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.raw.is_empty()
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[1, 2, 4]);
let mut iterator = slice.keys();
assert_eq!(iterator.next(), Some(Id(0)));
assert_eq!(iterator.next(), Some(Id(1)));
assert_eq!(iterator.next(), Some(Id(2)));
assert_eq!(iterator.next(), None);
```
"#
)]
pub fn keys(&self) -> TiSliceKeys<K>
where
K: Index,
{
(0..self.len()).map(Index::from_usize)
}
#[inline]
pub fn first(&self) -> Option<&V> {
self.raw.first()
}
#[inline]
pub fn first_mut(&mut self) -> Option<&mut V> {
self.raw.first_mut()
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let empty_slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[]);
let slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[1, 2, 4]);
assert_eq!(empty_slice.first_key(), None);
assert_eq!(slice.first_key(), Some(Id(0)));
```
"#
)]
#[inline]
pub fn first_key(&self) -> Option<K>
where
K: Index,
{
if self.is_empty() {
None
} else {
Some(Index::from_usize(0))
}
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let empty_slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[]);
let slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[1, 2, 4]);
assert_eq!(empty_slice.first_key_value(), None);
assert_eq!(slice.first_key_value(), Some((Id(0), &1)));
```
"#
)]
#[inline]
pub fn first_key_value(&self) -> Option<(K, &V)>
where
K: Index,
{
self.raw.first().map(|first| (Index::from_usize(0), first))
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let empty_slice: &mut TiSlice<Id, usize> = TiSlice::from_mut(&mut []);
let mut array = [1, 2, 4];
let slice: &mut TiSlice<Id, usize> = TiSlice::from_mut(&mut array);
assert_eq!(empty_slice.first_key_value_mut(), None);
assert_eq!(slice.first_key_value_mut(), Some((Id(0), &mut 1)));
*slice.first_key_value_mut().unwrap().1 = 123;
assert_eq!(slice.raw, [123, 2, 4]);
```
"#
)]
#[inline]
pub fn first_key_value_mut(&mut self) -> Option<(K, &mut V)>
where
K: Index,
{
self.raw
.first_mut()
.map(|first| (Index::from_usize(0), first))
}
#[inline]
pub fn split_first(&self) -> Option<(&V, &TiSlice<K, V>)> {
self.raw
.split_first()
.map(|(first, rest)| (first, rest.into()))
}
#[inline]
pub fn split_first_mut(&mut self) -> Option<(&mut V, &mut TiSlice<K, V>)> {
self.raw
.split_first_mut()
.map(|(first, rest)| (first, rest.into()))
}
#[inline]
pub fn split_last(&self) -> Option<(&V, &TiSlice<K, V>)> {
self.raw
.split_last()
.map(|(last, rest)| (last, rest.into()))
}
#[inline]
pub fn split_last_mut(&mut self) -> Option<(&mut V, &mut TiSlice<K, V>)> {
self.raw
.split_last_mut()
.map(|(last, rest)| (last, rest.into()))
}
#[inline]
pub fn last(&self) -> Option<&V> {
self.raw.last()
}
#[inline]
pub fn last_mut(&mut self) -> Option<&mut V> {
self.raw.last_mut()
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let empty_slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[]);
let slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[1, 2, 4]);
assert_eq!(empty_slice.last_key(), None);
assert_eq!(slice.last_key(), Some(Id(2)));
```
"#
)]
#[inline]
pub fn last_key(&self) -> Option<K>
where
K: Index,
{
if self.is_empty() {
None
} else {
Some(Index::from_usize(self.len() - 1))
}
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let empty_slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[]);
let slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[1, 2, 4]);
assert_eq!(empty_slice.last_key_value(), None);
assert_eq!(slice.last_key_value(), Some((Id(2), &4)));
```
"#
)]
#[inline]
pub fn last_key_value(&self) -> Option<(K, &V)>
where
K: Index,
{
let len = self.len();
self.raw
.last()
.map(|last| (Index::from_usize(len - 1), last))
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let empty_slice: &mut TiSlice<Id, usize> = TiSlice::from_mut(&mut []);
let mut array = [1, 2, 4];
let slice: &mut TiSlice<Id, usize> = TiSlice::from_mut(&mut array);
assert_eq!(empty_slice.last_key_value_mut(), None);
assert_eq!(slice.last_key_value_mut(), Some((Id(2), &mut 4)));
*slice.last_key_value_mut().unwrap().1 = 123;
assert_eq!(slice.raw, [1, 2, 123]);
```
"#
)]
#[inline]
pub fn last_key_value_mut(&mut self) -> Option<(K, &mut V)>
where
K: Index,
{
let len = self.len();
self.raw
.last_mut()
.map(|last| (Index::from_usize(len - 1), last))
}
#[inline]
pub fn get<I>(&self, index: I) -> Option<&I::Output>
where
I: TiSliceIndex<K, V>,
{
index.get(self)
}
#[inline]
pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
where
I: TiSliceIndex<K, V>,
{
index.get_mut(self)
}
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
where
I: TiSliceIndex<K, V>,
{
index.get_unchecked(self)
}
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
where
I: TiSliceIndex<K, V>,
{
index.get_unchecked_mut(self)
}
#[inline]
pub const fn as_ptr(&self) -> *const V {
self.raw.as_ptr()
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut V {
self.raw.as_mut_ptr()
}
#[inline]
pub fn swap(&mut self, a: K, b: K)
where
K: Index,
{
self.raw.swap(a.into_usize(), b.into_usize())
}
#[inline]
pub fn reverse(&mut self) {
self.raw.reverse()
}
#[inline]
pub fn iter(&self) -> Iter<'_, V> {
self.raw.iter()
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[1, 2, 4]);
let mut iterator = slice.iter_enumerated();
assert_eq!(iterator.next(), Some((Id(0), &1)));
assert_eq!(iterator.next(), Some((Id(1), &2)));
assert_eq!(iterator.next(), Some((Id(2), &4)));
assert_eq!(iterator.next(), None);
```
"#
)]
#[inline]
pub fn iter_enumerated(&self) -> TiEnumerated<Iter<'_, V>, K, &V>
where
K: Index,
{
self.raw
.iter()
.enumerate()
.map(|(key, value)| (Index::from_usize(key), value))
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, V> {
self.raw.iter_mut()
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let mut array = [1, 2, 4];
let slice: &mut TiSlice<Id, usize> = TiSlice::from_mut(&mut array);
for (key, value) in slice.iter_mut_enumerated() {
*value += key.0;
}
assert_eq!(array, [1, 3, 6]);
```
"#
)]
#[inline]
pub fn iter_mut_enumerated(&mut self) -> TiEnumerated<IterMut<'_, V>, K, &mut V>
where
K: Index,
{
self.raw
.iter_mut()
.enumerate()
.map(|(key, value)| (Index::from_usize(key), value))
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[1, 2, 4, 2, 1]);
assert_eq!(slice.position(|&value| value == 1), Some(Id(0)));
assert_eq!(slice.position(|&value| value == 2), Some(Id(1)));
assert_eq!(slice.position(|&value| value == 3), None);
assert_eq!(slice.position(|&value| value == 4), Some(Id(2)));
```
"#
)]
#[inline]
pub fn position<P>(&self, predicate: P) -> Option<K>
where
K: Index,
P: FnMut(&V) -> bool,
{
self.raw.iter().position(predicate).map(Index::from_usize)
}
#[cfg_attr(
feature = "impl-index-from",
doc = r#"
# Example
```
# use derive_more::{From, Into};
# use typed_index_collections::TiSlice;
#[derive(Debug, Eq, From, Into, PartialEq)]
pub struct Id(usize);
let slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[1, 2, 4, 2, 1]);
assert_eq!(slice.rposition(|&value| value == 1), Some(Id(4)));
assert_eq!(slice.rposition(|&value| value == 2), Some(Id(3)));
assert_eq!(slice.rposition(|&value| value == 3), None);
assert_eq!(slice.rposition(|&value| value == 4), Some(Id(2)));
```
"#
)]
#[inline]
pub fn rposition<P>(&self, predicate: P) -> Option<K>
where
K: Index,
P: FnMut(&V) -> bool,
{
self.raw.iter().rposition(predicate).map(Index::from_usize)
}
#[inline]
pub fn windows(&self, size: usize) -> TiSliceRefMap<Windows<'_, V>, K, V> {
self.raw.windows(size).map(TiSlice::from_ref)
}
#[inline]
pub fn chunks(&self, chunk_size: usize) -> TiSliceRefMap<Chunks<'_, V>, K, V> {
self.raw.chunks(chunk_size).map(TiSlice::from_ref)
}
#[inline]
pub fn chunks_mut(&mut self, chunk_size: usize) -> TiSliceMutMap<ChunksMut<'_, V>, K, V> {
self.raw.chunks_mut(chunk_size).map(TiSlice::from_mut)
}
#[inline]
pub fn chunks_exact(&self, chunk_size: usize) -> TiSliceRefMap<ChunksExact<'_, V>, K, V> {
self.raw.chunks_exact(chunk_size).map(TiSlice::from_ref)
}
#[inline]
pub fn chunks_exact_mut(
&mut self,
chunk_size: usize,
) -> TiSliceMutMap<ChunksExactMut<'_, V>, K, V> {
self.raw.chunks_exact_mut(chunk_size).map(TiSlice::from_mut)
}
#[inline]
pub fn rchunks(&self, chunk_size: usize) -> TiSliceRefMap<RChunks<'_, V>, K, V> {
self.raw.rchunks(chunk_size).map(TiSlice::from_ref)
}
#[inline]
pub fn rchunks_mut(&mut self, chunk_size: usize) -> TiSliceMutMap<RChunksMut<'_, V>, K, V> {
self.raw.rchunks_mut(chunk_size).map(TiSlice::from_mut)
}
#[inline]
pub fn rchunks_exact(&self, chunk_size: usize) -> TiSliceRefMap<RChunksExact<'_, V>, K, V> {
self.raw.rchunks_exact(chunk_size).map(TiSlice::from_ref)
}
#[inline]
pub fn rchunks_exact_mut(
&mut self,
chunk_size: usize,
) -> TiSliceMutMap<RChunksExactMut<'_, V>, K, V> {
self.raw
.rchunks_exact_mut(chunk_size)
.map(TiSlice::from_mut)
}
#[inline]
pub fn split_at(&self, mid: K) -> (&Self, &Self)
where
K: Index,
{
let (left, right) = self.raw.split_at(mid.into_usize());
(left.into(), right.into())
}
#[inline]
pub fn split_at_mut(&mut self, mid: K) -> (&mut Self, &mut Self)
where
K: Index,
{
let (left, right) = self.raw.split_at_mut(mid.into_usize());
(left.into(), right.into())
}
#[inline]
pub fn split<F>(&self, pred: F) -> TiSliceRefMap<Split<'_, V, F>, K, V>
where
F: FnMut(&V) -> bool,
{
self.raw.split(pred).map(TiSlice::from_ref)
}
#[inline]
pub fn split_mut<F>(&mut self, pred: F) -> TiSliceMutMap<SplitMut<'_, V, F>, K, V>
where
F: FnMut(&V) -> bool,
{
self.raw.split_mut(pred).map(TiSlice::from_mut)
}
#[inline]
pub fn rsplit<F>(&self, pred: F) -> TiSliceRefMap<RSplit<'_, V, F>, K, V>
where
F: FnMut(&V) -> bool,
{
self.raw.rsplit(pred).map(TiSlice::from_ref)
}
#[inline]
pub fn rsplit_mut<F>(&mut self, pred: F) -> TiSliceMutMap<RSplitMut<'_, V, F>, K, V>
where
F: FnMut(&V) -> bool,
{
self.raw.rsplit_mut(pred).map(TiSlice::from_mut)
}
#[inline]
pub fn splitn<F>(&self, n: usize, pred: F) -> TiSliceRefMap<SplitN<'_, V, F>, K, V>
where
F: FnMut(&V) -> bool,
{
self.raw.splitn(n, pred).map(TiSlice::from_ref)
}
#[inline]
pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> TiSliceMutMap<SplitNMut<'_, V, F>, K, V>
where
F: FnMut(&V) -> bool,
{
self.raw.splitn_mut(n, pred).map(TiSlice::from_mut)
}
#[inline]
pub fn rsplitn<F>(&self, n: usize, pred: F) -> TiSliceRefMap<RSplitN<'_, V, F>, K, V>
where
F: FnMut(&V) -> bool,
{
self.raw.rsplitn(n, pred).map(TiSlice::from_ref)
}
#[inline]
pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> TiSliceMutMap<RSplitNMut<'_, V, F>, K, V>
where
F: FnMut(&V) -> bool,
{
self.raw.rsplitn_mut(n, pred).map(TiSlice::from_mut)
}
pub fn contains(&self, x: &V) -> bool
where
V: PartialEq,
{
self.raw.contains(x)
}
pub fn starts_with(&self, needle: &Self) -> bool
where
V: PartialEq,
{
self.raw.starts_with(needle.into())
}
pub fn ends_with(&self, needle: &Self) -> bool
where
V: PartialEq,
{
self.raw.ends_with(needle.into())
}
pub fn binary_search(&self, x: &V) -> Result<K, K>
where
V: Ord,
K: Index,
{
self.raw
.binary_search(x)
.map(Index::from_usize)
.map_err(Index::from_usize)
}
#[inline]
pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<K, K>
where
F: FnMut(&'a V) -> Ordering,
K: Index,
{
self.raw
.binary_search_by(f)
.map(Index::from_usize)
.map_err(Index::from_usize)
}
#[inline]
pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<K, K>
where
F: FnMut(&'a V) -> B,
B: Ord,
K: Index,
{
self.raw
.binary_search_by_key(b, f)
.map(Index::from_usize)
.map_err(Index::from_usize)
}
#[inline]
pub fn sort_unstable(&mut self)
where
V: Ord,
{
self.raw.sort_unstable()
}
#[inline]
pub fn sort_unstable_by<F>(&mut self, compare: F)
where
F: FnMut(&V, &V) -> Ordering,
{
self.raw.sort_unstable_by(compare)
}
#[inline]
pub fn sort_unstable_by_key<K2, F>(&mut self, f: F)
where
F: FnMut(&V) -> K2,
K2: Ord,
{
self.raw.sort_unstable_by_key(f)
}
pub fn rotate_left(&mut self, mid: K)
where
K: Index,
{
self.raw.rotate_left(mid.into_usize())
}
pub fn rotate_right(&mut self, k: K)
where
K: Index,
{
self.raw.rotate_right(k.into_usize())
}
pub fn clone_from_slice(&mut self, src: &Self)
where
V: Clone,
{
self.raw.clone_from_slice(&src.raw)
}
pub fn copy_from_slice(&mut self, src: &Self)
where
V: Copy,
{
self.raw.copy_from_slice(&src.raw)
}
pub fn copy_within<R>(&mut self, src: R, dest: K)
where
R: TiRangeBounds<K>,
V: Copy,
K: Index,
{
self.raw.copy_within(src.into_range(), dest.into_usize())
}
pub fn swap_with_slice(&mut self, other: &mut Self) {
self.raw.swap_with_slice(other.into())
}
#[allow(clippy::missing_safety_doc)]
pub unsafe fn align_to<U>(&self) -> (&Self, &TiSlice<K, U>, &Self) {
let (first, mid, last) = self.raw.align_to();
(first.into(), mid.into(), last.into())
}
#[allow(clippy::missing_safety_doc)]
pub unsafe fn align_to_mut<U>(&mut self) -> (&mut Self, &mut TiSlice<K, U>, &mut Self) {
let (first, mid, last) = self.raw.align_to_mut();
(first.into(), mid.into(), last.into())
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
impl<K, V> TiSlice<K, V> {
#[inline]
pub fn sort(&mut self)
where
V: Ord,
{
self.raw.sort()
}
#[inline]
pub fn sort_by<F>(&mut self, compare: F)
where
F: FnMut(&V, &V) -> Ordering,
{
self.raw.sort_by(compare)
}
#[inline]
pub fn sort_by_key<K2, F>(&mut self, f: F)
where
F: FnMut(&V) -> K2,
K2: Ord,
{
self.raw.sort_by_key(f)
}
#[inline]
pub fn sort_by_cached_key<K2, F>(&mut self, f: F)
where
F: FnMut(&V) -> K2,
K2: Ord,
{
self.raw.sort_by_cached_key(f)
}
#[inline]
pub fn to_vec(&self) -> TiVec<K, V>
where
V: Clone,
{
self.raw.to_vec().into()
}
#[inline]
pub fn into_vec(self: Box<Self>) -> TiVec<K, V> {
Box::<[V]>::from(self).into_vec().into()
}
pub fn repeat(&self, n: usize) -> TiVec<K, V>
where
V: Copy,
{
self.raw.repeat(n).into()
}
pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output
where
Self: Concat<Item>,
{
Concat::concat(self)
}
pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
where
Self: Join<Separator>,
{
Join::join(self, sep)
}
}
impl<K, V> fmt::Debug for TiSlice<K, V>
where
K: fmt::Debug + Index,
V: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter_enumerated()).finish()
}
}
impl<K, V> AsRef<TiSlice<K, V>> for TiSlice<K, V> {
fn as_ref(&self) -> &TiSlice<K, V> {
self
}
}
impl<K, V> AsMut<TiSlice<K, V>> for TiSlice<K, V> {
fn as_mut(&mut self) -> &mut TiSlice<K, V> {
self
}
}
impl<I, K, V> ops::Index<I> for TiSlice<K, V>
where
I: TiSliceIndex<K, V>,
{
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
index.index(self)
}
}
impl<I, K, V> ops::IndexMut<I> for TiSlice<K, V>
where
I: TiSliceIndex<K, V>,
{
#[inline]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
index.index_mut(self)
}
}
impl<'a, K, V> IntoIterator for &'a TiSlice<K, V> {
type Item = &'a V;
type IntoIter = Iter<'a, V>;
#[allow(clippy::into_iter_on_ref)]
fn into_iter(self) -> Iter<'a, V> {
self.raw.into_iter()
}
}
impl<'a, K, V> IntoIterator for &'a mut TiSlice<K, V> {
type Item = &'a mut V;
type IntoIter = IterMut<'a, V>;
#[allow(clippy::into_iter_on_ref)]
fn into_iter(self) -> IterMut<'a, V> {
(&mut self.raw).into_iter()
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
impl<K, V: Clone> ToOwned for TiSlice<K, V> {
type Owned = TiVec<K, V>;
fn to_owned(&self) -> TiVec<K, V> {
self.raw.to_owned().into()
}
}
impl<K, A, B> PartialEq<TiSlice<K, B>> for TiSlice<K, A>
where
A: PartialEq<B>,
{
fn eq(&self, other: &TiSlice<K, B>) -> bool {
self.raw == other.raw
}
}
impl<K, V> Default for &TiSlice<K, V> {
#[inline]
fn default() -> Self {
TiSlice::from_ref(&[])
}
}
impl<K, V> Default for &mut TiSlice<K, V> {
#[inline]
fn default() -> Self {
TiSlice::from_mut(&mut [])
}
}
impl<'a, K, V> From<&'a [V]> for &'a TiSlice<K, V> {
fn from(slice: &'a [V]) -> Self {
TiSlice::from_ref(slice)
}
}
impl<'a, K, V> From<&'a mut [V]> for &'a mut TiSlice<K, V> {
fn from(slice: &'a mut [V]) -> Self {
TiSlice::from_mut(slice)
}
}
impl<'a, K, V> From<&'a TiSlice<K, V>> for &'a [V] {
fn from(slice: &'a TiSlice<K, V>) -> Self {
&slice.raw
}
}
impl<'a, K, V> From<&'a mut TiSlice<K, V>> for &'a mut [V] {
fn from(slice: &'a mut TiSlice<K, V>) -> Self {
&mut slice.raw
}
}
#[cfg(feature = "serde")]
impl<K, V: Serialize> Serialize for TiSlice<K, V> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.raw.serialize(serializer)
}
}
#[cfg(test)]
mod test {
use crate::TiSlice;
#[derive(Clone, Debug, Eq, PartialEq)]
struct NoCopy<T>(T);
mod private {
#[cfg(feature = "impl-index-from")]
use derive_more::{From, Into};
#[cfg(not(feature = "impl-index-from"))]
use crate::Index;
#[cfg_attr(feature = "impl-index-from", derive(From, Into))]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Id(usize);
#[cfg(not(feature = "impl-index-from"))]
impl Index for Id {
fn from_usize(index: usize) -> Self {
Self(index)
}
fn into_usize(self) -> usize {
self.0
}
}
}
use private::Id;
mod conversion {
use super::Id;
use crate::TiSlice;
#[cfg(not(feature = "impl-index-from"))]
use crate::Index;
pub trait DummyConvert {
type Target;
fn into_t(self) -> Self::Target;
}
pub trait TypedConvert {
type Target;
fn into_t(self) -> Self::Target;
}
impl<'a, T> DummyConvert for T {
type Target = T;
fn into_t(self) -> Self::Target {
self
}
}
macro_rules! impl_convert {
(impl {($($args:tt)*)($self:ident)($source:ty)($target:ty)($($where:tt)*)($($body:tt)*)} ) => {
impl $($args)* TypedConvert for $source $($where)* {
type Target = $target;
fn into_t($self) -> Self::Target {
$($body)*
}
}
};
( |$self:ident: $source:ty| -> $target:ty { $($body:tt)* } ) => {
impl_convert!(impl {()($self)($source)($target)()($($body)*)});
};
( for ($($args:tt)*) |$self:ident: $source:ty| -> $target:ty { $($body:tt)* } ) => {
impl_convert!(impl {(<$($args)*>)($self)($source)($target)()($($body)*)});
};
( for ($($args:tt)*) |$self:ident: $source:ty| -> $target:ty
where ( $($bounds:tt)* ) { $($body:tt)* }
) => {
impl_convert!(impl {(<$($args)*>)($self)($source)($target)(where $($bounds)*)($($body)*)});
};
}
#[cfg(not(feature = "impl-index-from"))]
impl_convert!(|self: usize| -> Id { Id::from_usize(self) });
#[cfg(not(feature = "impl-index-from"))]
impl_convert!(|self: Id| -> usize { self.into_usize() });
#[cfg(feature = "impl-index-from")]
impl_convert!(|self: usize| -> Id { self.into() });
#[cfg(feature = "impl-index-from")]
impl_convert!(|self: Id| -> usize { self.into() });
impl_convert!(for ('a, V)
|self: &'a [V]| -> &'a TiSlice<Id, V> { self.into() });
impl_convert!(for ('a, V)
|self: &'a mut [V]| -> &'a mut TiSlice<Id, V> { self.into() });
impl_convert!(for ('a, V)
|self: &'a TiSlice<Id, V>| -> &'a [V] { self.into() });
impl_convert!(for ('a, V)
|self: &'a mut TiSlice<Id, V>| -> &'a mut [V] { self.into() });
impl_convert!(for ('a, V)
|self: (&'a V, &'a TiSlice<Id, V>)| -> (&'a V, &'a [V]) {
(self.0, self.1.into())
}
);
impl_convert!(for ('a, V)
|self: (&'a mut V, &'a mut TiSlice<Id, V>)| -> (&'a mut V, &'a mut [V]) {
(self.0, self.1.into())
}
);
impl_convert!(for ('a, V, U)
|self: (&'a TiSlice<Id, V>, &'a TiSlice<Id, U>)| -> (&'a [V], &'a [U]) {
(self.0.into(), self.1.into())
}
);
impl_convert!(for ('a, V, U)
|self: (&'a mut TiSlice<Id, V>, &'a mut TiSlice<Id, U>)| -> (&'a mut [V], &'a mut [U]) {
(self.0.into(), self.1.into())
}
);
impl_convert!(for ('a, V, U, W)
|self: (&'a TiSlice<Id, V>, &'a TiSlice<Id, U>, &'a TiSlice<Id, W>)|
-> (&'a [V], &'a [U], &'a [W])
{
(self.0.into(), self.1.into(), self.2.into())
}
);
impl_convert!(for ('a, V, U, W) |
self: (&'a mut TiSlice<Id, V>, &'a mut TiSlice<Id, U>, &'a mut TiSlice<Id, W>
)| -> (&'a mut [V], &'a mut [U], &'a mut [W]) {
(self.0.into(), self.1.into(), self.2.into())
}
);
impl_convert!(for (T) |self: Option<T>| -> Option<T::Target> where (T: TypedConvert) {
self.map(|value| value.into_t())
});
impl_convert!(for (T, U) |self: Result<T, U>| -> Result<T::Target, U::Target>
where (T: TypedConvert, U: TypedConvert) {
self.map(|value| value.into_t()).map_err(|value| value.into_t())
}
);
}
macro_rules! for_in {
(for $name:ident in [$($value:expr),* $(,)?] $expr:expr) => {
$({
let $name = $value;
$expr
})*
};
}
macro_rules! assert_api_impl(
(
($fn:ident)
($($mut_outer:tt)*)
($($mut_inner:tt)*)
($($ref:tt)*)
($source:expr)
($arg:ident)
($expr:expr)
) => {{
let $($mut_outer)* _1 = $source;
let $($mut_outer)* _2 = $source;
$fn!({
#[deny(unused_imports)]
use conversion::TypedConvert;
let $($mut_inner)* $arg = $($ref)* _1;
$expr
}, {
#[deny(unused_imports)]
use conversion::DummyConvert;
let $($mut_inner)* $arg = $($ref)* _2;
$expr
},
"where expr: {}", stringify!($expr))
}};
);
macro_rules! assert_eq_api(
($source:expr => |&mut $arg:ident| $expr:expr) => {
assert_api_impl!((assert_eq)(mut)()(&mut)($source)($arg)($expr))
};
($source:expr => |mut $arg:ident| $expr:expr) => {
assert_api_impl!((assert_eq)()(mut)()($source)($arg)($expr))
};
($source:expr => |&$arg:ident| $expr:expr) => {
assert_api_impl!((assert_eq)()()(&)($source)($arg)($expr))
};
($source:expr => |$arg:ident| $expr:expr) => {
assert_api_impl!((assert_eq)()()()($source)($arg)($expr))
};
);
macro_rules! assert_ne_api(
($source:expr => |&mut $arg:ident| $expr:expr) => {
assert_api_impl!((assert_ne)(mut)()(&mut)($source)($arg)($expr))
};
($source:expr => |mut $arg:ident| $expr:expr) => {
assert_api_impl!((assert_ne)()(mut)()($source)($arg)($expr))
};
($source:expr => |&$arg:ident| $expr:expr) => {
assert_api_impl!((assert_ne)()()(&)($source)($arg)($expr))
};
($source:expr => |$arg:ident| $expr:expr) => {
assert_api_impl!((assert_ne)()()()($source)($arg)($expr))
};
);
#[rustfmt::skip]
fn array_32_from<T, F>(mut func: F) -> [T; 32]
where
F: FnMut() -> T,
{
[
func(), func(), func(), func(), func(), func(), func(), func(),
func(), func(), func(), func(), func(), func(), func(), func(),
func(), func(), func(), func(), func(), func(), func(), func(),
func(), func(), func(), func(), func(), func(), func(), func(),
]
}
#[test]
fn no_std_api_compatibility() {
for_in!(for arr in [[0; 0], [1], [1, 2], [1, 2, 4]] {
assert_eq_api!(arr => |arr| arr.as_ref().into_t().len());
assert_eq_api!(arr => |arr| arr.as_ref().into_t().is_empty());
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().first());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t().first_mut());
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().split_first().into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t().split_first_mut().into_t());
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().split_last().into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t().split_last_mut().into_t());
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().last());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t().last_mut());
for index in 0..5_usize {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().get(index.into_t()));
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t().get_mut(index.into_t()));
}
for index in 0..arr.len() {
unsafe {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get_unchecked(index.into_t()));
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_unchecked_mut(index.into_t()));
}
}
for start in 0..5usize {
for end in 0..5usize {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get(start.into_t()..end.into_t()).into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_mut(start.into_t()..end.into_t()).into_t());
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get(start.into_t()..=end.into_t()).into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_mut(start.into_t()..=end.into_t()).into_t());
}
}
unsafe {
for start in 0..arr.len() {
for end in start..arr.len() {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get_unchecked(start.into_t()..end.into_t()).into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_unchecked_mut(start.into_t()..end.into_t()).into_t());
}
}
if !arr.is_empty() {
for start in 0..arr.len() - 1 {
for end in start..arr.len() - 1 {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get_unchecked(start.into_t()..=end.into_t()).into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_unchecked_mut(start.into_t()..=end.into_t()).into_t());
}
}
}
}
for start in 0..5usize {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get(start.into_t()..).into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_mut(start.into_t()..).into_t());
}
unsafe {
for start in 0..arr.len() {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get_unchecked(start.into_t()..).into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_unchecked_mut(start.into_t()..).into_t());
}
}
for end in 0..5usize {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get(..end.into_t()).into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_mut(..end.into_t()).into_t());
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get(..=end.into_t()).into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_mut(..=end.into_t()).into_t());
}
unsafe {
for end in 0..arr.len() {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get_unchecked(..end.into_t()).into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_unchecked_mut(..end.into_t()).into_t());
}
if !arr.is_empty() {
for end in 0..arr.len() - 1 {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.get_unchecked(..=end.into_t()).into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t()
.get_unchecked_mut(..=end.into_t()).into_t());
}
}
}
});
for_in!(for arr in [&[0; 0], &[1], &[1, 2], &[1, 2, 4]] {
assert_eq_api!(arr => |arr| arr.into_t().as_ptr());
});
for_in!(for arr in [[0; 0], [1], [1, 2], [1, 2, 4]] {
assert_ne_api!(arr => |&mut arr| arr.as_mut().into_t().as_mut_ptr());
});
assert_eq_api!([1u32, 2, 3] => |&mut arr| {
arr.as_mut().into_t().swap(0.into_t(), 2.into_t());
arr
});
for_in!(for arr in [[0; 0], [1], [1, 2], [1, 2, 4]] {
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().reverse();
arr
});
assert_eq_api!(arr => |&arr| {
let mut iter = arr.as_ref().into_t().iter();
array_32_from(|| iter.next())
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().iter_mut().for_each(|item| *item += 1);
arr
});
for chunk_size in 1..5 {
assert_eq_api!(arr => |&arr| {
let mut windows = arr.as_ref().into_t().windows(chunk_size);
array_32_from(|| windows.next().into_t())
});
assert_eq_api!(arr => |&arr| {
let mut chunks = arr.as_ref().into_t().chunks(chunk_size);
array_32_from(|| chunks.next().into_t())
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().chunks_mut(chunk_size)
.for_each(|slice| slice.iter_mut().for_each(|item| *item += 1));
arr
});
assert_eq_api!(arr => |&arr| {
let mut chunks = arr.as_ref().into_t().chunks_exact(chunk_size);
array_32_from(|| chunks.next().into_t())
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().chunks_exact_mut(chunk_size)
.for_each(|slice| slice.iter_mut().for_each(|item| *item += 1));
arr
});
assert_eq_api!(arr => |&arr| {
let mut chunks = arr.as_ref().into_t().rchunks(chunk_size);
array_32_from(|| chunks.next().into_t())
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().rchunks_mut(chunk_size)
.for_each(|slice| slice.iter_mut().for_each(|item| *item += 1));
arr
});
assert_eq_api!(arr => |&arr| {
let mut chunks = arr.as_ref().into_t().rchunks_exact(chunk_size);
array_32_from(|| chunks.next().into_t())
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().rchunks_exact_mut(chunk_size)
.for_each(|slice| slice.iter_mut().for_each(|item| *item += 1));
arr
});
}
});
for_in!(for arr in [[0; 0], [1], [1, 2], [1, 2, 4], [1, 2, 3, 4]] {
for mid in 0..arr.len() {
assert_eq_api!(arr => |&arr| {
arr.as_ref().into_t().split_at(mid.into_t()).into_t()
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().split_at_mut(mid.into_t()).into_t()
});
}
for div in 1..5 {
assert_eq_api!(arr => |&arr| {
let mut split = arr.as_ref().into_t().split(|v| v % div == 0);
array_32_from(|| split.next().into_t())
});
assert_eq_api!(arr => |&mut arr| {
let mut split = arr.as_mut().into_t().split_mut(|v| v % div == 0);
array_32_from(|| split.next().into_t())
});
assert_eq_api!(arr => |&arr| {
let mut split = arr.as_ref().into_t().rsplit(|v| v % div == 0);
array_32_from(|| split.next().into_t())
});
assert_eq_api!(arr => |&mut arr| {
let mut split = arr.as_mut().into_t().rsplit_mut(|v| v % div == 0);
array_32_from(|| split.next().into_t())
});
for num in 1..5 {
assert_eq_api!(arr => |&arr| {
let mut split = arr.as_ref().into_t().splitn(num, |v| v % div == 0);
array_32_from(|| split.next().into_t())
});
assert_eq_api!(arr => |&mut arr| {
let mut split = arr.as_mut().into_t().splitn_mut(num, |v| v % div == 0);
array_32_from(|| split.next().into_t())
});
assert_eq_api!(arr => |&arr| {
let mut split = arr.as_ref().into_t().rsplitn(num, |v| v % div == 0);
array_32_from(|| split.next().into_t())
});
assert_eq_api!(arr => |&mut arr| {
let mut split = arr.as_mut().into_t().rsplitn_mut(num, |v| v % div == 0);
array_32_from(|| split.next().into_t())
});
}
}
});
for_in!(for arr in [[0; 0], [1], [1, 2], [1, 3, 5], [1, 2, 3, 4]] {
for value in 0..5 {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().contains(&value));
}
for needle in &[
&[][..],
&[0][..],
&[1, 2][..],
&[3, 4][..],
&[1, 3][..],
&[3, 5][..],
] {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().starts_with(needle.into_t()));
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().ends_with(needle.into_t()));
}
for value in 0..5 {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().contains(&value));
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().binary_search(&value).into_t());
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.binary_search_by(|item| item.cmp(&value)).into_t());
assert_eq_api!(arr => |&arr| arr.as_ref().into_t()
.binary_search_by_key(&value, |item| 5 - item).into_t());
}
});
for_in!(
for arr in [[0; 0], [1], [1, 3], [7, 3, 5], [10, 6, 35, 4]] {
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().sort_unstable();
arr
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t()
.sort_unstable_by(|lhs, rhs| rhs.partial_cmp(lhs).unwrap());
arr
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t()
.sort_unstable_by_key(|&value| value * (value % 3));
arr
});
for mid in 0..arr.len() {
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().rotate_left(mid.into_t());
arr
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().rotate_right(mid.into_t());
arr
});
}
}
);
for_in!(for src in [
[NoCopy(0); 0],
[NoCopy(1)],
[NoCopy(1), NoCopy(3)],
[NoCopy(7), NoCopy(3), NoCopy(5)],
[NoCopy(10), NoCopy(6), NoCopy(35), NoCopy(4)]
] {
assert_eq_api!([
NoCopy(1),
NoCopy(2),
NoCopy(3),
NoCopy(4),
NoCopy(5),
NoCopy(6),
] => |&mut arr| {
arr.as_mut().into_t()[..src.len().into_t()]
.clone_from_slice(src.as_ref().into_t());
arr
});
});
for_in!(
for src in [[0; 0], [1], [1, 3], [7, 3, 5], [10, 6, 35, 4]] {
assert_eq_api!([1, 2, 3, 4, 5, 6] => |&mut arr| {
arr.as_mut().into_t()[..src.len().into_t()]
.copy_from_slice(src.as_ref().into_t());
arr
});
}
);
assert_eq_api!([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] => |&mut arr| {
arr.as_mut().into_t().copy_within(1.into_t()..4.into_t(), 6.into_t());
arr
});
assert_eq_api!(([1, 2], [3, 4, 5, 6]) => |mut args| {
args.0.as_mut().into_t().swap_with_slice((&mut args.1[2..]).into_t());
});
{
let mut arr = [1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17];
for start in 0..arr.len() {
for end in start..arr.len() {
unsafe {
assert_eq_api!(&arr => |&arr| {
arr.as_ref()[start..end].into_t().align_to::<u64>().into_t()
});
assert_eq!(
{
let (prefix, values, suffixes) = arr.as_mut().align_to::<u64>();
(prefix.to_vec(), values.to_vec(), suffixes.to_vec())
},
{
let (prefix, values, suffixes) =
TiSlice::<Id, _>::from_mut(arr.as_mut()).align_to::<u64>();
(
prefix.raw.to_vec(),
values.raw.to_vec(),
suffixes.raw.to_vec(),
)
}
);
}
}
}
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
#[test]
fn std_api_compatibility() {
use alloc::boxed::Box;
for_in!(
for arr in [[0; 0], [1], [1, 3], [7, 3, 5], [10, 6, 35, 4]] {
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().sort();
arr
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().sort_by(|lhs, rhs| rhs.partial_cmp(lhs).unwrap());
arr
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().sort_by_key(|&value| value * (value % 3));
arr
});
assert_eq_api!(arr => |&mut arr| {
arr.as_mut().into_t().sort_by_cached_key(|&value| value * (value % 3));
arr
});
assert_eq_api!(arr => |&arr| arr.into_t().to_vec().as_slice().into_t());
assert_eq_api!(arr => |&arr| {
let boxed = Box::new(arr.into_t().to_vec().into_boxed_slice());
boxed.into_vec().as_slice().into_t()
});
assert_eq_api!(arr => |&arr| arr.into_t().repeat(5).as_slice().into_t());
assert_eq_api!([[1, 2], [3, 4]] => |arr| arr.into_t().concat().as_slice().into_t());
assert_eq_api!([[1, 2], [3, 4]] => |arr| arr.into_t().join(&0).as_slice().into_t());
}
);
}
#[test]
fn no_std_trait_api_compatibility() {
use core::slice::IterMut;
for_in!(for arr in [[0; 0], [1], [1, 2], [1, 2, 4]] {
assert_eq_api!(arr => |&arr| arr.as_ref().into_t().as_ref().into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut().into_t().as_mut().into_t());
for index in 0..arr.len() {
assert_eq_api!(arr => |&arr| &arr.as_ref().into_t()[index.into_t()]);
assert_eq_api!(arr => |&mut arr| &mut arr.as_mut().into_t()[index.into_t()]);
}
for start in 0..arr.len() {
for end in start..arr.len() {
assert_eq_api!(arr => |&arr| &arr.as_ref().into_t()
[start.into_t()..end.into_t()].into_t());
assert_eq_api!(arr => |&mut arr| &mut arr.as_mut().into_t()
[start.into_t()..end.into_t()].into_t());
}
}
if !arr.is_empty() {
for start in 0..arr.len() - 1 {
for end in start..arr.len() - 1 {
assert_eq_api!(arr => |&arr| &arr.as_ref()
.into_t()[start.into_t()..=end.into_t()].into_t());
assert_eq_api!(arr => |&mut arr| &mut arr.as_mut()
.into_t()[start.into_t()..=end.into_t()].into_t());
}
}
}
for start in 0..arr.len() {
assert_eq_api!(arr => |&arr| arr.as_ref()
.into_t()[start.into_t()..].into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut()
.into_t()[start.into_t()..].into_t());
}
for end in 0..arr.len() {
assert_eq_api!(arr => |&arr| arr.as_ref()
.into_t()[..end.into_t()].into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut()
.into_t()[..end.into_t()].into_t());
}
if !arr.is_empty() {
for end in 0..arr.len() - 1 {
assert_eq_api!(arr => |&arr| arr.as_ref()
.into_t()[..=end.into_t()].into_t());
assert_eq_api!(arr => |&mut arr| arr.as_mut()
.into_t()[..=end.into_t()].into_t());
}
}
assert_eq_api!(arr => |&arr| {
#[allow(clippy::into_iter_on_ref)]
let mut iter = arr.as_ref().into_t().into_iter();
array_32_from(|| iter.next())
});
assert_eq_api!(arr => |&mut arr| {
#[allow(clippy::into_iter_on_ref)]
let mut iter: IterMut<'_, _> = arr.as_mut().into_t().into_iter();
array_32_from(|| iter.next())
});
});
for_in!(for lhs in [[0; 0], [1], [1, 2], [1, 2, 4]] {
for_in!(for rhs in [[0; 0], [1], [1, 2], [1, 2, 4]] {
let arrays = (lhs, rhs);
assert_eq_api!(arrays => |arrays| arrays.0.as_ref().into_t() == arrays.1.as_ref().into_t());
});
});
let default_slice_ref: &[usize] = Default::default();
let default_ti_slice_ref: &TiSlice<Id, usize> = Default::default();
assert_eq!(default_slice_ref, &default_ti_slice_ref.raw);
let default_slice_mut: &mut [usize] = Default::default();
let default_ti_slice_mut: &mut TiSlice<Id, usize> = Default::default();
assert_eq!(default_slice_mut, &mut default_ti_slice_mut.raw);
}
#[cfg(any(feature = "alloc", feature = "std"))]
#[test]
fn alloc_trait_api_compatibility() {
use alloc::borrow::ToOwned;
for_in!(for arr in [[0; 0], [1], [1, 2], [1, 2, 4]] {
assert_eq_api!(arr => |arr| arr.as_ref().into_t().to_owned().as_slice().into_t());
});
}
#[test]
fn use_non_zero_indecies() {
use crate::Index;
use core::num::NonZeroUsize;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Id(NonZeroUsize);
impl Index for Id {
fn from_usize(value: usize) -> Self {
Self(NonZeroUsize::new(value + 1).unwrap())
}
fn into_usize(self) -> usize {
self.0.get() - 1
}
}
assert_eq!(
core::mem::size_of::<Option<Id>>(),
core::mem::size_of::<Id>()
);
let slice: &TiSlice<Id, usize> = TiSlice::from_ref(&[1, 2, 4, 8, 16]);
assert_eq!(
slice.first_key_value(),
Some((Id(NonZeroUsize::new(1).unwrap()), &1))
);
}
}