use crate::{
iter::{ConstIntoIter, IsIteratorKind},
option, slice,
};
use konst_kernel::iterator_shared;
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub use konst_kernel::into_iter::slice_into_iter::iter;
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub use konst_kernel::into_iter::slice_into_iter::Iter;
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub use konst_kernel::into_iter::slice_into_iter::IterRev;
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub use konst_kernel::into_iter::slice_into_iter::iter_copied;
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub use konst_kernel::into_iter::slice_into_iter::IterCopied;
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub use konst_kernel::into_iter::slice_into_iter::IterCopiedRev;
mod requires_rust_1_64 {
use super::*;
#[inline(always)]
pub(crate) const fn some_if_nonempty<T>(slice: &[T]) -> Option<&[T]> {
if let [] = slice {
None
} else {
Some(slice)
}
}
#[track_caller]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn windows<T>(slice: &[T], size: usize) -> Windows<'_, T> {
assert!(size != 0, "window size must be non-zero");
Windows { slice, size }
}
macro_rules! windows_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
item = &'a [T],
iter_forward = Windows<'a, T>,
iter_reversed = WindowsRev<'a, T>,
next(self){
if self.slice.len() < self.size {
None
} else {
let up_to = slice::slice_up_to(self.slice, self.size);
self.slice = slice::slice_from(self.slice, 1);
Some((up_to, self))
}
},
next_back {
let len = self.slice.len();
if len < self.size {
None
} else {
let up_to = slice::slice_from(self.slice, len - self.size);
self.slice = slice::slice_up_to(self.slice, len - 1);
Some((up_to, self))
}
},
fields = {slice, size},
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct Windows<'a, T> {
slice: &'a [T],
size: usize,
}
impl<'a, T> ConstIntoIter for Windows<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T];
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct WindowsRev<'a, T> {
slice: &'a [T],
size: usize,
}
impl<'a, T> ConstIntoIter for WindowsRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T];
}
impl<'a, T> Windows<'a, T> {
windows_shared! {is_forward = true}
}
impl<'a, T> WindowsRev<'a, T> {
windows_shared! {is_forward = false}
}
pub const fn array_chunks<'a, T, const N: usize>(slice: &'a [T]) -> ArrayChunks<'a, T, N> {
let (arrays, rem) = slice::as_chunks(slice);
ArrayChunks { arrays, rem }
}
macro_rules! array_chunks_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
item = &'a [T; N],
iter_forward = ArrayChunks<'a, T, N>,
iter_reversed = ArrayChunksRev<'a, T, N>,
next(self) {
match self.arrays {
[elem, arrays @ ..] => Some((elem, Self {arrays, rem: self.rem})),
[] => None,
}
},
next_back {
match self.arrays {
[arrays @ .., elem] => Some((elem, Self {arrays, rem: self.rem})),
[] => None,
}
},
fields = {arrays, rem},
}
};
}
pub struct ArrayChunks<'a, T, const N: usize> {
arrays: &'a [[T; N]],
rem: &'a [T],
}
impl<'a, T, const N: usize> ConstIntoIter for ArrayChunks<'a, T, N> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T; N];
}
pub struct ArrayChunksRev<'a, T, const N: usize> {
arrays: &'a [[T; N]],
rem: &'a [T],
}
impl<'a, T, const N: usize> ConstIntoIter for ArrayChunksRev<'a, T, N> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T; N];
}
impl<'a, T, const N: usize> ArrayChunks<'a, T, N> {
array_chunks_shared! {is_forward = true}
pub const fn remainder(&self) -> &'a [T] {
self.rem
}
}
impl<'a, T, const N: usize> ArrayChunksRev<'a, T, N> {
array_chunks_shared! {is_forward = false}
}
#[track_caller]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn chunks<T>(slice: &[T], chunk_size: usize) -> Chunks<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
Chunks {
slice: some_if_nonempty(slice),
chunk_size,
}
}
macro_rules! chunks_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
item = &'a [T],
iter_forward = Chunks<'a, T>,
iter_reversed = ChunksRev<'a, T>,
next(self) {
option::map!(self.slice, |slice| {
let (ret, next) = slice::split_at(slice, self.chunk_size);
self.slice = some_if_nonempty(next);
(ret, self)
})
},
next_back{
option::map!(self.slice, |slice| {
let at = (slice.len() - 1) / self.chunk_size * self.chunk_size;
let (next, ret) = slice::split_at(slice, at);
self.slice = some_if_nonempty(next);
(ret, self)
})
},
fields = {slice, chunk_size},
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct Chunks<'a, T> {
slice: Option<&'a [T]>,
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for Chunks<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T];
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct ChunksRev<'a, T> {
slice: Option<&'a [T]>,
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for ChunksRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T];
}
impl<'a, T> Chunks<'a, T> {
chunks_shared! {is_forward = true}
}
impl<'a, T> ChunksRev<'a, T> {
chunks_shared! {is_forward = false}
}
#[track_caller]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn rchunks<T>(slice: &[T], chunk_size: usize) -> RChunks<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
RChunks {
slice: some_if_nonempty(slice),
chunk_size,
}
}
macro_rules! rchunks_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
item = &'a [T],
iter_forward = RChunks<'a, T>,
iter_reversed = RChunksRev<'a, T>,
next(self) {
option::map!(self.slice, |slice| {
let at = slice.len().saturating_sub(self.chunk_size);
let (next, ret) = slice::split_at(slice, at);
self.slice = some_if_nonempty(next);
(ret, self)
})
},
next_back{
option::map!(self.slice, |slice| {
let rem = slice.len() % self.chunk_size;
let at = if rem == 0 { self.chunk_size } else { rem };
let (ret, next) = slice::split_at(slice, at);
self.slice = some_if_nonempty(next);
(ret, self)
})
},
fields = {slice, chunk_size},
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct RChunks<'a, T> {
slice: Option<&'a [T]>,
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for RChunks<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T];
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct RChunksRev<'a, T> {
slice: Option<&'a [T]>,
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for RChunksRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T];
}
impl<'a, T> RChunks<'a, T> {
rchunks_shared! {is_forward = true}
}
impl<'a, T> RChunksRev<'a, T> {
rchunks_shared! {is_forward = false}
}
#[track_caller]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn chunks_exact<T>(slice: &[T], chunk_size: usize) -> ChunksExact<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
let at = slice.len() - slice.len() % chunk_size;
let (slice, rem) = slice::split_at(slice, at);
ChunksExact {
slice,
rem,
chunk_size,
}
}
macro_rules! chunks_exact_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
item = &'a [T],
iter_forward = ChunksExact<'a, T>,
iter_reversed = ChunksExactRev<'a, T>,
next(self) {
if self.slice.is_empty() {
None
} else {
let (ret, next) = slice::split_at(self.slice, self.chunk_size);
self.slice = next;
Some((ret, self))
}
},
next_back {
if self.slice.is_empty() {
None
} else {
let at = self.slice.len() - self.chunk_size;
let (next, ret) = slice::split_at(self.slice, at);
self.slice = next;
Some((ret, self))
}
},
fields = {slice, rem, chunk_size},
}
pub const fn remainder(&self) -> &'a [T] {
self.rem
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct ChunksExact<'a, T> {
slice: &'a [T],
rem: &'a [T],
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for ChunksExact<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T];
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct ChunksExactRev<'a, T> {
slice: &'a [T],
rem: &'a [T],
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for ChunksExactRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T];
}
impl<'a, T> ChunksExact<'a, T> {
chunks_exact_shared! {is_forward = true}
}
impl<'a, T> ChunksExactRev<'a, T> {
chunks_exact_shared! {is_forward = false}
}
#[track_caller]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn rchunks_exact<T>(slice: &[T], chunk_size: usize) -> RChunksExact<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
let (rem, slice) = slice::split_at(slice, slice.len() % chunk_size);
RChunksExact {
slice,
rem,
chunk_size,
}
}
macro_rules! rchunks_exact_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
item = &'a [T],
iter_forward = RChunksExact<'a, T>,
iter_reversed = RChunksExactRev<'a, T>,
next(self) {
if self.slice.is_empty() {
None
} else {
let at = self.slice.len() - self.chunk_size;
let (next, ret) = slice::split_at(self.slice, at);
self.slice = next;
Some((ret, self))
}
},
next_back {
if self.slice.is_empty() {
None
} else {
let (ret, next) = slice::split_at(self.slice, self.chunk_size);
self.slice = next;
Some((ret, self))
}
},
fields = {slice, rem, chunk_size},
}
pub const fn remainder(&self) -> &'a [T] {
self.rem
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct RChunksExact<'a, T> {
slice: &'a [T],
rem: &'a [T],
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for RChunksExact<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T];
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct RChunksExactRev<'a, T> {
slice: &'a [T],
rem: &'a [T],
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for RChunksExactRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a [T];
}
impl<'a, T> RChunksExact<'a, T> {
rchunks_exact_shared! {is_forward = true}
}
impl<'a, T> RChunksExactRev<'a, T> {
rchunks_exact_shared! {is_forward = false}
}
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub use requires_rust_1_64::*;