ptr_iter/
lib.rs

1#![no_std]
2#![warn(missing_docs)]
3
4//! A crate with iterators to simplify working with pointers.
5//!
6//! Constructing these iterators is unsafe, but once constructed the iteration
7//! itself is considered a safe operation.
8//!
9//! The two iterators themselves will iterate forever. The constructor functions
10//! apply the correct iterator adapters to limit the iteration to stay within
11//! safe bounds.
12//!
13//! ## Safety
14//! * You must always use the iterator before the pointer it's based upon
15//!   becomes invalidated. This is the same logic as constructing a slice from a
16//!   raw pointer: If you use a pointer to build a safe type and then invalidate
17//!   the source pointer, the safe type itself will become invalid too.
18//! * The iteration is done with the pointer [`add`](https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.add)
19//!   method, and so these iterators must only be constructed with pointers to
20//!   valid allocations.
21
22/// An iterator based on a mutable pointer.
23#[derive(Debug, Clone, PartialEq, Eq)]
24#[repr(transparent)]
25pub struct MutPtrIter<T>(*mut T);
26impl<T> Iterator for MutPtrIter<T> {
27  type Item = *mut T;
28  #[inline]
29  fn next(&mut self) -> Option<Self::Item> {
30    let out = self.0;
31    self.0 = unsafe { self.0.add(1) };
32    Some(out)
33  }
34  #[inline]
35  fn size_hint(&self) -> (usize, Option<usize>) {
36    (usize::MAX, None)
37  }
38}
39impl<T> MutPtrIter<T> {
40  /// Iterates all pointers within the slice pointer given.
41  ///
42  /// ```rust
43  /// # use ptr_iter::MutPtrIter;
44  /// let mut arr: [u8; 4] = [5, 6, 7, 8];
45  /// let mut iter = unsafe { MutPtrIter::over_slice_ptr(&mut arr).map(|p| *p) };
46  /// assert_eq!(iter.next(), Some(5_u8));
47  /// assert_eq!(iter.next(), Some(6_u8));
48  /// assert_eq!(iter.next(), Some(7_u8));
49  /// assert_eq!(iter.next(), Some(8_u8));
50  /// assert_eq!(iter.next(), None);
51  /// assert_eq!(iter.next(), None);
52  /// ```
53  ///
54  /// ## Safety
55  /// * The slice pointer must point to a valid allocation.
56  /// * You agree ahead of time to not use the iterator after the pointer is
57  ///   invalid.
58  #[inline]
59  pub unsafe fn over_slice_ptr(p: *mut [T]) -> core::iter::Take<Self> {
60    // Safety: the caller has to pass a valid pointer, so we can use
61    // new_unchecked because a null pointer is never valid. This appears to be
62    // the only stable way to get a slice pointer's length.
63    let len: usize = core::ptr::NonNull::new_unchecked(p).len();
64    Self(p as *mut T).take(len)
65  }
66}
67
68/// An iterator based on a constant pointer.
69#[derive(Debug, Clone, PartialEq, Eq)]
70#[repr(transparent)]
71pub struct ConstPtrIter<T>(*const T);
72impl<T> Iterator for ConstPtrIter<T> {
73  type Item = *const T;
74  #[inline]
75  fn next(&mut self) -> Option<Self::Item> {
76    let out = self.0;
77    self.0 = unsafe { self.0.add(1) };
78    Some(out)
79  }
80  #[inline]
81  fn size_hint(&self) -> (usize, Option<usize>) {
82    (usize::MAX, None)
83  }
84}
85impl<T> ConstPtrIter<T> {
86  /// Iterates all pointers within the slice pointer given.
87  ///
88  /// ```rust
89  /// # use ptr_iter::ConstPtrIter;
90  /// let arr: [u8; 4] = [5, 6, 7, 8];
91  /// let mut iter = unsafe { ConstPtrIter::over_slice_ptr(&arr).map(|p| *p) };
92  /// assert_eq!(iter.next(), Some(5_u8));
93  /// assert_eq!(iter.next(), Some(6_u8));
94  /// assert_eq!(iter.next(), Some(7_u8));
95  /// assert_eq!(iter.next(), Some(8_u8));
96  /// assert_eq!(iter.next(), None);
97  /// assert_eq!(iter.next(), None);
98  /// ```
99  ///
100  /// ## Safety
101  /// * The slice pointer must point to a valid allocation.
102  /// * You agree ahead of time to not use the iterator after the pointer is
103  ///   invalid.
104  #[inline]
105  pub unsafe fn over_slice_ptr(p: *const [T]) -> core::iter::Take<Self> {
106    // Safety: the caller has to pass a valid pointer, so we can use
107    // new_unchecked because a null pointer is never valid. This appears to be
108    // the only stable way to get a slice pointer's length.
109    let len: usize = core::ptr::NonNull::new_unchecked(p as *mut [T]).len();
110    Self(p as *const T).take(len)
111  }
112
113  /// Reads successive pointer positions and returns values until the type's
114  /// default value is read.
115  ///
116  /// * The default value is *excluded* from the iterator's output sequence.
117  ///
118  /// This covers the common case of iterating "C String" style data, where the
119  /// data consists of an unknown number of non-zero elements and then a 0
120  /// marking the end of the sequence.
121  ///
122  /// ```rust
123  /// # use ptr_iter::ConstPtrIter;
124  /// let arr: &[u8; 5] = b"rust\0";
125  /// let mut iter = unsafe { ConstPtrIter::read_until_default(arr.as_ptr()) };
126  /// assert_eq!(iter.next(), Some(b'r'));
127  /// assert_eq!(iter.next(), Some(b'u'));
128  /// assert_eq!(iter.next(), Some(b's'));
129  /// assert_eq!(iter.next(), Some(b't'));
130  /// assert_eq!(iter.next(), None);
131  /// assert_eq!(iter.next(), None);
132  /// ```
133  ///
134  /// ## Safety
135  /// * The pointer must be valid for reads up to and including the position of
136  ///   the default element.
137  /// * You agree ahead of time to not use the iterator after the pointer is
138  ///   invalid.
139  #[inline]
140  pub unsafe fn read_until_default(
141    p: *const T,
142  ) -> impl Iterator<Item = T> + Clone
143  where
144    T: Copy + Default + PartialEq,
145  {
146    Self(p).map(|p| unsafe { *p }).take_while(|p| p != &T::default())
147  }
148}