use core::{fmt, iter::FusedIterator, mem, slice};
pub struct IterMut<'a, T> {
i1: slice::IterMut<'a, T>,
i2: slice::IterMut<'a, T>,
}
impl<'a, T> IterMut<'a, T> {
pub(super) fn new(i1: slice::IterMut<'a, T>, i2: slice::IterMut<'a, T>) -> Self {
Self { i1, i2 }
}
pub fn into_slices(self) -> (&'a mut [T], &'a mut [T]) {
(self.i1.into_slice(), self.i2.into_slice())
}
pub fn as_slices(&self) -> (&[T], &[T]) {
(self.i1.as_slice(), self.i2.as_slice())
}
}
impl<T: fmt::Debug> fmt::Debug for IterMut<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("IterMut")
.field(&self.i1.as_slice())
.field(&self.i2.as_slice())
.finish()
}
}
#[rustversion::since(1.70)]
impl<T> Default for IterMut<'_, T> {
fn default() -> Self {
IterMut {
i1: Default::default(),
i2: Default::default(),
}
}
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
#[inline]
fn next(&mut self) -> Option<&'a mut T> {
match self.i1.next() {
Some(val) => Some(val),
None => {
mem::swap(&mut self.i1, &mut self.i2);
self.i1.next()
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
fn fold<Acc, F>(self, accum: Acc, mut f: F) -> Acc
where
F: FnMut(Acc, Self::Item) -> Acc,
{
let accum = self.i1.fold(accum, &mut f);
self.i2.fold(accum, &mut f)
}
#[inline]
fn last(mut self) -> Option<&'a mut T> {
self.next_back()
}
}
impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a mut T> {
match self.i2.next_back() {
Some(val) => Some(val),
None => {
mem::swap(&mut self.i1, &mut self.i2);
self.i2.next_back()
}
}
}
fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc
where
F: FnMut(Acc, Self::Item) -> Acc,
{
let accum = self.i2.rfold(accum, &mut f);
self.i1.rfold(accum, &mut f)
}
}
impl<T> ExactSizeIterator for IterMut<'_, T> {
fn len(&self) -> usize {
self.i1.len() + self.i2.len()
}
}
impl<T> FusedIterator for IterMut<'_, T> {}
#[cfg(test)]
mod tests {
use crate::{typenum::U5, GenericArrayDeque};
#[test]
fn into_slices_allows_mutation() {
let mut deque = GenericArrayDeque::<_, U5>::new();
for value in 0..5 {
assert!(deque.push_back(value).is_none());
}
assert_eq!(deque.pop_front(), Some(0));
assert!(deque.push_back(5).is_none());
let mut iter = deque.iter_mut();
assert_eq!(iter.next().map(|v| *v), Some(1));
let (front, back) = iter.into_slices();
front[0] = 10;
if let Some(last) = back.first_mut() {
*last = 50;
}
assert_eq!(deque[0], 1);
assert_eq!(deque[1], 10);
assert_eq!(deque[4], 50);
}
#[test]
fn as_slices_reflect_remaining_segments() {
let mut deque = GenericArrayDeque::<_, U5>::new();
for value in 0..5 {
assert!(deque.push_back(value).is_none());
}
assert_eq!(deque.pop_front(), Some(0));
assert!(deque.push_back(5).is_none());
let mut iter = deque.iter_mut();
iter.next();
let (front, back) = iter.as_slices();
assert_eq!(front, &[2, 3, 4]);
assert_eq!(back, &[5]);
}
#[test]
fn fold_and_rfold_visit_all_items() {
let mut deque = GenericArrayDeque::<_, U5>::new();
for value in 0..5 {
assert!(deque.push_back(value).is_none());
}
{
let sum = deque.iter_mut().fold(0, |acc, item| acc + *item);
assert_eq!(sum, 10);
}
{
let sum = deque.iter_mut().rfold(0, |acc, item| acc + *item);
assert_eq!(sum, 10);
}
}
#[test]
fn size_hint_tracks_progress() {
let mut deque = GenericArrayDeque::<_, U5>::new();
for value in 0..5 {
assert!(deque.push_back(value).is_none());
}
let mut iter = deque.iter_mut();
assert_eq!(iter.size_hint(), (5, Some(5)));
iter.next();
assert_eq!(iter.size_hint(), (4, Some(4)));
iter.next_back();
assert_eq!(iter.size_hint(), (3, Some(3)));
}
#[test]
fn last_allows_mutating_tail() {
let mut deque = GenericArrayDeque::<_, U5>::new();
for value in 0..5 {
assert!(deque.push_back(value).is_none());
}
if let Some(last) = deque.iter_mut().last() {
*last = 99;
}
assert_eq!(deque[4], 99);
}
#[rustversion::since(1.70)]
#[test]
fn default_is_empty() {
use super::IterMut;
let iter: IterMut<'static, u8> = Default::default();
assert_eq!(iter.len(), 0);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
}