use crate::list::{Iter, IterMut};
use crate::{ElemPool, IndexError, PieList};
use core::iter::Extend;
#[must_use]
pub struct PieViewMut<'a, T> {
pub(crate) list: &'a mut PieList<T>,
pub(crate) pool: &'a mut ElemPool<T>,
}
impl<'a, T> PieViewMut<'a, T> {
pub fn new(list: &'a mut PieList<T>, pool: &'a mut ElemPool<T>) -> Self {
Self { list, pool }
}
#[inline]
pub fn len(&self) -> usize {
self.list.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.list.is_empty()
}
#[inline]
pub fn push_back(&mut self, elt: T) {
self.list
.push_back(elt, self.pool)
.expect("Pool allocation failed");
}
#[inline]
pub fn push_front(&mut self, elt: T) {
self.list
.push_front(elt, self.pool)
.expect("Pool allocation failed");
}
#[inline]
pub fn pop_back(&mut self) -> Option<T> {
self.list.pop_back(self.pool)
}
#[inline]
pub fn pop_front(&mut self) -> Option<T> {
self.list.pop_front(self.pool)
}
#[inline]
pub fn front(&self) -> Option<&T> {
self.list.front(self.pool)
}
#[inline]
pub fn front_mut(&mut self) -> Option<&mut T> {
self.list.front_mut(self.pool)
}
#[inline]
pub fn back(&self) -> Option<&T> {
self.list.back(self.pool)
}
#[inline]
pub fn back_mut(&mut self) -> Option<&mut T> {
self.list.back_mut(self.pool)
}
#[inline]
pub fn clear(&mut self) {
self.list.clear(self.pool);
}
pub fn insert(&mut self, index: usize, element: T) -> Result<(), IndexError> {
if index == self.len() {
self.push_back(element);
Ok(())
} else {
let mut cursor = self.list.cursor_mut_at(index, self.pool)?;
cursor.insert_before(element, self.pool)
}
}
pub fn remove(&mut self, index: usize) -> Result<T, IndexError> {
let mut cursor = self.list.cursor_mut_at(index, self.pool)?;
Ok(cursor
.remove_current(self.pool)
.expect("Logic error: Cursor valid but no element"))
}
#[inline]
pub fn iter(&self) -> Iter<'_, T> {
self.list.iter(self.pool)
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
self.list.iter_mut(self.pool)
}
}
impl<'a, T> IntoIterator for PieViewMut<'a, T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.list.iter_mut(self.pool)
}
}
impl<'a, 'b, T> IntoIterator for &'b mut PieViewMut<'a, T> {
type Item = &'b mut T;
type IntoIter = IterMut<'b, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<'a, T> Extend<T> for PieViewMut<'a, T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for item in iter {
self.push_back(item);
}
}
}
#[cfg(test)]
mod tests {
use crate::{ElemPool, PieList};
#[test]
fn test_view_mut_push_pop() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
let mut view = list.view_mut(&mut pool);
view.push_back(10);
view.push_front(20); view.push_back(30);
assert_eq!(view.len(), 3);
assert!(!view.is_empty());
assert_eq!(view.pop_front(), Some(20));
assert_eq!(view.pop_back(), Some(30));
assert_eq!(view.pop_back(), Some(10));
assert!(view.is_empty());
view.clear(); }
#[test]
fn test_view_mut_references() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
let mut view = list.view_mut(&mut pool);
view.push_back(10);
view.push_back(20);
if let Some(front) = view.front_mut() {
*front = 11;
}
if let Some(back) = view.back_mut() {
*back = 22;
}
assert_eq!(view.front(), Some(&11));
assert_eq!(view.back(), Some(&22));
view.clear();
}
#[test]
fn test_view_mut_iteration() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
let mut view = list.view_mut(&mut pool);
view.extend([1, 2, 3]);
for item in &mut view {
*item *= 10;
}
let vec: Vec<_> = view.iter().copied().collect();
assert_eq!(vec, vec![10, 20, 30]);
let mut count = 0;
for _ in view {
count += 1;
}
assert_eq!(count, 3);
list.clear(&mut pool); }
#[test]
fn test_view_mut_insert_remove() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
let mut view = list.view_mut(&mut pool);
view.push_back(10);
view.push_back(30);
view.insert(1, 20).unwrap();
assert_eq!(view.len(), 3);
let removed = view.remove(1).unwrap();
assert_eq!(removed, 20);
assert_eq!(view.len(), 2);
view.clear();
}
#[test]
fn test_extend_from_vec() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
let mut view = list.view_mut(&mut pool);
view.extend(vec![1, 2, 3, 4, 5]);
assert_eq!(view.len(), 5);
let items: Vec<_> = view.iter().copied().collect();
assert_eq!(items, vec![1, 2, 3, 4, 5]);
view.clear();
}
#[test]
fn test_extend_from_range() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
let mut view = list.view_mut(&mut pool);
view.extend(10..15);
assert_eq!(view.len(), 5);
let items: Vec<_> = view.iter().copied().collect();
assert_eq!(items, vec![10, 11, 12, 13, 14]);
view.clear();
}
#[test]
fn test_extend_appends_to_existing() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
let mut view = list.view_mut(&mut pool);
view.push_back(0);
view.extend([1, 2]);
assert_eq!(view.len(), 3);
let items: Vec<_> = view.iter().copied().collect();
assert_eq!(items, vec![0, 1, 2]);
view.clear();
}
#[test]
fn test_extend_empty_iterator() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
let mut view = list.view_mut(&mut pool);
view.extend(core::iter::empty::<i32>());
assert!(view.is_empty());
view.clear();
}
}