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}