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}