Skip to main content

trait_obj_list/iters/
iter.rs

1use crate::DynList;
2use crate::ptr;
3use crate::types::ListType;
4use crate::types::ListTypeRev;
5
6/// Immutable iterator for a [`DynList`].
7///
8/// The iterator is cloneable, letting you "save" the iterator's position in the list.
9pub struct Iter<'a, T, Typ>
10where
11	T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
12	Typ: ListType<T>,
13{
14	pub(crate) list: &'a DynList<T, Typ>,
15	pub(crate) offset: usize,
16	pub(crate) index: usize,
17	pub(crate) rev_offset: usize,
18	pub(crate) rev_index: usize,
19}
20impl<'a, T, Typ> Iterator for Iter<'a, T, Typ>
21where
22	T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
23	Typ: ListType<T>,
24{
25	type Item = &'a T;
26
27	fn next(&mut self) -> Option<Self::Item> {
28		if self.offset >= self.rev_offset {
29			debug_assert_eq!(self.offset, self.rev_offset);
30			debug_assert_eq!(self.index, self.rev_index);
31			return None;
32		}
33		let (p, size) = unsafe {
34			self.list
35				.typ
36				.read_entry(self.list.data.as_ptr(), self.offset, self.index)
37		};
38		self.offset += size;
39		self.index += 1;
40		Some(unsafe { &*p })
41	}
42
43	fn size_hint(&self) -> (usize, Option<usize>) {
44		let n = self.rev_index - self.index;
45		(n, Some(n))
46	}
47}
48impl<'a, T, Typ> DoubleEndedIterator for Iter<'a, T, Typ>
49where
50	T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
51	Typ: ListTypeRev<T>,
52{
53	fn next_back(&mut self) -> Option<Self::Item> {
54		if self.offset >= self.rev_offset {
55			debug_assert_eq!(self.offset, self.rev_offset);
56			debug_assert_eq!(self.index, self.rev_index);
57			return None;
58		}
59		let size = unsafe {
60			self.list
61				.typ
62				.prev_entry_size(self.list.data.as_ptr(), self.rev_offset, self.rev_index)
63		};
64		debug_assert!(
65			self.rev_offset >= size,
66			"SOUNDNESS BUG: prev_entry_size returned too big of a size. rev_offset = {} but prev_entry_size returned {}",
67			self.rev_offset,
68			size
69		);
70		self.rev_offset -= size;
71		self.rev_index -= 1;
72
73		let (p, s) = unsafe {
74			self.list
75				.typ
76				.read_entry(self.list.data.as_ptr(), self.rev_offset, self.rev_index)
77		};
78		debug_assert_eq!(s, size);
79
80		Some(unsafe { &*p })
81	}
82}
83impl<'a, T, Typ> ExactSizeIterator for Iter<'a, T, Typ>
84where
85	T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
86	Typ: ListType<T>,
87{
88}
89impl<'a, T, Typ> Clone for Iter<'a, T, Typ>
90where
91	T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
92	Typ: ListType<T>,
93{
94	fn clone(&self) -> Self {
95		Self {
96			list: self.list,
97			offset: self.offset,
98			index: self.index,
99			rev_index: self.index,
100			rev_offset: self.rev_offset,
101		}
102	}
103}