orx_concurrent_vec/
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
use crate::{elem::ConcurrentElement, ConcurrentSlice, ConcurrentVec};
use orx_pinned_vec::IntoConcurrentPinnedVec;

impl<T, P> ConcurrentVec<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 (a, b) = vec.split_at(3);
    /// assert_eq!(a, [0, 1, 2]);
    /// assert_eq!(b, [3, 4, 5, 6, 7]);
    /// ```
    pub fn split_at(&self, mid: usize) -> (ConcurrentSlice<T, P>, ConcurrentSlice<T, P>) {
        assert!(mid <= self.len());
        (self.slice(0..mid), self.slice(mid..))
    }

    /// 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 (a, b) = vec.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 (a, b) = vec.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 mut iter = vec.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(
        &self,
        chunk_size: usize,
    ) -> impl ExactSizeIterator<Item = ConcurrentSlice<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)
        })
    }
}