imgref_iter/iter/generic/
mod.rs

1use std::iter::FusedIterator;
2use std::marker::PhantomData;
3use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
4use imgref::Img;
5use crate::{slice_ptr_len, slice_ptr_len_mut};
6
7mod ptr;
8
9pub use ptr::*;
10
11#[repr(transparent)]
12#[derive(Copy, Clone, Eq, PartialEq, Debug)]
13pub struct Iter<'a, T>(IterPtr<T>, PhantomData<&'a [T]>);
14
15impl<'a, T> Iter<'a, T> {
16	/// Wraps an [`IterPtr`] in an [`Iter`].
17	///
18	/// # Safety
19	///
20	/// The [`IterPtr`] must be valid for reads and shared references.
21	#[inline]
22	pub unsafe fn wrap(ptr: IterPtr<T>) -> Self {
23		Self(ptr, PhantomData)
24	}
25
26	/// Creates a new [`Iter`] over the specified slice and stride.
27	///
28	/// # Panics
29	///
30	/// Panics if the given slice does not start and end at an element. That is,
31	/// both the first and last elements of the slice must be elements that
32	/// would be returned by this iterator. Do not include trailing stride.
33	#[inline]
34	pub fn new(slice: &[T], stride: usize) -> Self {
35		unsafe { Self::new_ptr(slice as *const [T], stride) }
36	}
37
38	/// Creates a new [`Iter`] over the specified slice and stride.
39	///
40	/// # Safety
41	///
42	/// UB if the given slice does not start and end at an element. That is,
43	/// both the first and last elements of the slice must be elements that
44	/// would be returned by this iterator. Do not include trailing stride.
45	#[inline]
46	pub unsafe fn new_unchecked(slice: &[T], stride: usize) -> Self {
47		Self::new_ptr_unchecked(slice as *const [T], stride)
48	}
49
50	/// Creates a new [`Iter`] over the specified slice and stride.
51	///
52	/// # Panics
53	///
54	/// Panics if the given slice does not start and end at an element. That is,
55	/// both the first and last elements of the slice must be elements that
56	/// would be returned by this iterator. Do not include trailing stride.
57	#[inline]
58	pub unsafe fn new_ptr(slice: *const [T], stride: usize) -> Self {
59		assert!(IterPtr::is_slice_perfect(slice_ptr_len(slice), stride));
60		Self::new_ptr_unchecked(slice, stride)
61	}
62
63	/// Creates a new [`Iter`] over the specified slice and stride.
64	///
65	/// # Safety
66	///
67	/// UB if the given slice does not start and end at an element. That is,
68	/// both the first and last elements of the slice must be elements that
69	/// would be returned by this iterator. Do not include trailing stride.
70	#[inline]
71	pub unsafe fn new_ptr_unchecked(slice: *const [T], stride: usize) -> Self {
72		Self::wrap(IterPtr::new(slice, stride))
73	}
74
75	/// Creates a new [`Iter`] over the specified buffer row.
76	///
77	/// # Panics
78	///
79	/// Panics if the given row is out of bounds.
80	#[inline]
81	pub fn row<S: AsRef<[T]>>(buf: &'a Img<S>, row: usize) -> Self {
82		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
83		let buf = buf.buf().as_ref() as *const [T];
84		unsafe { Self::row_ptr(Img::new_stride(buf, width, height, stride), row) }
85	}
86
87	/// Creates a new [`Iter`] over the specified buffer row.
88	///
89	/// # Safety
90	///
91	/// The provided buffer must be valid for reads.
92	///
93	/// # Panics
94	///
95	/// Panics if the given row is out of bounds.
96	#[inline]
97	pub unsafe fn row_ptr(buf: Img<*const [T]>, row: usize) -> Self {
98		assert!(row < buf.height());
99		Self::row_ptr_unchecked(buf, row)
100	}
101
102	/// Creates a new [`Iter`] over the specified buffer row.
103	///
104	/// # Safety
105	///
106	/// The provided buffer must be valid for reads, and the given row must not
107	/// be out of bounds.
108	#[inline]
109	pub unsafe fn row_ptr_unchecked(buf: Img<*const [T]>, row: usize) -> Self {
110		let slice = {
111			let data = buf.buf().cast::<T>().add(row * buf.stride());
112			let len = buf.width();
113			slice_from_raw_parts(data, len)
114		};
115
116		Self::new_ptr_unchecked(slice, 1)
117	}
118
119	/// Creates a new [`Iter`] over the specified buffer col.
120	///
121	/// # Panics
122	///
123	/// Panics if the given col is out of bounds.
124	#[inline]
125	pub fn col<S: AsRef<[T]>>(buf: &'a Img<S>, col: usize) -> Self {
126		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
127		let buf = buf.buf().as_ref() as *const [T];
128		unsafe { Self::col_ptr(Img::new_stride(buf, width, height, stride), col) }
129	}
130
131	/// Creates a new [`Iter`] over the specified buffer col.
132	///
133	/// # Safety
134	///
135	/// The provided buffer must be valid for reads.
136	///
137	/// # Panics
138	///
139	/// Panics if the given col is out of bounds.
140	#[inline]
141	pub unsafe fn col_ptr(buf: Img<*const [T]>, col: usize) -> Self {
142		assert!(col < buf.width());
143		Self::col_ptr_unchecked(buf, col)
144	}
145
146	/// Creates a new [`Iter`] over the specified buffer col.
147	///
148	/// # Safety
149	///
150	/// The provided buffer must be valid for reads, and the given col must not
151	/// be out of bounds.
152	#[inline]
153	pub unsafe fn col_ptr_unchecked(buf: Img<*const [T]>, col: usize) -> Self {
154		let slice = {
155			let data = buf.buf().cast::<T>().add(col);
156			let len = buf.stride() * (buf.height() - 1) + 1;
157			slice_from_raw_parts(data, len)
158		};
159
160		Self::new_ptr_unchecked(slice, buf.stride())
161	}
162
163	/// Converts this [`Iter`] into its inner [`IterPtr`].
164	pub fn into_inner(self) -> IterPtr<T> {
165		self.0
166	}
167}
168
169impl<'a, T> Iterator for Iter<'a, T> {
170	type Item = &'a T;
171
172	#[inline]
173	fn next(&mut self) -> Option<Self::Item> {
174		self.0.next().map(|ptr| unsafe { &*ptr })
175	}
176
177	#[inline]
178	fn size_hint(&self) -> (usize, Option<usize>) {
179		let len = self.len();
180		(len, Some(len))
181	}
182}
183
184impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
185	#[inline]
186	fn next_back(&mut self) -> Option<Self::Item> {
187		self.0.next_back().map(|ptr| unsafe { &*ptr })
188	}
189}
190
191impl<'a, T> ExactSizeIterator for Iter<'a, T> {
192	#[inline]
193	fn len(&self) -> usize {
194		self.0.len()
195	}
196}
197
198impl<'a, T> FusedIterator for Iter<'a, T> {}
199
200#[repr(transparent)]
201#[derive(Eq, PartialEq, Debug)]
202pub struct IterMut<'a, T>(IterPtrMut<T>, PhantomData<&'a mut [T]>);
203
204impl<'a, T> IterMut<'a, T> {
205	/// Wraps an [`IterPtrMut`] in an [`IterMut`].
206	///
207	/// # Safety
208	///
209	/// The [`IterPtrMut`] must be valid for reads and writes.
210	#[inline]
211	pub unsafe fn wrap(ptr: IterPtrMut<T>) -> Self {
212		Self(ptr, PhantomData)
213	}
214
215	/// Creates a new [`Iter`] over the specified slice and stride.
216	///
217	/// # Panics
218	///
219	/// Panics if the given slice does not start and end at an element. That is,
220	/// both the first and last elements of the slice must be elements that
221	/// would be returned by this iterator. Do not include trailing stride.
222	#[inline]
223	pub fn new(slice: &mut [T], stride: usize) -> Self {
224		unsafe { Self::new_ptr(slice as *mut [T], stride) }
225	}
226
227	/// Creates a new [`Iter`] over the specified slice and stride.
228	///
229	/// # Safety
230	///
231	/// UB if the given slice does not start and end at an element. That is,
232	/// both the first and last elements of the slice must be elements that
233	/// would be returned by this iterator. Do not include trailing stride.
234	#[inline]
235	pub unsafe fn new_unchecked(slice: &mut [T], stride: usize) -> Self {
236		Self::new_ptr_unchecked(slice as *mut [T], stride)
237	}
238
239	/// Creates a new [`Iter`] over the specified slice and stride.
240	///
241	/// # Panics
242	///
243	/// Panics if the given slice does not start and end at an element. That is,
244	/// both the first and last elements of the slice must be elements that
245	/// would be returned by this iterator. Do not include trailing stride.
246	#[inline]
247	pub unsafe fn new_ptr(slice: *mut [T], stride: usize) -> Self {
248		assert!(IterPtr::is_slice_perfect(slice_ptr_len_mut(slice), stride));
249		Self::new_ptr_unchecked(slice, stride)
250	}
251
252	/// Creates a new [`Iter`] over the specified slice and stride.
253	///
254	/// # Safety
255	///
256	/// UB if the given slice does not start and end at an element. That is,
257	/// both the first and last elements of the slice must be elements that
258	/// would be returned by this iterator. Do not include trailing stride.
259	#[inline]
260	pub unsafe fn new_ptr_unchecked(slice: *mut [T], stride: usize) -> Self {
261		Self::wrap(IterPtrMut::new(slice, stride))
262	}
263
264	/// Creates a new [`Iter`] over the specified buffer row.
265	///
266	/// # Panics
267	///
268	/// Panics if the given row is out of bounds.
269	#[inline]
270	pub fn row<S: AsMut<[T]>>(buf: &'a mut Img<S>, row: usize) -> Self {
271		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
272		let buf = buf.buf_mut().as_mut() as *mut [T];
273		unsafe { Self::row_ptr(Img::new_stride(buf, width, height, stride), row) }
274	}
275
276	/// Creates a new [`Iter`] over the specified buffer row.
277	///
278	/// # Safety
279	///
280	/// The provided buffer must be valid for reads.
281	///
282	/// # Panics
283	///
284	/// Panics if the given row is out of bounds.
285	#[inline]
286	pub unsafe fn row_ptr(buf: Img<*mut [T]>, row: usize) -> Self {
287		assert!(row < buf.height());
288		Self::row_ptr_unchecked(buf, row)
289	}
290
291	/// Creates a new [`Iter`] over the specified buffer row.
292	///
293	/// # Safety
294	///
295	/// The provided buffer must be valid for reads, and the given row must not
296	/// be out of bounds.
297	#[inline]
298	pub unsafe fn row_ptr_unchecked(buf: Img<*mut [T]>, row: usize) -> Self {
299		let slice = {
300			let data = buf.buf().cast::<T>().add(row * buf.stride());
301			let len = buf.width();
302			slice_from_raw_parts_mut(data, len)
303		};
304
305		Self::new_ptr_unchecked(slice, 1)
306	}
307
308	/// Creates a new [`Iter`] over the specified buffer col.
309	///
310	/// # Panics
311	///
312	/// Panics if the given col is out of bounds.
313	#[inline]
314	pub fn col<S: AsMut<[T]>>(buf: &'a mut Img<S>, col: usize) -> Self {
315		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
316		let buf = buf.buf_mut().as_mut() as *mut [T];
317		unsafe { Self::col_ptr(Img::new_stride(buf, width, height, stride), col) }
318	}
319
320	/// Creates a new [`Iter`] over the specified buffer col.
321	///
322	/// # Safety
323	///
324	/// The provided buffer must be valid for reads.
325	///
326	/// # Panics
327	///
328	/// Panics if the given col is out of bounds.
329	#[inline]
330	pub unsafe fn col_ptr(buf: Img<*mut [T]>, col: usize) -> Self {
331		assert!(col < buf.width());
332		Self::col_ptr_unchecked(buf, col)
333	}
334
335	/// Creates a new [`Iter`] over the specified buffer col.
336	///
337	/// # Safety
338	///
339	/// The provided buffer must be valid for reads, and the given col must not
340	/// be out of bounds.
341	#[inline]
342	pub unsafe fn col_ptr_unchecked(buf: Img<*mut [T]>, col: usize) -> Self {
343		let slice = {
344			let data = buf.buf().cast::<T>().add(col);
345			let len = buf.stride() * (buf.height() - 1) + 1;
346			slice_from_raw_parts_mut(data, len)
347		};
348
349		Self::new_ptr_unchecked(slice, buf.stride())
350	}
351
352	/// Converts this [`IterMut`] into its inner [`IterPtrMut`].
353	pub fn into_inner(self) -> IterPtrMut<T> {
354		self.0
355	}
356}
357
358impl<'a, T> Iterator for IterMut<'a, T> {
359	type Item = &'a mut T;
360
361	fn next(&mut self) -> Option<Self::Item> {
362		self.0.next().map(|ptr| unsafe { &mut *ptr })
363	}
364
365	fn size_hint(&self) -> (usize, Option<usize>) {
366		let len = self.len();
367		(len, Some(len))
368	}
369}
370
371impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
372	fn next_back(&mut self) -> Option<Self::Item> {
373		self.0.next_back().map(|ptr| unsafe { &mut *ptr })
374	}
375}
376
377impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
378	fn len(&self) -> usize {
379		self.0.len()
380	}
381}
382
383impl<'a, T> FusedIterator for IterMut<'a, T> {}