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}