imgref_iter/iter/windows/
ptr.rs

1use std::iter::FusedIterator;
2use std::ops::Range;
3use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
4use imgref::Img;
5use crate::iter::{IterPtr, IterPtrMut};
6use crate::{slice_ptr_len, slice_ptr_len_mut};
7
8#[derive(Clone, Eq, PartialEq, Debug)]
9pub struct IterWindowsPtr<T>(*const [T], usize, usize, Range<usize>);
10
11unsafe impl<T: Sync> Send for IterWindowsPtr<T> {}
12
13unsafe impl<T> Sync for IterWindowsPtr<T> {}
14
15impl<T> IterWindowsPtr<T> {
16	/// Creates a new [`IterWindowsPtr`]:
17	///
18	/// - `slice` is the slice that will be returned by the first iteration;
19	/// - `slice_stride` is the stride of `slice`;
20	/// - `iter_stride` is how far the slice will move each iteration;
21	/// - `len` is how many iterations
22	///
23	/// For example, for an iterator over rows, this would be:
24	///
25	/// - the first row of the image;
26	/// - `1`;
27	/// - the stride of the image;
28	/// - the height of the image
29	///
30	/// For an iterator over cols:
31	///
32	/// - the first column of the image;
33	/// - the stride of the image;
34	/// - `1`;
35	/// - the width of the image
36	///
37	/// # Safety
38	///
39	/// The provided slice must be valid for the lifetime of the returned
40	/// [`IterWindowsPtr`]. There must be at least `iter_stride` elements
41	/// available past the end of the provided slice.
42	///
43	/// # Panics
44	///
45	/// Panics if the slice does not start and end on an element.
46	#[inline]
47	pub unsafe fn new(slice: *const [T], slice_stride: usize, iter_stride: usize, len: usize) -> Self {
48		assert!(IterPtr::is_slice_perfect(slice_ptr_len(slice), slice_stride));
49		Self::new_unchecked(slice, slice_stride, iter_stride, len)
50	}
51
52	/// Same as `new`, but does not verify the slice length.
53	///
54	/// # Safety
55	///
56	/// All safety invariants of `new` must be upheld, and the slice must start
57	/// and end on an element.
58	#[inline]
59	pub unsafe fn new_unchecked(slice: *const [T], slice_stride: usize, iter_stride: usize, len: usize) -> Self {
60		Self(slice, slice_stride, iter_stride, 0..len)
61	}
62
63	/// Creates a new [`IterWindowsPtr`] over the rows of an [`Img`].
64	///
65	/// # Safety
66	///
67	/// The buffer must be valid for the lifetime of the returned iterator.
68	///
69	/// # Panics
70	///
71	/// Panics if the provided buffer has a width and height too large to fit in
72	/// its backing store.
73	#[inline]
74	pub unsafe fn rows<S: AsRef<[T]>>(buf: &Img<S>) -> Self {
75		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
76		let buf = buf.buf().as_ref() as *const [T];
77		Self::rows_ptr(Img::new_stride(buf, width, height, stride))
78	}
79
80	/// Creates a new [`IterWindowsPtr`] over the rows of an [`Img`].
81	///
82	/// # Safety
83	///
84	/// The buffer must be valid for the lifetime of the returned iterator.
85	///
86	/// # Panics
87	///
88	/// Panics if the provided buffer has a width and height too large to fit in
89	/// its backing store.
90	#[inline]
91	pub unsafe fn rows_ptr(buf: Img<*const [T]>) -> Self {
92		IterPtr::assert_slice_enough(buf);
93		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
94		let first_row = slice_from_raw_parts(buf.buf().cast::<T>(), width);
95		Self::new_unchecked(first_row, 1, stride, height)
96	}
97
98	/// Creates a new [`IterWindowsPtr`] over the cols of an [`Img`].
99	///
100	/// # Safety
101	///
102	/// The buffer must be valid for the lifetime of the returned iterator.
103	///
104	/// # Panics
105	///
106	/// Panics if the provided buffer has a width and height too large to fit in
107	/// its backing store.
108	#[inline]
109	pub unsafe fn cols<S: AsRef<[T]>>(buf: &Img<S>) -> Self {
110		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
111		let buf = buf.buf().as_ref() as *const [T];
112		Self::cols_ptr(Img::new_stride(buf, width, height, stride))
113	}
114
115	/// Creates a new [`IterWindowsPtr`] over the cols of an [`Img`].
116	///
117	/// # Safety
118	///
119	/// The buffer must be valid for the lifetime of the returned iterator.
120	///
121	/// # Panics
122	///
123	/// Panics if the provided buffer has a width and height too large to fit in
124	/// its backing store.
125	#[inline]
126	pub unsafe fn cols_ptr(buf: Img<*const [T]>) -> Self {
127		IterPtr::assert_slice_enough(buf);
128		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
129		let first_col = slice_from_raw_parts(buf.buf().cast::<T>(), stride * (height - 1) + 1);
130		Self::new_unchecked(first_col, buf.stride(), 1, width)
131	}
132
133	#[inline]
134	unsafe fn window(&self, offset: usize) -> *const [T] {
135		let data = self.0.cast::<T>().add(offset);
136		let len = slice_ptr_len(self.0);
137		slice_from_raw_parts(data, len)
138	}
139}
140
141impl<T> Iterator for IterWindowsPtr<T> {
142	type Item = IterPtr<T>;
143
144	#[inline]
145	fn next(&mut self) -> Option<Self::Item> {
146		self.3.next().map(|index| unsafe { IterPtr::new(self.window(index * self.2), self.1) })
147	}
148
149	#[inline]
150	fn size_hint(&self) -> (usize, Option<usize>) {
151		let len = self.len();
152		(len, Some(len))
153	}
154}
155
156impl<T> DoubleEndedIterator for IterWindowsPtr<T> {
157	#[inline]
158	fn next_back(&mut self) -> Option<Self::Item> {
159		self.3.next_back().map(|index| unsafe { IterPtr::new(self.window(index * self.2), self.1) })
160	}
161}
162
163impl<T> ExactSizeIterator for IterWindowsPtr<T> {
164	#[inline]
165	fn len(&self) -> usize {
166		self.3.len()
167	}
168}
169
170impl<T> FusedIterator for IterWindowsPtr<T> {}
171
172#[derive(Clone, Eq, PartialEq, Debug)]
173pub struct IterWindowsPtrMut<T>(*mut [T], usize, usize, Range<usize>);
174
175unsafe impl<T: Send> Send for IterWindowsPtrMut<T> {}
176
177unsafe impl<T> Sync for IterWindowsPtrMut<T> {}
178
179impl<T> IterWindowsPtrMut<T> {
180	/// Creates a new [`IterWindowsPtrMut`]:
181	///
182	/// - `slice` is the slice that will be returned by the first iteration;
183	/// - `slice_stride` is the stride of `slice`;
184	/// - `iter_stride` is how far the slice will move each iteration;
185	/// - `len` is how many iterations
186	///
187	/// For example, for an iterator over rows, this would be:
188	///
189	/// - the first row of the image;
190	/// - `1`;
191	/// - the stride of the image;
192	/// - the height of the image
193	///
194	/// For an iterator over cols:
195	///
196	/// - the first column of the image;
197	/// - the stride of the image;
198	/// - `1`;
199	/// - the width of the image
200	///
201	/// # Safety
202	///
203	/// The provided slice must be valid for the lifetime of the returned
204	/// [`IterWindowsPtrMut`]. There must be at least `iter_stride` elements
205	/// available past the end of the provided slice.
206	///
207	/// # Panics
208	///
209	/// Panics if the slice does not start and end on an element.
210	#[inline]
211	pub unsafe fn new(slice: *mut [T], slice_stride: usize, iter_stride: usize, len: usize) -> Self {
212		assert!(IterPtr::is_slice_perfect(slice_ptr_len_mut(slice), slice_stride));
213		Self::new_unchecked(slice, slice_stride, iter_stride, len)
214	}
215
216	/// Same as `new`, but does not verify the slice length.
217	///
218	/// # Safety
219	///
220	/// All safety invariants of `new` must be upheld, and the slice must start
221	/// and end on an element.
222	#[inline]
223	pub unsafe fn new_unchecked(slice: *mut [T], slice_stride: usize, iter_stride: usize, len: usize) -> Self {
224		Self(slice, slice_stride, iter_stride, 0..len)
225	}
226
227	/// Creates a new [`IterWindowsPtrMut`] over the rows of an [`Img`].
228	///
229	/// # Safety
230	///
231	/// The buffer must be valid for the lifetime of the returned iterator.
232	///
233	/// # Panics
234	///
235	/// Panics if the provided buffer has a width and height too large to fit in
236	/// its backing store.
237	#[inline]
238	pub unsafe fn rows<S: AsMut<[T]>>(buf: &mut Img<S>) -> Self {
239		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
240		let buf = buf.buf_mut().as_mut() as *mut [T];
241		Self::rows_ptr(Img::new_stride(buf, width, height, stride))
242	}
243
244	/// Creates a new [`IterWindowsPtrMut`] over the rows of an [`Img`].
245	///
246	/// # Safety
247	///
248	/// The buffer must be valid for the lifetime of the returned iterator.
249	///
250	/// # Panics
251	///
252	/// Panics if the provided buffer has a width and height too large to fit in
253	/// its backing store.
254	#[inline]
255	pub unsafe fn rows_ptr(buf: Img<*mut [T]>) -> Self {
256		IterPtrMut::assert_slice_enough(buf);
257		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
258		let first_row = slice_from_raw_parts_mut(buf.buf().cast::<T>(), width);
259		Self::new_unchecked(first_row, 1, stride, height)
260	}
261
262	/// Creates a new [`IterWindowsPtrMut`] over the cols of an [`Img`].
263	///
264	/// # Safety
265	///
266	/// The buffer must be valid for the lifetime of the returned iterator.
267	///
268	/// # Panics
269	///
270	/// Panics if the provided buffer has a width and height too large to fit in
271	/// its backing store.
272	#[inline]
273	pub unsafe fn cols<S: AsMut<[T]>>(buf: &mut Img<S>) -> Self {
274		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
275		let buf = buf.buf_mut().as_mut() as *mut [T];
276		Self::cols_ptr(Img::new_stride(buf, width, height, stride))
277	}
278
279	/// Creates a new [`IterWindowsPtrMut`] over the cols of an [`Img`].
280	///
281	/// # Safety
282	///
283	/// The buffer must be valid for the lifetime of the returned iterator.
284	///
285	/// # Panics
286	///
287	/// Panics if the provided buffer has a width and height too large to fit in
288	/// its backing store.
289	#[inline]
290	pub unsafe fn cols_ptr(buf: Img<*mut [T]>) -> Self {
291		IterPtrMut::assert_slice_enough(buf);
292		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
293		let first_col = slice_from_raw_parts_mut(buf.buf().cast::<T>(), stride * (height - 1) + 1);
294		Self::new_unchecked(first_col, buf.stride(), 1, width)
295	}
296
297	#[inline]
298	unsafe fn window(&self, offset: usize) -> *mut [T] {
299		let data = self.0.cast::<T>().add(offset);
300		let len = slice_ptr_len_mut(self.0);
301		slice_from_raw_parts_mut(data, len)
302	}
303}
304
305impl<T> Iterator for IterWindowsPtrMut<T> {
306	type Item = IterPtrMut<T>;
307
308	#[inline]
309	fn next(&mut self) -> Option<Self::Item> {
310		self.3.next().map(|index| unsafe { IterPtrMut::new(self.window(index * self.2), self.1) })
311	}
312
313	#[inline]
314	fn size_hint(&self) -> (usize, Option<usize>) {
315		let len = self.len();
316		(len, Some(len))
317	}
318}
319
320impl<T> DoubleEndedIterator for IterWindowsPtrMut<T> {
321	#[inline]
322	fn next_back(&mut self) -> Option<Self::Item> {
323		self.3.next_back().map(|index| unsafe { IterPtrMut::new(self.window(index * self.2), self.1) })
324	}
325}
326
327impl<T> ExactSizeIterator for IterWindowsPtrMut<T> {
328	#[inline]
329	fn len(&self) -> usize {
330		self.3.len()
331	}
332}
333
334impl<T> FusedIterator for IterWindowsPtrMut<T> {}