orx_concurrent_vec/
split.rs

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