orx_concurrent_vec/concurrent_slice/
slice.rs

1use crate::{ConcurrentVec, elem::ConcurrentElement, helpers::DefaultPinVec};
2use core::ops::RangeBounds;
3use orx_fixed_vec::IntoConcurrentPinnedVec;
4
5/// A slice of a [`ConcurrentVec`].
6///
7/// It can be created from a ConcurrentVec by [`ConcurrentVec::slice`]
8/// or from another slice by [`ConcurrentSlice::slice`].
9///
10/// [`ConcurrentVec::slice`]: crate::ConcurrentVec::slice
11/// [`ConcurrentSlice::slice`]: crate::ConcurrentSlice::slice
12#[derive(Clone, Copy)]
13pub struct ConcurrentSlice<'a, T, P = DefaultPinVec<T>>
14where
15    P: IntoConcurrentPinnedVec<ConcurrentElement<T>>,
16{
17    pub(super) vec: &'a ConcurrentVec<T, P>,
18    pub(super) a: usize,
19    pub(super) len: usize,
20}
21
22impl<'a, T, P> ConcurrentSlice<'a, T, P>
23where
24    P: IntoConcurrentPinnedVec<ConcurrentElement<T>>,
25{
26    pub(crate) fn new(vec: &'a ConcurrentVec<T, P>, a: usize, len: usize) -> Self {
27        Self { vec, a, len }
28    }
29
30    #[inline(always)]
31    pub(super) fn idx(&self, i: usize) -> Option<usize> {
32        match i < self.len {
33            true => Some(self.a + i),
34            false => None,
35        }
36    }
37
38    // api
39
40    /// Returns the length of the slice.
41    ///
42    /// # Example
43    ///
44    /// ```rust
45    /// use orx_concurrent_vec::*;
46    ///
47    /// let vec = ConcurrentVec::from_iter([0, 1, 2, 3, 4]);
48    ///
49    /// assert_eq!(vec.slice(0..3).len(), 3);
50    /// assert_eq!(vec.slice(1..=2).len(), 2);
51    /// assert_eq!(vec.slice(5..).len(), 0);
52    /// ```
53    #[inline(always)]
54    pub fn len(&self) -> usize {
55        self.len
56    }
57
58    /// Returns whether the slice is empty or not.
59    ///
60    /// # Example
61    ///
62    /// ```rust
63    /// use orx_concurrent_vec::*;
64    ///
65    /// let vec = ConcurrentVec::from_iter([0, 1, 2, 3, 4]);
66    ///
67    /// assert_eq!(vec.slice(0..3).is_empty(), false);
68    /// assert_eq!(vec.slice(1..=2).is_empty(), false);
69    /// assert_eq!(vec.slice(5..).is_empty(), true);
70    /// ```
71    #[inline(always)]
72    pub fn is_empty(&self) -> bool {
73        self.len == 0
74    }
75
76    /// Creates and returns a slice of a `ConcurrentVec` or another `ConcurrentSlice`.
77    ///
78    /// Concurrent counterpart of a slice for a standard vec or an array.
79    ///
80    /// A `ConcurrentSlice` provides a focused / restricted view on a slice of the vector.
81    /// It provides all methods of the concurrent vector except for the ones which
82    /// grow the size of the vector.
83    ///
84    /// # Examples
85    ///
86    /// ```rust
87    /// use orx_concurrent_vec::*;
88    ///
89    /// let vec = ConcurrentVec::from_iter([0, 1, 2, 3, 4]);
90    ///
91    /// let slice = vec.slice(1..);
92    /// assert_eq!(&slice, &[1, 2, 3, 4]);
93    ///
94    /// let slice = vec.slice(1..4);
95    /// assert_eq!(&slice, &[1, 2, 3]);
96    ///
97    /// let slice = vec.slice(..3);
98    /// assert_eq!(&slice, &[0, 1, 2]);
99    ///
100    /// let slice = vec.slice(3..10);
101    /// assert_eq!(&slice, &[3, 4]);
102    ///
103    /// let slice = vec.slice(7..9);
104    /// assert_eq!(&slice, &[]);
105    ///
106    /// // slices can also be sliced
107    ///
108    /// let slice = vec.slice(1..=4);
109    /// assert_eq!(&slice, &[1, 2, 3, 4]);
110    ///
111    /// let sub_slice = slice.slice(1..3);
112    /// assert_eq!(&sub_slice, &[2, 3]);
113    /// ```
114    pub fn slice<R: RangeBounds<usize>>(&self, range: R) -> ConcurrentSlice<'_, T, P> {
115        let [a, b] = orx_pinned_vec::utils::slice::vec_range_limits(&range, Some(self.len()));
116        let len = b - a;
117        ConcurrentSlice::new(self.vec, self.a + a, len)
118    }
119
120    /// Returns the element at the `i`-th position;
121    /// returns None if the index is out of bounds.
122    ///
123    /// The safe api of the `ConcurrentVec` never gives out `&T` or `&mut T` references.
124    /// Instead, returns a [`ConcurrentElement`] which provides thread safe concurrent read and write
125    /// methods on the element.
126    ///
127    /// # Examples
128    ///
129    /// ```rust
130    /// use orx_concurrent_vec::*;
131    ///
132    /// let vec = ConcurrentVec::new();
133    /// vec.extend([0, 1, 2, 3, 4, 5, 6]);
134    ///
135    /// let slice = vec.slice(1..5);
136    /// assert_eq!(&slice, &[1, 2, 3, 4]);
137    ///
138    /// assert!(slice.get(4).is_none());
139    ///
140    /// let cloned = slice.get(2).map(|elem| elem.cloned());
141    /// assert_eq!(cloned, Some(3));
142    ///
143    /// let double = slice.get(2).map(|elem| elem.map(|x| x * 2));
144    /// assert_eq!(double, Some(6));
145    ///
146    /// let elem = slice.get(2).unwrap();
147    /// assert_eq!(elem, &3);
148    ///
149    /// elem.set(42);
150    /// assert_eq!(elem, &42);
151    ///
152    /// elem.update(|x| *x = *x / 2);
153    /// assert_eq!(elem, &21);
154    ///
155    /// let old = elem.replace(7);
156    /// assert_eq!(old, 21);
157    /// assert_eq!(elem, &7);
158    ///
159    /// assert_eq!(&slice, &[1, 2, 7, 4]);
160    /// assert_eq!(&vec, &[0, 1, 2, 7, 4, 5, 6]);
161    /// ```
162    #[inline(always)]
163    pub fn get(&self, i: usize) -> Option<&ConcurrentElement<T>> {
164        match i < self.len {
165            true => unsafe { self.vec.core.get(self.a + i) },
166            false => None,
167        }
168    }
169
170    /// Returns the cloned value of element at the `i`-th position;
171    /// returns None if the index is out of bounds.
172    ///
173    /// Note that `slice.get_cloned(i)` is short-hand for `slice.get(i).map(|elem| elem.cloned())`.
174    ///
175    /// # Examples
176    ///
177    /// ```rust
178    /// use orx_concurrent_vec::*;
179    ///
180    /// let vec = ConcurrentVec::new();
181    /// vec.extend([10, 0, 1, 2, 3, 14, 15]);
182    ///
183    /// let slice = vec.slice(1..5);
184    ///
185    /// assert_eq!(slice.get_cloned(2), Some(2));
186    /// assert_eq!(slice.get_cloned(4), None);
187    /// ```
188    #[inline(always)]
189    pub fn get_cloned(&self, i: usize) -> Option<T>
190    where
191        T: Clone,
192    {
193        match i < self.len {
194            true => unsafe { self.vec.core.get(self.a + i) }.map(|e| e.cloned()),
195            false => None,
196        }
197    }
198
199    /// Returns the copied value of element at the `i`-th position;
200    /// returns None if the index is out of bounds.
201    ///
202    /// Note that `slice.get_copied(i)` is short-hand for `slice.get(i).map(|elem| elem.copied())`.
203    ///
204    /// # Examples
205    ///
206    /// ```rust
207    /// use orx_concurrent_vec::*;
208    ///
209    /// let vec = ConcurrentVec::from_iter([0, 1, 2, 3]);
210    ///
211    /// assert_eq!(vec.get_copied(2), Some(2));
212    /// assert_eq!(vec.get_copied(4), None);
213    /// ```
214    #[inline(always)]
215    pub fn get_copied(&self, i: usize) -> Option<T>
216    where
217        T: Copy,
218    {
219        self.get_cloned(i)
220    }
221
222    /// Returns an iterator to the elements of the slice.
223    ///
224    /// The safe api of the `ConcurrentSlice` never gives out `&T` or `&mut T` references.
225    /// Instead, the iterator yields [`ConcurrentElement`] which provides thread safe concurrent read and write
226    /// methods on the element.
227    ///
228    /// # Examples
229    ///
230    /// ```
231    /// use orx_concurrent_vec::*;
232    ///
233    /// let vec = ConcurrentVec::new();
234    /// vec.extend([10, 0, 1, 2, 3, 14, 15]);
235    ///
236    /// let slice = vec.slice(1..5);
237    ///
238    /// // read - map
239    ///
240    /// let doubles: Vec<_> = slice.iter().map(|elem| elem.map(|x| x * 2)).collect();
241    /// assert_eq!(doubles, [0, 2, 4, 6]);
242    ///
243    /// // read - reduce
244    ///
245    /// let sum: i32 = slice.iter().map(|elem| elem.cloned()).sum();
246    /// assert_eq!(sum, 6);
247    ///
248    /// // mutate
249    ///
250    /// for (i, elem) in slice.iter().enumerate() {
251    ///     match i {
252    ///         2 => elem.set(42),
253    ///         _ => elem.update(|x| *x *= 2),
254    ///     }
255    /// }
256    /// assert_eq!(&slice, &[0, 2, 42, 6]);
257    ///
258    /// let old_vals: Vec<_> = slice.iter().map(|elem| elem.replace(7)).collect();
259    /// assert_eq!(&old_vals, &[0, 2, 42, 6]);
260    /// assert_eq!(&slice, &[7, 7, 7, 7]);
261    ///
262    /// assert_eq!(&vec, &[10, 7, 7, 7, 7, 14, 15]);
263    /// ```
264    pub fn iter(&self) -> impl Iterator<Item = &ConcurrentElement<T>> {
265        let b = self.a + self.len;
266        unsafe { self.vec.core.iter_over_range(self.a..b) }
267    }
268
269    /// Returns an iterator to cloned values of the elements of the slice.
270    ///
271    /// Note that `slice.iter_cloned()` is short-hand for `slice.iter().map(|elem| elem.cloned())`.
272    ///
273    /// # Examples
274    ///
275    /// ```
276    /// use orx_concurrent_vec::*;
277    ///
278    /// let vec = ConcurrentVec::new();
279    /// vec.extend([0, 42, 7, 3]);
280    ///
281    /// let slice = vec.slice(1..=2);
282    ///
283    /// let mut iter = slice.iter_cloned();
284    ///
285    /// assert_eq!(iter.next(), Some(42));
286    /// assert_eq!(iter.next(), Some(7));
287    /// assert_eq!(iter.next(), None);
288    ///
289    /// let sum: i32 = slice.iter_cloned().sum();
290    /// assert_eq!(sum, 49);
291    /// ```
292    pub fn iter_cloned(&self) -> impl Iterator<Item = T> + '_
293    where
294        T: Clone,
295    {
296        let b = self.a + self.len;
297        unsafe { self.vec.core.iter_over_range(self.a..b) }.map(|elem| elem.cloned())
298    }
299}