bitvec/array/
iter.rs

1#![doc = include_str!("../../doc/array/iter.md")]
2
3use core::{
4	fmt::{
5		self,
6		Debug,
7		Formatter,
8	},
9	iter::FusedIterator,
10	ops::Range,
11};
12
13use tap::Pipe;
14use wyz::comu::Const;
15
16use super::BitArray;
17use crate::{
18	mem,
19	order::BitOrder,
20	ptr::BitPtr,
21	slice::BitSlice,
22	view::BitViewSized,
23};
24
25/// [Original](https://doc.rust-lang.org/std/primitive.array.html#impl-IntoIterator)
26impl<A, O> IntoIterator for BitArray<A, O>
27where
28	A: BitViewSized,
29	O: BitOrder,
30{
31	type IntoIter = IntoIter<A, O>;
32	type Item = <IntoIter<A, O> as Iterator>::Item;
33
34	#[inline]
35	fn into_iter(self) -> Self::IntoIter {
36		IntoIter::new(self)
37	}
38}
39
40/// [Original](https://doc.rust-lang.org/std/primitive.array.html#impl-IntoIterator-1)
41#[cfg(not(tarpaulin_include))]
42impl<'a, A, O> IntoIterator for &'a BitArray<A, O>
43where
44	O: BitOrder,
45	A: 'a + BitViewSized,
46{
47	type IntoIter = <&'a BitSlice<A::Store, O> as IntoIterator>::IntoIter;
48	type Item = <&'a BitSlice<A::Store, O> as IntoIterator>::Item;
49
50	#[inline]
51	fn into_iter(self) -> Self::IntoIter {
52		self.as_bitslice().into_iter()
53	}
54}
55
56/// [Original](https://doc.rust-lang.org/std/primitive.array.html#impl-IntoIterator-2)
57#[cfg(not(tarpaulin_include))]
58impl<'a, A, O> IntoIterator for &'a mut BitArray<A, O>
59where
60	O: BitOrder,
61	A: 'a + BitViewSized,
62{
63	type IntoIter = <&'a mut BitSlice<A::Store, O> as IntoIterator>::IntoIter;
64	type Item = <&'a mut BitSlice<A::Store, O> as IntoIterator>::Item;
65
66	#[inline]
67	fn into_iter(self) -> Self::IntoIter {
68		self.as_mut_bitslice().into_iter()
69	}
70}
71
72#[derive(Clone)]
73#[doc = include_str!("../../doc/array/IntoIter.md")]
74pub struct IntoIter<A, O>
75where
76	A: BitViewSized,
77	O: BitOrder,
78{
79	/// The bit-array being iterated.
80	array: BitArray<A, O>,
81	/// The indices in `.array` that have not yet been yielded.
82	///
83	/// This range is always a strict subset of `0 .. self.array.len()`.
84	alive: Range<usize>,
85}
86
87impl<A, O> IntoIter<A, O>
88where
89	A: BitViewSized,
90	O: BitOrder,
91{
92	/// Converts a bit-array into its iterator.
93	///
94	/// The [`.into_iter()`] method on bit-arrays forwards to this. While
95	/// `BitArray` does deref to `&/mut BitSlice`, which also has
96	/// `.into_iter()`, this behavior has always been present alongside
97	/// `BitArray` and there is no legacy forwarding to preserve.
98	///
99	/// ## Original
100	///
101	/// [`IntoIter::new`](core::array::IntoIter::new)s
102	#[inline]
103	pub fn new(array: BitArray<A, O>) -> Self {
104		Self {
105			array,
106			alive: 0 .. mem::bits_of::<A>(),
107		}
108	}
109
110	/// Views the remaining unyielded bits in the iterator.
111	///
112	/// ## Original
113	///
114	/// [`IntoIter::as_slice`](core::array::IntoIter::as_slice)
115	#[inline]
116	pub fn as_bitslice(&self) -> &BitSlice<A::Store, O> {
117		unsafe { self.array.as_bitslice().get_unchecked(self.alive.clone()) }
118	}
119
120	#[inline]
121	#[cfg(not(tarpaulin_include))]
122	#[deprecated = "use `.as_bitslice()` instead"]
123	#[allow(missing_docs, clippy::missing_docs_in_private_items)]
124	pub fn as_slice(&self) -> &BitSlice<A::Store, O> {
125		self.as_bitslice()
126	}
127
128	/// Mutably views the remaining unyielded bits in the iterator.
129	///
130	/// ## Original
131	///
132	/// [`IntoIter::as_mut_slice`](core::array::IntoIter::as_mut_slice)
133	#[inline]
134	pub fn as_mut_bitslice(&mut self) -> &mut BitSlice<A::Store, O> {
135		unsafe {
136			self.array
137				.as_mut_bitslice()
138				.get_unchecked_mut(self.alive.clone())
139		}
140	}
141
142	#[inline]
143	#[cfg(not(tarpaulin_include))]
144	#[deprecated = "use `.as_bitslice_mut()` instead"]
145	#[allow(missing_docs, clippy::missing_docs_in_private_items)]
146	pub fn as_mut_slice(&mut self) -> &mut BitSlice<A::Store, O> {
147		self.as_mut_bitslice()
148	}
149
150	/// Gets a bit from the bit-array.
151	#[inline]
152	fn get(&self, index: usize) -> bool {
153		unsafe {
154			self.array
155				.as_raw_slice()
156				.pipe(BitPtr::<Const, A::Store, O>::from_slice)
157				.add(index)
158				.read()
159		}
160	}
161}
162
163#[cfg(not(tarpaulin_include))]
164impl<A, O> Debug for IntoIter<A, O>
165where
166	A: BitViewSized,
167	O: BitOrder,
168{
169	#[inline]
170	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
171		fmt.debug_tuple("IntoIter")
172			.field(&self.as_bitslice())
173			.finish()
174	}
175}
176
177impl<A, O> Iterator for IntoIter<A, O>
178where
179	A: BitViewSized,
180	O: BitOrder,
181{
182	type Item = bool;
183
184	easy_iter!();
185
186	#[inline]
187	fn next(&mut self) -> Option<Self::Item> {
188		self.alive.next().map(|idx| self.get(idx))
189	}
190
191	#[inline]
192	fn nth(&mut self, n: usize) -> Option<Self::Item> {
193		self.alive.nth(n).map(|idx| self.get(idx))
194	}
195}
196
197impl<A, O> DoubleEndedIterator for IntoIter<A, O>
198where
199	A: BitViewSized,
200	O: BitOrder,
201{
202	#[inline]
203	fn next_back(&mut self) -> Option<Self::Item> {
204		self.alive.next_back().map(|idx| self.get(idx))
205	}
206
207	#[inline]
208	fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
209		self.alive.nth_back(n).map(|idx| self.get(idx))
210	}
211}
212
213impl<A, O> ExactSizeIterator for IntoIter<A, O>
214where
215	A: BitViewSized,
216	O: BitOrder,
217{
218	#[inline]
219	fn len(&self) -> usize {
220		self.alive.len()
221	}
222}
223
224impl<A, O> FusedIterator for IntoIter<A, O>
225where
226	A: BitViewSized,
227	O: BitOrder,
228{
229}