use crate::list::Iter;
use crate::{ElemPool, PieList};
use core::cmp::Ordering;
use core::fmt;
#[must_use]
pub struct PieView<'a, T> {
pub(crate) list: &'a PieList<T>,
pub(crate) pool: &'a ElemPool<T>,
}
impl<'a, T> Clone for PieView<'a, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, T> Copy for PieView<'a, T> {}
impl<'a, T> PieView<'a, T> {
pub fn new(list: &'a PieList<T>, pool: &'a 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 front(&self) -> Option<&T> {
self.list.front(self.pool)
}
#[inline]
pub fn back(&self) -> Option<&T> {
self.list.back(self.pool)
}
#[inline]
pub fn iter(&self) -> Iter<'a, T> {
self.list.iter(self.pool)
}
}
impl<'a, T: fmt::Debug> fmt::Debug for PieView<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<'a, T: PartialEq> PartialEq for PieView<'a, T> {
fn eq(&self, other: &Self) -> bool {
if core::ptr::eq(self.list, other.list) && core::ptr::eq(self.pool, other.pool) {
return true;
}
self.iter().eq(other.iter())
}
}
impl<'a, T: Eq> Eq for PieView<'a, T> {}
impl<'a, T: PartialOrd> PartialOrd for PieView<'a, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.iter().partial_cmp(other.iter())
}
}
impl<'a, T: Ord> Ord for PieView<'a, T> {
fn cmp(&self, other: &Self) -> Ordering {
self.iter().cmp(other.iter())
}
}
impl<'a, T> IntoIterator for PieView<'a, T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[cfg(test)]
mod tests {
use crate::{ElemPool, PieList};
#[test]
fn test_view_debug_impl() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
list.push_back(10, &mut pool).unwrap();
list.push_back(20, &mut pool).unwrap();
list.push_back(30, &mut pool).unwrap();
let view = list.view(&pool);
let output = format!("{:?}", view);
assert_eq!(output, "[10, 20, 30]");
list.clear(&mut pool);
}
#[test]
fn test_view_iteration() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
list.push_back(1, &mut pool).unwrap();
list.push_back(2, &mut pool).unwrap();
list.push_back(3, &mut pool).unwrap();
let view = list.view(&pool);
let collected: Vec<&i32> = view.into_iter().collect();
assert_eq!(collected, vec![&1, &2, &3]);
let mut sum = 0;
for item in view {
sum += item;
}
assert_eq!(sum, 6);
list.clear(&mut pool);
}
#[test]
fn test_view_partial_eq() {
let mut pool1 = ElemPool::new();
let mut list1 = PieList::new(&mut pool1);
list1.push_back(1, &mut pool1).unwrap();
list1.push_back(2, &mut pool1).unwrap();
let mut pool2 = ElemPool::new();
let mut list2 = PieList::new(&mut pool2);
list2.push_back(1, &mut pool2).unwrap();
list2.push_back(2, &mut pool2).unwrap();
let mut pool3 = ElemPool::new();
let mut list3 = PieList::new(&mut pool3);
list3.push_back(1, &mut pool3).unwrap();
list3.push_back(99, &mut pool3).unwrap();
let view1 = list1.view(&pool1);
let view2 = list2.view(&pool2);
let view3 = list3.view(&pool3);
assert_eq!(view1, view2, "Lists with same content should be equal");
assert_ne!(view1, view3, "Lists with different content should not be equal");
list3.clear(&mut pool3);
list2.clear(&mut pool2);
list1.clear(&mut pool1);
}
#[test]
fn test_view_partial_ord() {
let mut pool = ElemPool::new();
let mut list1 = PieList::new(&mut pool);
list1.push_back(1, &mut pool).unwrap();
let mut list2 = PieList::new(&mut pool);
list2.push_back(2, &mut pool).unwrap();
let view1 = list1.view(&pool);
let view2 = list2.view(&pool);
assert!(view1 < view2);
assert!(view2 > view1);
list1.clear(&mut pool);
list2.clear(&mut pool);
}
#[test]
fn test_view_with_non_copy_types() {
let mut pool = ElemPool::new();
let mut list = PieList::new(&mut pool);
list.push_back("hello".to_string(), &mut pool).unwrap();
list.push_back("world".to_string(), &mut pool).unwrap();
let view = list.view(&pool);
let output = format!("{:?}", view);
assert_eq!(output, "[\"hello\", \"world\"]");
list.clear(&mut pool);
}
}