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}