imgref_iter/iter/generic/
ptr.rs

1use std::cmp::min;
2use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
3use imgref::Img;
4use crate::{slice_ptr_len, slice_ptr_len_mut};
5
6#[derive(Copy, Clone, Eq, PartialEq, Debug)]
7pub struct IterPtr<T>(*const [T], usize);
8
9unsafe impl<T: Sync> Send for IterPtr<T> {}
10
11unsafe impl<T> Sync for IterPtr<T> {}
12
13impl IterPtr<()> {
14	/// This crate's iterators are double-ended, so there must be an element on
15	/// both sides of the slice.
16	///
17	/// Even if they weren't, trailing stride is not even guaranteed, meaning
18	/// that relying on it would be a mistake. Offsetting into it would be UB.
19	/// Instead we just rely on elements from first to last existing, and
20	/// everything around them is forbidden territory.
21	#[doc(hidden)]
22	#[inline(always)]
23	pub(crate) fn is_slice_perfect(len: usize, stride: usize) -> bool {
24		len == 0 || stride == 1 || len % stride == 1
25	}
26
27	/// It's possible to construct `Img`s with any dimensions over any slice,
28	/// which means the slice might not have enough elements, even if the `Img`
29	/// says it does.
30	///
31	/// If the slice has enough elements, does nothing. Else, panics with a
32	/// descriptive message.
33	#[doc(hidden)]
34	#[inline(always)]
35	pub(crate) fn assert_slice_enough<T>(img: Img<*const [T]>) {
36		let (width, height, stride) = (img.width(), img.height(), img.stride());
37		let needed = stride * (height - 1) + width;
38		let got = unsafe { slice_ptr_len(*img.buf()) };
39
40		if got < needed {
41			panic!("image (with width {width}, height {height} and stride {stride}) backing buffer too short; needed {needed} elements, but only got {got}");
42		} else if width > stride {
43			panic!("image (with width {width}, height {height} and stride {stride}) width is greater than stride")
44		}
45	}
46}
47
48impl<T> IterPtr<T> {
49	/// Creates a new [`IterPtr`] over the specified slice and stride.
50	///
51	/// # Safety
52	///
53	/// The given slice must outlive this [`IterPtr`].
54	///
55	/// # Panics
56	///
57	/// Panics if the given slice does not start and end at an element. That is,
58	/// both the first and last elements of the slice must be elements that
59	/// would be returned by this iterator. Do not include trailing stride.
60	#[inline]
61	pub unsafe fn new(slice: *const [T], stride: usize) -> Self {
62		assert!(IterPtr::is_slice_perfect(slice_ptr_len(slice), stride));
63		Self::new_unchecked(slice, stride)
64	}
65
66	/// Creates a new [`IterPtr`] over the specified slice and stride.
67	///
68	/// # Safety
69	///
70	/// The given slice must outlive this [`IterPtr`].
71	///
72	/// UB if the given slice does not start and end at an element. That is,
73	/// both the first and last elements of the slice must be elements that
74	/// would be returned by this iterator. Do not include trailing stride.
75	#[inline]
76	pub unsafe fn new_unchecked(slice: *const [T], stride: usize) -> Self {
77		Self(slice, stride)
78	}
79
80	/// Creates a new [`IterPtr`] over the specified slice and stride.
81	///
82	/// # Safety
83	///
84	/// The given slice must outlive this [`IterPtr`].
85	///
86	/// # Panics
87	///
88	/// Panics if the given slice does not start and end at an element. That is,
89	/// both the first and last elements of the slice must be elements that
90	/// would be returned by this iterator. Do not include trailing stride.
91	#[inline]
92	pub unsafe fn new_slice(slice: &[T], stride: usize) -> Self {
93		Self::new(slice as *const [T], stride)
94	}
95
96	/// Creates a new [`IterPtr`] over the specified slice and stride.
97	///
98	/// # Safety
99	///
100	/// The given slice must outlive this [`IterPtr`].
101	///
102	/// UB if the given slice does not start and end at an element. That is,
103	/// both the first and last elements of the slice must be elements that
104	/// would be returned by this iterator. Do not include trailing stride.
105	#[inline]
106	pub unsafe fn new_slice_unchecked(slice: &[T], stride: usize) -> Self {
107		Self::new_unchecked(slice as *const [T], stride)
108	}
109
110	/// Creates a new [`IterPtr`] over the specified buffer row.
111	///
112	/// # Safety
113	///
114	/// The given buffer must outlive this [`IterPtr`].
115	///
116	/// # Panics
117	///
118	/// Panics if the given row is out of bounds.
119	#[inline]
120	pub unsafe fn row<S: AsRef<[T]>>(buf: &Img<S>, row: usize) -> Self {
121		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
122		let buf = buf.buf().as_ref() as *const [T];
123		Self::row_ptr(Img::new_stride(buf, width, height, stride), row)
124	}
125
126	/// Creates a new [`IterPtr`] over the specified buffer row.
127	///
128	/// # Safety
129	///
130	/// The given buffer must outlive this [`IterPtr`].
131	///
132	/// # Panics
133	///
134	/// Panics if the provided buffer has a width and height too large to fit in
135	/// its backing store.
136	///
137	/// Panics if the given row is out of bounds.
138	#[inline]
139	pub unsafe fn row_ptr(buf: Img<*const [T]>, row: usize) -> Self {
140		IterPtr::assert_slice_enough(buf);
141		assert!(row < buf.height());
142		Self::row_ptr_unchecked(buf, row)
143	}
144
145	/// Creates a new [`IterPtr`] over the specified buffer row.
146	///
147	/// # Safety
148	///
149	/// The given slice must outlive this [`IterPtr`].
150	///
151	/// The given row must not be out of bounds.
152	#[inline]
153	pub unsafe fn row_ptr_unchecked(buf: Img<*const [T]>, row: usize) -> Self {
154		let slice = {
155			let data = buf.buf().cast::<T>().add(row * buf.stride());
156			let len = buf.width();
157			slice_from_raw_parts(data, len)
158		};
159
160		Self::new_unchecked(slice, 1)
161	}
162
163	/// Creates a new [`IterPtr`] over the specified buffer col.
164	///
165	/// # Safety
166	///
167	/// The given buffer must outlive this [`IterPtr`].
168	///
169	/// # Panics
170	///
171	/// Panics if the given col is out of bounds.
172	#[inline]
173	pub unsafe fn col<S: AsRef<[T]>>(buf: &Img<S>, col: usize) -> Self {
174		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
175		let buf = buf.buf().as_ref() as *const [T];
176		Self::col_ptr(Img::new_stride(buf, width, height, stride), col)
177	}
178
179	/// Creates a new [`IterPtr`] over the specified buffer col.
180	///
181	/// # Safety
182	///
183	/// The given slice must outlive this [`IterPtr`].
184	///
185	/// # Panics
186	///
187	/// Panics if the provided buffer has a width and height too large to fit in
188	/// its backing store.
189	///
190	/// Panics if the given col is out of bounds.
191	#[inline]
192	pub unsafe fn col_ptr(buf: Img<*const [T]>, col: usize) -> Self {
193		IterPtr::assert_slice_enough(buf);
194		assert!(col < buf.width());
195		Self::col_ptr_unchecked(buf, col)
196	}
197
198	/// Creates a new [`IterPtr`] over the specified buffer col.
199	///
200	/// # Safety
201	///
202	/// The given slice must outlive this [`IterPtr`].
203	///
204	/// The given col must not be out of bounds.
205	#[inline]
206	pub unsafe fn col_ptr_unchecked(buf: Img<*const [T]>, col: usize) -> Self {
207		let slice = {
208			let data = buf.buf().cast::<T>().add(col);
209			let len = buf.stride() * (buf.height() - 1) + 1;
210			slice_from_raw_parts(data, len)
211		};
212
213		Self::new_unchecked(slice, buf.stride())
214	}
215}
216
217impl<T> Iterator for IterPtr<T> {
218	type Item = *const T;
219
220	#[inline]
221	fn next(&mut self) -> Option<Self::Item> {
222		let len = unsafe { slice_ptr_len(self.0) };
223
224		if len > 0 {
225			let first = self.0.cast::<T>();
226
227			self.0 = unsafe {
228				let data = first.add(min(self.1, len));
229				let len = len.saturating_sub(self.1);
230				slice_from_raw_parts(data, len)
231			};
232
233			Some(first)
234		} else {
235			None
236		}
237	}
238
239	#[inline]
240	fn size_hint(&self) -> (usize, Option<usize>) {
241		let len = self.len();
242		(len, Some(len))
243	}
244}
245
246impl<T> DoubleEndedIterator for IterPtr<T> {
247	#[inline]
248	fn next_back(&mut self) -> Option<Self::Item> {
249		let len = unsafe { slice_ptr_len(self.0) };
250
251		if len > 0 {
252			let first = self.0.cast::<T>();
253
254			self.0 = {
255				let data = first;
256				let len = len.saturating_sub(self.1);
257				slice_from_raw_parts(data, len)
258			};
259
260			Some(unsafe { first.add(len - 1) })
261		} else {
262			None
263		}
264	}
265}
266
267impl<T> ExactSizeIterator for IterPtr<T> {
268	#[inline]
269	fn len(&self) -> usize {
270		let len = unsafe { slice_ptr_len(self.0) };
271		(len + (self.1 - 1)) / self.1
272	}
273}
274
275#[derive(Copy, Clone, Eq, PartialEq, Debug)]
276pub struct IterPtrMut<T>(*mut [T], usize);
277
278unsafe impl<T: Send> Send for IterPtrMut<T> {}
279
280unsafe impl<T> Sync for IterPtrMut<T> {}
281
282impl IterPtrMut<()> {
283	#[doc(hidden)]
284	#[inline(always)]
285	pub(crate) fn assert_slice_enough<T>(img: Img<*mut [T]>) {
286		use crate::traits::ImgAsPtr;
287		IterPtr::assert_slice_enough(img.as_ptr())
288	}
289}
290
291impl<T> IterPtrMut<T> {
292	/// Creates a new [`IterPtrMut`] over the specified slice and stride.
293	///
294	/// # Safety
295	///
296	/// The given slice must outlive this [`IterPtrMut`].
297	///
298	/// # Panics
299	///
300	/// Panics if the given slice does not start and end at an element. That is,
301	/// both the first and last elements of the slice must be elements that
302	/// would be returned by this iterator. Do not include trailing stride.
303	#[inline]
304	pub unsafe fn new(slice: *mut [T], stride: usize) -> Self {
305		assert!(IterPtr::is_slice_perfect(slice_ptr_len_mut(slice), stride));
306		Self::new_unchecked(slice, stride)
307	}
308
309	/// Creates a new [`IterPtrMut`] over the specified slice and stride.
310	///
311	/// # Safety
312	///
313	/// The given slice must outlive this [`IterPtrMut`].
314	///
315	/// UB if the given slice does not start and end at an element. That is,
316	/// both the first and last elements of the slice must be elements that
317	/// would be returned by this iterator. Do not include trailing stride.
318	#[inline]
319	pub unsafe fn new_unchecked(slice: *mut [T], stride: usize) -> Self {
320		Self(slice, stride)
321	}
322
323	/// Creates a new [`IterPtrMut`] over the specified slice and stride.
324	///
325	/// # Safety
326	///
327	/// The given slice must outlive this [`IterPtrMut`].
328	///
329	/// # Panics
330	///
331	/// Panics if the given slice does not start and end at an element. That is,
332	/// both the first and last elements of the slice must be elements that
333	/// would be returned by this iterator. Do not include trailing stride.
334	#[inline]
335	pub unsafe fn new_slice(slice: &mut [T], stride: usize) -> Self {
336		Self::new(slice as *mut [T], stride)
337	}
338
339	/// Creates a new [`IterPtrMut`] over the specified slice and stride.
340	///
341	/// # Safety
342	///
343	/// The given slice must outlive this [`IterPtrMut`].
344	///
345	/// UB if the given slice does not start and end at an element. That is,
346	/// both the first and last elements of the slice must be elements that
347	/// would be returned by this iterator. Do not include trailing stride.
348	#[inline]
349	pub unsafe fn new_slice_unchecked(slice: &mut [T], stride: usize) -> Self {
350		Self::new_unchecked(slice as *mut [T], stride)
351	}
352
353	/// Creates a new [`IterPtrMut`] over the specified buffer row.
354	///
355	/// # Safety
356	///
357	/// The given buffer must outlive this [`IterPtrMut`].
358	///
359	/// # Panics
360	///
361	/// Panics if the given row is out of bounds.
362	#[inline]
363	pub unsafe fn row<S: AsMut<[T]>>(buf: &mut Img<S>, row: usize) -> Self {
364		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
365		let buf = buf.buf_mut().as_mut() as *mut [T];
366		Self::row_ptr(Img::new_stride(buf, width, height, stride), row)
367	}
368
369	/// Creates a new [`IterPtrMut`] over the specified buffer row.
370	///
371	/// # Safety
372	///
373	/// The given buffer must outlive this [`IterPtrMut`].
374	///
375	/// # Panics
376	///
377	/// Panics if the provided buffer has a width and height too large to fit in
378	/// its backing store.
379	///
380	/// Panics if the given row is out of bounds.
381	#[inline]
382	pub unsafe fn row_ptr(buf: Img<*mut [T]>, row: usize) -> Self {
383		IterPtrMut::assert_slice_enough(buf);
384		assert!(row < buf.height());
385		Self::row_ptr_unchecked(buf, row)
386	}
387
388	/// Creates a new [`IterPtrMut`] over the specified buffer row.
389	///
390	/// # Safety
391	///
392	/// The given slice must outlive this [`IterPtrMut`].
393	///
394	/// The given row must not be out of bounds.
395	#[inline]
396	pub unsafe fn row_ptr_unchecked(buf: Img<*mut [T]>, row: usize) -> Self {
397		let slice = {
398			let data = buf.buf().cast::<T>().add(row * buf.stride());
399			let len = buf.width();
400			slice_from_raw_parts_mut(data, len)
401		};
402
403		Self::new_unchecked(slice, 1)
404	}
405
406	/// Creates a new [`IterPtrMut`] over the specified buffer col.
407	///
408	/// # Safety
409	///
410	/// The given buffer must outlive this [`IterPtrMut`].
411	///
412	/// # Panics
413	///
414	/// Panics if the given col is out of bounds.
415	#[inline]
416	pub unsafe fn col<S: AsMut<[T]>>(buf: &mut Img<S>, col: usize) -> Self {
417		let (width, height, stride) = (buf.width(), buf.height(), buf.stride());
418		let buf = buf.buf_mut().as_mut() as *mut [T];
419		Self::col_ptr(Img::new_stride(buf, width, height, stride), col)
420	}
421
422	/// Creates a new [`IterPtrMut`] over the specified buffer col.
423	///
424	/// # Safety
425	///
426	/// The given slice must outlive this [`IterPtrMut`].
427	///
428	/// # Panics
429	///
430	/// Panics if the provided buffer has a width and height too large to fit in
431	/// its backing store.
432	///
433	/// Panics if the given col is out of bounds.
434	#[inline]
435	pub unsafe fn col_ptr(buf: Img<*mut [T]>, col: usize) -> Self {
436		IterPtrMut::assert_slice_enough(buf);
437		assert!(col < buf.width());
438		Self::col_ptr_unchecked(buf, col)
439	}
440
441	/// Creates a new [`IterPtrMut`] over the specified buffer col.
442	///
443	/// # Safety
444	///
445	/// The given slice must outlive this [`IterPtrMut`].
446	///
447	/// The given col must not be out of bounds.
448	#[inline]
449	pub unsafe fn col_ptr_unchecked(buf: Img<*mut [T]>, col: usize) -> Self {
450		let slice = {
451			let data = buf.buf().cast::<T>().add(col);
452			let len = buf.stride() * (buf.height() - 1) + 1;
453			slice_from_raw_parts_mut(data, len)
454		};
455
456		Self::new_unchecked(slice, buf.stride())
457	}
458}
459
460impl<T> Iterator for IterPtrMut<T> {
461	type Item = *mut T;
462
463	#[inline]
464	fn next(&mut self) -> Option<Self::Item> {
465		let len = unsafe { slice_ptr_len_mut(self.0) };
466
467		if len > 0 {
468			let first = self.0.cast::<T>();
469
470			self.0 = unsafe {
471				let data = first.add(min(self.1, len));
472				let len = len.saturating_sub(self.1);
473				slice_from_raw_parts_mut(data, len)
474			};
475
476			Some(first)
477		} else {
478			None
479		}
480	}
481
482	#[inline]
483	fn size_hint(&self) -> (usize, Option<usize>) {
484		let len = self.len();
485		(len, Some(len))
486	}
487}
488
489impl<T> DoubleEndedIterator for IterPtrMut<T> {
490	#[inline]
491	fn next_back(&mut self) -> Option<Self::Item> {
492		let len = unsafe { slice_ptr_len_mut(self.0) };
493
494		if len > 0 {
495			let first = self.0.cast::<T>();
496
497			self.0 = {
498				let data = first;
499				let len = len.saturating_sub(self.1);
500				slice_from_raw_parts_mut(data, len)
501			};
502
503			Some(unsafe { first.add(len - 1) })
504		} else {
505			None
506		}
507	}
508}
509
510impl<T> ExactSizeIterator for IterPtrMut<T> {
511	#[inline]
512	fn len(&self) -> usize {
513		let len = unsafe { slice_ptr_len_mut(self.0) };
514		(len + (self.1 - 1)) / self.1
515	}
516}