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