orx_concurrent_vec/concurrent_slice/
split.rs

1use super::ConcurrentSlice;
2use crate::elem::ConcurrentElement;
3use orx_fixed_vec::IntoConcurrentPinnedVec;
4
5impl<'a, T, P> ConcurrentSlice<'a, T, P>
6where
7    P: IntoConcurrentPinnedVec<ConcurrentElement<T>>,
8{
9    /// Divides one slice into two at an index:
10    /// * the first will contain elements in positions `[0, mid)`,
11    /// * the second will contain elements in positions `[mid, self.len())`.
12    ///
13    /// # Panics
14    ///
15    /// Panics if `mid > self.len()`.
16    ///
17    /// # Examples
18    ///
19    /// ```
20    /// use orx_concurrent_vec::*;
21    ///
22    /// let vec = ConcurrentVec::from_iter(0..8);
23    ///
24    /// let slice = vec.as_slice();
25    ///
26    /// let (a, b) = slice.split_at(3);
27    /// assert_eq!(a, [0, 1, 2]);
28    /// assert_eq!(b, [3, 4, 5, 6, 7]);
29    /// ```
30    pub fn split_at(
31        &'a self,
32        mid: usize,
33    ) -> (ConcurrentSlice<'a, T, P>, ConcurrentSlice<'a, T, P>) {
34        let len = self.len();
35        assert!(mid <= len);
36        (self.slice(0..mid), self.slice(mid..len))
37    }
38
39    /// Returns the first and all the rest of the elements of the slice, or None if it is empty.
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// use orx_concurrent_vec::*;
45    ///
46    /// let vec = ConcurrentVec::from_iter(0..4);
47    /// let slice = vec.as_slice();
48    ///
49    /// let (a, b) = slice.split_first().unwrap();
50    /// assert_eq!(a, &0);
51    /// assert_eq!(b, [1, 2, 3]);
52    ///
53    /// // empty
54    /// let slice = vec.slice(0..0);
55    /// assert!(slice.split_first().is_none());
56    ///
57    /// // single element
58    /// let slice = vec.slice(2..3);
59    /// let (a, b) = slice.split_first().unwrap();
60    /// assert_eq!(a, &2);
61    /// assert_eq!(b, []);
62    /// ```
63    pub fn split_first(&self) -> Option<(&ConcurrentElement<T>, ConcurrentSlice<T, P>)> {
64        match self.get(0) {
65            Some(a) => {
66                let b = self.slice(1..self.len());
67                Some((a, b))
68            }
69            None => None,
70        }
71    }
72
73    /// Returns the last and all the rest of the elements of the slice, or None if it is empty.
74    ///
75    /// # Examples
76    ///
77    /// ```
78    /// use orx_concurrent_vec::*;
79    ///
80    /// let vec = ConcurrentVec::from_iter(0..4);
81    /// let slice = vec.as_slice();
82    ///
83    /// let (a, b) = slice.split_last().unwrap();
84    /// assert_eq!(a, &3);
85    /// assert_eq!(b, [0, 1, 2]);
86    ///
87    /// // empty
88    /// let slice = vec.slice(0..0);
89    /// assert!(slice.split_last().is_none());
90    ///
91    /// // single element
92    /// let slice = vec.slice(2..3);
93    /// let (a, b) = slice.split_last().unwrap();
94    /// assert_eq!(a, &2);
95    /// assert_eq!(b, []);
96    /// ```
97    pub fn split_last(&self) -> Option<(&ConcurrentElement<T>, ConcurrentSlice<T, P>)> {
98        let len = self.len();
99        match len {
100            0 => None,
101            _ => {
102                let a = self.slice(0..(len - 1));
103                let b = &self[len - 1];
104                Some((b, a))
105            }
106        }
107    }
108
109    /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the beginning of the slice.
110    ///
111    /// The chunks are slices and do not overlap.
112    /// If chunk_size does not divide the length of the slice, then the last chunk will not have length chunk_size.
113    ///
114    /// # Panics
115    ///
116    /// Panics if chunk_size is 0.
117    ///
118    /// # Examples
119    ///
120    /// ```
121    /// use orx_concurrent_vec::*;
122    ///
123    /// let vec: ConcurrentVec<_> = ['l', 'o', 'r', 'e', 'm'].into_iter().collect();
124    /// let slice = vec.as_slice();
125    ///
126    /// let mut iter = slice.chunks(2);
127    /// assert_eq!(iter.next().unwrap(), ['l', 'o']);
128    /// assert_eq!(iter.next().unwrap(), ['r', 'e']);
129    /// assert_eq!(iter.next().unwrap(), ['m']);
130    /// assert!(iter.next().is_none());
131    /// ```
132    pub fn chunks(
133        &'a self,
134        chunk_size: usize,
135    ) -> impl ExactSizeIterator<Item = ConcurrentSlice<'a, T, P>> {
136        assert!(chunk_size > 0);
137
138        let len = self.len();
139        let mut num_slices = len / chunk_size;
140        let remainder = len - num_slices * chunk_size;
141        if remainder > 0 {
142            num_slices += 1;
143        }
144
145        (0..num_slices).map(move |i| {
146            let a = i * chunk_size;
147            let b = a + match (i == num_slices - 1, remainder > 0) {
148                (true, true) => remainder,
149                _ => chunk_size,
150            };
151            self.slice(a..b)
152        })
153    }
154}