imgref_iter/iter/generic/
ptr.rs1use 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 #[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 #[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 #[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 #[inline]
76 pub unsafe fn new_unchecked(slice: *const [T], stride: usize) -> Self {
77 Self(slice, stride)
78 }
79
80 #[inline]
92 pub unsafe fn new_slice(slice: &[T], stride: usize) -> Self {
93 Self::new(slice as *const [T], stride)
94 }
95
96 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[inline]
319 pub unsafe fn new_unchecked(slice: *mut [T], stride: usize) -> Self {
320 Self(slice, stride)
321 }
322
323 #[inline]
335 pub unsafe fn new_slice(slice: &mut [T], stride: usize) -> Self {
336 Self::new(slice as *mut [T], stride)
337 }
338
339 #[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 #[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 #[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 #[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 #[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 #[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 #[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}