#![expect(clippy::explicit_auto_deref, reason = "autoderef isn't happening")]
#![expect(
clippy::mem_replace_with_default,
reason = "Default::default() can't be used in const"
)]
use crate::{
iter::{ConstIntoIter, IntoIterWrapper, IsIteratorKind, IsStdKind},
option, slice,
};
use core::mem::ManuallyDrop;
impl<'a, T, const N: usize> ConstIntoIter for &'a [T; N] {
type Kind = IsStdKind;
type IntoIter = Iter<'a, T>;
type Item = &'a T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T, const N: usize> ConstIntoIter for &&'a [T; N] {
type Kind = IsStdKind;
type IntoIter = Iter<'a, T>;
type Item = &'a T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T, const N: usize> IntoIterWrapper<&'a [T; N], IsStdKind> {
pub const fn const_into_iter(self) -> Iter<'a, T> {
Iter {
slice: ManuallyDrop::into_inner(self.iter) as &[T],
}
}
}
impl<'a, T, const N: usize> IntoIterWrapper<&&'a [T; N], IsStdKind> {
pub const fn const_into_iter(self) -> Iter<'a, T> {
Iter {
slice: (*ManuallyDrop::into_inner(self.iter)) as &[T],
}
}
}
impl<'a, T> ConstIntoIter for &'a [T] {
type Kind = IsStdKind;
type IntoIter = Iter<'a, T>;
type Item = &'a T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> IntoIterWrapper<&'a [T], IsStdKind> {
pub const fn const_into_iter(self) -> Iter<'a, T> {
Iter {
slice: ManuallyDrop::into_inner(self.iter),
}
}
}
impl<'a, T> ConstIntoIter for &&'a [T] {
type Kind = IsStdKind;
type IntoIter = Iter<'a, T>;
type Item = &'a T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> IntoIterWrapper<&&'a [T], IsStdKind> {
pub const fn const_into_iter(self) -> Iter<'a, T> {
Iter {
slice: *ManuallyDrop::into_inner(self.iter),
}
}
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn iter<T>(slice: &[T]) -> Iter<'_, T> {
Iter { slice }
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct Iter<'a, T> {
slice: &'a [T],
}
impl<'a, T> ConstIntoIter for Iter<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a T;
const ITEMS_NEED_DROP: bool = false;
}
macro_rules! iter_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
item = &'a T,
iter_forward = Iter<'a, T>,
iter_reversed = IterRev<'a, T>,
next(self) {
if let [elem, rem @ ..] = self.slice {
self.slice = rem;
Some(elem)
} else {
None
}
},
next_back {
if let [rem @ .., elem] = self.slice {
self.slice = rem;
Some(elem)
} else {
None
}
},
fields = {slice},
}
pub const fn as_slice(&self) -> &'a [T] {
self.slice
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct IterRev<'a, T> {
slice: &'a [T],
}
impl<'a, T> ConstIntoIter for IterRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> Iter<'a, T> {
iter_shared! {is_forward = true}
}
impl<'a, T> IterRev<'a, T> {
iter_shared! {is_forward = false}
}
impl<'a, T, const N: usize> ConstIntoIter for &'a mut [T; N] {
type Kind = IsStdKind;
type IntoIter = IterMut<'a, T>;
type Item = &'a mut T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T, const N: usize> ConstIntoIter for &'a mut &mut [T; N] {
type Kind = IsStdKind;
type IntoIter = IterMut<'a, T>;
type Item = &'a mut T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T, const N: usize> IntoIterWrapper<&'a mut [T; N], IsStdKind> {
pub const fn const_into_iter(self) -> IterMut<'a, T> {
IterMut {
slice: ManuallyDrop::into_inner(self.iter) as &mut [T],
}
}
}
impl<'a, T, const N: usize> IntoIterWrapper<&'a mut &mut [T; N], IsStdKind> {
pub const fn const_into_iter(self) -> IterMut<'a, T> {
IterMut {
slice: (*ManuallyDrop::into_inner(self.iter)) as &mut [T],
}
}
}
impl<'a, T> ConstIntoIter for &'a mut [T] {
type Kind = IsStdKind;
type IntoIter = IterMut<'a, T>;
type Item = &'a mut T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> IntoIterWrapper<&'a mut [T], IsStdKind> {
pub const fn const_into_iter(self) -> IterMut<'a, T> {
IterMut {
slice: ManuallyDrop::into_inner(self.iter),
}
}
}
impl<'a, T> ConstIntoIter for &'a mut &mut [T] {
type Kind = IsStdKind;
type IntoIter = IterMut<'a, T>;
type Item = &'a mut T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> IntoIterWrapper<&'a mut &mut [T], IsStdKind> {
pub const fn const_into_iter(self) -> IterMut<'a, T> {
IterMut {
slice: &mut **ManuallyDrop::into_inner(self.iter),
}
}
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn iter_mut<T>(slice: &mut [T]) -> IterMut<'_, T> {
IterMut { slice }
}
macro_rules! iter_mut_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
is_copy = false,
item = &'a mut T,
iter_forward = IterMut<'a, T>,
iter_reversed = IterMutRev<'a, T>,
next(self) {
if let [elem, rem @ ..] = core::mem::replace(&mut self.slice, &mut []) {
self.slice = rem;
Some(elem)
} else {
None
}
},
next_back {
if let [rem @ .., elem] = core::mem::replace(&mut self.slice, &mut []) {
self.slice = rem;
Some(elem)
} else {
None
}
},
fields = {slice},
}
pub const fn as_slice(&self) -> &[T] {
self.slice
}
pub const fn as_mut_slice(&mut self) -> &mut [T] {
self.slice
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct IterMut<'a, T> {
slice: &'a mut [T],
}
impl<'a, T> ConstIntoIter for IterMut<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a mut T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> ConstIntoIter for IterMutRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a mut T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> IterMut<'a, T> {
iter_mut_shared! {is_forward = true}
}
impl<'a, T> IterMutRev<'a, T> {
iter_mut_shared! {is_forward = false}
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct IterMutRev<'a, T> {
slice: &'a mut [T],
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn iter_copied<T: Copy>(slice: &[T]) -> IterCopied<'_, T> {
IterCopied { slice }
}
macro_rules! iter_copied_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
item = T,
iter_forward = IterCopied<'a, T>,
iter_reversed = IterCopiedRev<'a, T>,
next(self) {
if let [elem, rem @ ..] = self.slice {
self.slice = rem;
Some(*elem)
} else {
None
}
},
next_back {
if let [rem @ .., elem] = self.slice {
self.slice = rem;
Some(*elem)
} else {
None
}
},
fields = {slice},
}
pub const fn as_slice(&self) -> &'a [T] {
self.slice
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct IterCopied<'a, T> {
slice: &'a [T],
}
impl<'a, T> ConstIntoIter for IterCopied<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = T;
const ITEMS_NEED_DROP: bool = false;
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct IterCopiedRev<'a, T> {
slice: &'a [T],
}
impl<'a, T> ConstIntoIter for IterCopiedRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = T;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T: Copy> IterCopied<'a, T> {
iter_copied_shared! {is_forward = true}
}
impl<'a, T: Copy> IterCopiedRev<'a, T> {
iter_copied_shared! {is_forward = false}
}
mod requires_rust_1_64 {
use super::*;
#[inline(always)]
pub(crate) const fn some_if_nonempty<T>(slice: &[T]) -> Option<&[T]> {
match slice {
[] => None,
_ => Some(slice),
}
}
#[inline(always)]
pub(crate) const fn some_if_nonempty_mut<T>(slice: &mut [T]) -> Option<&mut [T]> {
match slice {
[] => None,
_ => 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)
}
},
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)
}
},
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];
const ITEMS_NEED_DROP: bool = false;
}
#[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];
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> Windows<'a, T> {
windows_shared! {is_forward = true}
}
impl<'a, T> WindowsRev<'a, T> {
windows_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
})
},
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
})
},
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];
const ITEMS_NEED_DROP: bool = false;
}
#[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];
const ITEMS_NEED_DROP: bool = false;
}
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 chunks_mut<T>(slice: &mut [T], chunk_size: usize) -> ChunksMut<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
ChunksMut {
slice: some_if_nonempty_mut(slice),
chunk_size,
}
}
macro_rules! chunks_mut_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
is_copy = false,
item = &'a mut [T],
iter_forward = ChunksMut<'a, T>,
iter_reversed = ChunksMutRev<'a, T>,
next(self) {
option::map!(self.slice.take(), |slice| {
let (ret, next) = slice::split_at_mut(slice, self.chunk_size);
self.slice = some_if_nonempty_mut(next);
ret
})
},
next_back{
option::map!(self.slice.take(), |slice| {
let at = (slice.len() - 1) / self.chunk_size * self.chunk_size;
let (next, ret) = slice::split_at_mut(slice, at);
self.slice = some_if_nonempty_mut(next);
ret
})
},
fields = {slice, chunk_size},
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct ChunksMut<'a, T> {
slice: Option<&'a mut [T]>,
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for ChunksMut<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a mut [T];
const ITEMS_NEED_DROP: bool = false;
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct ChunksMutRev<'a, T> {
slice: Option<&'a mut [T]>,
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for ChunksMutRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a mut [T];
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> ChunksMut<'a, T> {
chunks_mut_shared! {is_forward = true}
}
impl<'a, T> ChunksMutRev<'a, T> {
chunks_mut_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
})
},
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
})
},
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];
const ITEMS_NEED_DROP: bool = false;
}
#[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];
const ITEMS_NEED_DROP: bool = false;
}
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 rchunks_mut<T>(slice: &mut [T], chunk_size: usize) -> RChunksMut<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
RChunksMut {
slice: some_if_nonempty_mut(slice),
chunk_size,
}
}
macro_rules! rchunks_mut_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
is_copy = false,
item = &'a mut [T],
iter_forward = RChunksMut<'a, T>,
iter_reversed = RChunksMutRev<'a, T>,
next(self) {
option::map!(self.slice.take(), |slice| {
let at = slice.len().saturating_sub(self.chunk_size);
let (next, ret) = slice::split_at_mut(slice, at);
self.slice = some_if_nonempty_mut(next);
ret
})
},
next_back{
option::map!(self.slice.take(), |slice| {
let rem = slice.len() % self.chunk_size;
let at = if rem == 0 { self.chunk_size } else { rem };
let (ret, next) = slice::split_at_mut(slice, at);
self.slice = some_if_nonempty_mut(next);
ret
})
},
fields = {slice, chunk_size},
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct RChunksMut<'a, T> {
slice: Option<&'a mut [T]>,
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for RChunksMut<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a mut [T];
const ITEMS_NEED_DROP: bool = false;
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct RChunksMutRev<'a, T> {
slice: Option<&'a mut [T]>,
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for RChunksMutRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a mut [T];
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> RChunksMut<'a, T> {
rchunks_mut_shared! {is_forward = true}
}
impl<'a, T> RChunksMutRev<'a, T> {
rchunks_mut_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)
}
},
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)
}
},
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];
const ITEMS_NEED_DROP: bool = false;
}
#[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];
const ITEMS_NEED_DROP: bool = false;
}
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)
}
},
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)
}
},
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];
const ITEMS_NEED_DROP: bool = false;
}
#[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];
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> RChunksExact<'a, T> {
rchunks_exact_shared! {is_forward = true}
}
impl<'a, T> RChunksExactRev<'a, T> {
rchunks_exact_shared! {is_forward = false}
}
#[track_caller]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn chunks_exact_mut<T>(slice: &mut [T], chunk_size: usize) -> ChunksExactMut<'_, 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_mut(slice, at);
ChunksExactMut {
slice,
rem,
chunk_size,
}
}
macro_rules! chunks_exact_mut_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
is_copy = false,
item = &'a mut [T],
iter_forward = ChunksExactMut<'a, T>,
iter_reversed = ChunksExactMutRev<'a, T>,
next(self) {
if self.slice.is_empty() {
None
} else {
let (ret, next) = slice::split_at_mut(self.take_slice(), self.chunk_size);
self.slice = next;
Some(ret)
}
},
next_back {
if self.slice.is_empty() {
None
} else {
let at = self.slice.len() - self.chunk_size;
let (next, ret) = slice::split_at_mut(self.take_slice(), at);
self.slice = next;
Some(ret)
}
},
fields = {slice, rem, chunk_size},
}
const fn take_slice(&mut self) -> &'a mut [T] {
core::mem::replace(&mut self.slice, &mut [])
}
pub const fn into_remainder(self) -> &'a mut [T] {
self.rem
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct ChunksExactMut<'a, T> {
slice: &'a mut [T],
rem: &'a mut [T],
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for ChunksExactMut<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a mut [T];
const ITEMS_NEED_DROP: bool = false;
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct ChunksExactMutRev<'a, T> {
slice: &'a mut [T],
rem: &'a mut [T],
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for ChunksExactMutRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a mut [T];
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> ChunksExactMut<'a, T> {
chunks_exact_mut_shared! {is_forward = true}
}
impl<'a, T> ChunksExactMutRev<'a, T> {
chunks_exact_mut_shared! {is_forward = false}
}
#[track_caller]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn rchunks_exact_mut<T>(
slice: &mut [T],
chunk_size: usize,
) -> RChunksExactMut<'_, T> {
assert!(chunk_size != 0, "chunk size must be non-zero");
let (rem, slice) = slice::split_at_mut(slice, slice.len() % chunk_size);
RChunksExactMut {
slice,
rem,
chunk_size,
}
}
macro_rules! rchunks_exact_mut_shared {
(is_forward = $is_forward:ident) => {
iterator_shared! {
is_forward = $is_forward,
is_copy = false,
item = &'a mut [T],
iter_forward = RChunksExactMut<'a, T>,
iter_reversed = RChunksExactMutRev<'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_mut(self.take_slice(), at);
self.slice = next;
Some(ret)
}
},
next_back {
if self.slice.is_empty() {
None
} else {
let (ret, next) = slice::split_at_mut(self.take_slice(), self.chunk_size);
self.slice = next;
Some(ret)
}
},
fields = {slice, rem, chunk_size},
}
const fn take_slice(&mut self) -> &'a mut [T] {
core::mem::replace(&mut self.slice, &mut [])
}
pub const fn into_remainder(self) -> &'a mut [T] {
self.rem
}
};
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct RChunksExactMut<'a, T> {
slice: &'a mut [T],
rem: &'a mut [T],
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for RChunksExactMut<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a mut [T];
const ITEMS_NEED_DROP: bool = false;
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct RChunksExactMutRev<'a, T> {
slice: &'a mut [T],
rem: &'a mut [T],
chunk_size: usize,
}
impl<'a, T> ConstIntoIter for RChunksExactMutRev<'a, T> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a mut [T];
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, T> RChunksExactMut<'a, T> {
rchunks_exact_mut_shared! {is_forward = true}
}
impl<'a, T> RChunksExactMutRev<'a, T> {
rchunks_exact_mut_shared! {is_forward = false}
}
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub use requires_rust_1_64::*;