stride/lib.rs
1//! This crate provides a slice-like [`Stride<T, S>`] type where elements are
2//! spaced a constant `S` elements in memory.
3//!
4//! For example, given an underlying slice `&[1, 2, 3, 4, 5, 6]`, the elements
5//! `&[1, 3, 5]` are a strided slice with a stride of 2. This crate makes use of
6//! const generics to provide the stride value `S` at compile time so that there
7//! is no runtime memory overhead to strided slices; `Stride` takes up the same
8//! amount of space as a slice.
9//!
10//! Many slice-like operations are implemented for `Stride` including iteration
11//! and indexing. Method names are similar to those of the slice type.
12//!
13//! Where you want a strided slice use:
14//! - [`::new()`][`Stride::new`] to construct a [`&Stride<T, S>`][`Stride`] that
15//! wraps a [`&[T]`][`slice`].
16//! - [`::new_mut()`][`Stride::new_mut`] to construct a
17//! [`&mut Stride<T, S>`][`Stride`] that wraps a [`&mut [T]`][`slice`].
18//!
19//! ```rust
20//! use stride::Stride;
21//!
22//! // The underlying data.
23//! let data = &mut [1, 2, 7, 4, 5, 6];
24//!
25//! // Create a strided slice with a stride of `2` referring to
26//! // elements `1`, `7`, and `5`.
27//! let stride = Stride::<_, 2>::new_mut(data);
28//!
29//! assert_eq!(stride.len(), 3);
30//!
31//! // We can use indexing to view values ..
32//! assert_eq!(stride[0], 1);
33//! assert_eq!(stride[1..3], &[7, 5]);
34//!
35//! // .. or modify them.
36//! stride[1] = 3;
37//! assert_eq!(stride, &[1, 3, 5]);
38//! assert_eq!(data, &[1, 2, 3, 4, 5, 6]);
39//! ```
40
41#![no_std]
42#![warn(unsafe_op_in_unsafe_fn)]
43
44mod index;
45mod iter;
46mod ops;
47
48use core::fmt;
49
50pub use crate::index::StrideIndex;
51pub use crate::iter::{Iter, IterMut};
52
53/// A constant strided slice.
54#[repr(transparent)]
55pub struct Stride<T, const S: usize> {
56 data: [T],
57}
58
59impl<T, const S: usize> fmt::Debug for Stride<T, S>
60where
61 T: fmt::Debug,
62{
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 f.debug_list().entries(self.iter()).finish()
65 }
66}
67
68impl<T, const S: usize> Default for &Stride<T, S> {
69 fn default() -> Self {
70 Stride::new(&[])
71 }
72}
73
74impl<T, const S: usize> Default for &mut Stride<T, S> {
75 fn default() -> Self {
76 Stride::new_mut(&mut [])
77 }
78}
79
80impl<T, const S: usize> Stride<T, S> {
81 /// Constructs a new strided slice.
82 ///
83 /// # Examples
84 ///
85 /// ```
86 /// # use stride::Stride;
87 /// #
88 /// let data = &[1, 2, 3, 4, 5, 6];
89 /// let stride = Stride::<_, 3>::new(data);
90 /// ```
91 pub fn new(data: &[T]) -> &Self {
92 unsafe { &*(data as *const [T] as *const Self) }
93 }
94
95 /// Constructs a new mutable strided slice.
96 ///
97 /// # Examples
98 ///
99 /// ```
100 /// # use stride::Stride;
101 /// #
102 /// let data = &mut [1, 2, 3, 4, 5, 6];
103 /// let stride = Stride::<_, 3>::new_mut(data);
104 /// ```
105 pub fn new_mut(data: &mut [T]) -> &mut Self {
106 unsafe { &mut *(data as *mut [T] as *mut Self) }
107 }
108
109 /// Returns the number of elements in the strided slice.
110 ///
111 /// This is equivalent to the ceiling division of the underlying slice
112 /// length by `S`.
113 ///
114 /// # Examples
115 ///
116 /// ```
117 /// # use stride::Stride;
118 /// #
119 /// let data = &[1, 2, 3, 4, 5, 6];
120 /// assert_eq!(Stride::<_, 1>::new(data).len(), 6);
121 /// assert_eq!(Stride::<_, 2>::new(data).len(), 3);
122 /// assert_eq!(Stride::<_, 3>::new(data).len(), 2);
123 /// ```
124 pub const fn len(&self) -> usize {
125 (self.data.len() + S - 1) / S
126 }
127
128 /// Returns `true` if the strided slice has a length of 0.
129 ///
130 /// # Examples
131 ///
132 /// ```
133 /// # use stride::Stride;
134 /// #
135 /// let stride = Stride::<_, 3>::new(&[1, 2, 3, 4, 5, 6]);
136 /// assert!(!stride.is_empty());
137 /// ```
138 pub const fn is_empty(&self) -> bool {
139 self.len() == 0
140 }
141
142 /// Returns a raw pointer to the underlying slice's buffer.
143 ///
144 /// *See [`slice::as_ptr()`].*
145 pub const fn as_ptr(&self) -> *const T {
146 self.data.as_ptr()
147 }
148
149 /// Returns an unsafe mutable pointer to the underlying slice's buffer.
150 ///
151 /// *See [`slice::as_mut_ptr()`].*
152 pub fn as_mut_ptr(&mut self) -> *mut T {
153 self.data.as_mut_ptr()
154 }
155
156 /// Returns a reference to an element or substride depending on the type of
157 /// index.
158 ///
159 /// - If given a position, returns a reference to the element at that
160 /// position or `None` if out of bounds.
161 /// - If given a range, returns the substride corresponding to that range,
162 /// or `None` if out of bounds.
163 ///
164 /// # Examples
165 ///
166 /// ```
167 /// # use stride::Stride;
168 /// #
169 /// let stride = Stride::<_, 2>::new(&[1, 2, 3, 4, 5, 6]);
170 /// assert_eq!(stride.get(1), Some(&3));
171 /// assert_eq!(stride.get(0..2), Some(Stride::<_, 2>::new(&[1, 2, 3, 4])));
172 /// assert_eq!(stride.get(3), None);
173 /// assert_eq!(stride.get(0..4), None);
174 /// ```
175 pub fn get<I>(&self, index: I) -> Option<&I::Output>
176 where
177 I: StrideIndex<Stride<T, S>>,
178 {
179 index.get(self)
180 }
181
182 /// Returns a mutable reference to an element or substride depending on the
183 /// type of index (see [`get`]) or `None` if the index is out of bounds.
184 ///
185 /// [`get`]: #method.get
186 ///
187 /// # Examples
188 ///
189 /// ```
190 /// # use stride::Stride;
191 /// #
192 /// let data = &mut [0, 1, 2, 3];
193 /// let stride = Stride::<_, 2>::new_mut(data);
194 ///
195 /// if let Some(elem) = stride.get_mut(1) {
196 /// *elem = 42;
197 /// }
198 /// assert_eq!(stride, Stride::<_, 2>::new(&[0, 1, 42, 3]));
199 /// ```
200 pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
201 where
202 I: StrideIndex<Stride<T, S>>,
203 {
204 index.get_mut(self)
205 }
206
207 /// Returns a reference to an element or substride, without doing bounds
208 /// checking.
209 ///
210 /// For a safe alternative see [`get`].
211 ///
212 /// # Safety
213 ///
214 /// Calling this method with an out-of-bounds index is *[undefined behavior]*
215 /// even if the resulting reference is not used.
216 ///
217 /// [`get`]: #method.get
218 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
219 pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
220 where
221 I: StrideIndex<Self>,
222 {
223 unsafe { &*index.get_unchecked(self) }
224 }
225
226 /// Returns a mutable reference to an element or substride, without doing
227 /// bounds checking.
228 ///
229 /// For a safe alternative see [`get_mut`].
230 ///
231 /// # Safety
232 ///
233 /// Calling this method with an out-of-bounds index is *[undefined behavior]*
234 /// even if the resulting reference is not used.
235 ///
236 /// [`get_mut`]: #method.get_mut
237 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
238 pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
239 where
240 I: StrideIndex<Self>,
241 {
242 unsafe { &mut *index.get_unchecked_mut(self) }
243 }
244
245 /// Returns a reference to the first element of the strided slice, or `None`
246 /// if it is empty.
247 pub fn first(&self) -> Option<&T> {
248 self.get(0)
249 }
250
251 /// Returns a mutable reference to the first element of the strided slice,
252 /// or `None` if it is empty.
253 pub fn first_mut(&mut self) -> Option<&mut T> {
254 self.get_mut(0)
255 }
256
257 /// Returns a reference to the last element of the strided slice, or `None`
258 /// if it is empty.
259 pub fn last(&self) -> Option<&T> {
260 self.get(self.len().saturating_sub(1))
261 }
262
263 /// Returns a mutable reference to the last element of the strided slice, or
264 /// `None` if it is empty.
265 pub fn last_mut(&mut self) -> Option<&mut T> {
266 self.get_mut(self.len().saturating_sub(1))
267 }
268
269 /// Swaps two elements in the strided slice.
270 ///
271 /// # Arguments
272 ///
273 /// - `a` - The index of the first element
274 /// - `b` - The index of the second element
275 ///
276 /// # Panics
277 ///
278 /// If `a` or `b` are out of bounds.
279 pub fn swap(&mut self, a: usize, b: usize) {
280 self.data.swap(a * S, b * S)
281 }
282
283 /// Returns an iterator over the stride.
284 ///
285 /// # Examples
286 ///
287 /// ```
288 /// # use stride::Stride;
289 /// #
290 /// let stride = Stride::<_, 2>::new(&[1, 2, 3, 4, 5, 6]);
291 /// let mut iterator = stride.iter();
292 /// assert_eq!(iterator.next(), Some(&1));
293 /// assert_eq!(iterator.next(), Some(&3));
294 /// assert_eq!(iterator.next(), Some(&5));
295 /// assert_eq!(iterator.next(), None);
296 /// ```
297 pub fn iter(&self) -> Iter<T, S> {
298 Iter::new(self)
299 }
300
301 /// Returns an iterator over the stride that allows modifying each value.
302 ///
303 /// # Examples
304 ///
305 /// ```
306 /// # use stride::Stride;
307 /// #
308 /// let slice = &mut [1, 1, 2, 2, 3, 3];
309 /// let stride = Stride::<_, 2>::new_mut(slice);
310 /// for elem in stride.iter_mut() {
311 /// *elem *= 2;
312 /// }
313 /// assert_eq!(slice, &[2, 1, 4, 2, 6, 3]);
314 /// ```
315 pub fn iter_mut(&mut self) -> IterMut<T, S> {
316 IterMut::new(self)
317 }
318}
319
320impl<T> Stride<T, 1> {
321 /// Returns a slice containing the entire strided slice.
322 ///
323 /// Only available on strided slices with a stride of `1`.
324 ///
325 /// # Examples
326 ///
327 /// ```
328 /// # use stride::Stride;
329 /// #
330 /// let slice = &[1, 2, 3];
331 /// let stride = Stride::<_, 1>::new(slice);
332 /// assert_eq!(stride.as_slice(), slice);
333 /// ```
334 pub fn as_slice(&self) -> &[T] {
335 &self.data
336 }
337
338 /// Returns a mutable slice containing the entire strided slice.
339 ///
340 /// Only available on strided slices with a stride of `1`.
341 ///
342 /// # Examples
343 ///
344 /// ```
345 /// # use stride::Stride;
346 /// #
347 /// let slice = &mut [1, 2, 7];
348 /// let stride = Stride::<_, 1>::new_mut(slice);
349 /// stride.as_mut_slice()[2] = 3;
350 /// assert_eq!(slice, &[1, 2, 3])
351 /// ```
352 pub fn as_mut_slice(&mut self) -> &mut [T] {
353 &mut self.data
354 }
355}