dock_crypto_utils/
extend_some.rs

1#[cfg(feature = "parallel")]
2use rayon::prelude::*;
3
4/// Extends only `Some(_)` produced by an iterator and drops all `None`s.
5#[derive(Debug, Clone, Eq, PartialEq)]
6pub struct ExtendSome<C>(pub C);
7
8impl<C: Default> Default for ExtendSome<C> {
9    fn default() -> Self {
10        Self(Default::default())
11    }
12}
13
14impl<C: IntoIterator> IntoIterator for ExtendSome<C> {
15    type Item = C::Item;
16    type IntoIter = C::IntoIter;
17
18    fn into_iter(self) -> Self::IntoIter {
19        self.0.into_iter()
20    }
21}
22
23impl<T, C: Extend<T>> Extend<Option<T>> for ExtendSome<C> {
24    fn extend<I: IntoIterator<Item = Option<T>>>(&mut self, iter: I) {
25        self.0.extend(iter.into_iter().flatten());
26    }
27}
28
29impl<T, C: Default + FromIterator<T>> FromIterator<Option<T>> for ExtendSome<C> {
30    fn from_iter<I: IntoIterator<Item = Option<T>>>(iter: I) -> Self {
31        Self(C::from_iter(iter.into_iter().flatten()))
32    }
33}
34
35#[cfg(feature = "parallel")]
36impl<T: Send, C: Default + FromParallelIterator<T> + Send> FromParallelIterator<Option<T>>
37    for ExtendSome<C>
38{
39    fn from_par_iter<I>(par_iter: I) -> Self
40    where
41        I: IntoParallelIterator<Item = Option<T>>,
42    {
43        Self(C::from_par_iter(par_iter.into_par_iter().flatten()))
44    }
45}
46
47#[cfg(feature = "parallel")]
48impl<T: Send, C: Default + ParallelExtend<T> + Send> ParallelExtend<Option<T>> for ExtendSome<C> {
49    fn par_extend<I>(&mut self, par_iter: I)
50    where
51        I: IntoParallelIterator<Item = Option<T>>,
52    {
53        self.0.par_extend(par_iter.into_par_iter().flatten());
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn basic() {
63        let ExtendSome::<Vec<_>>(arr) = [Some(1), Some(2), None, Some(4)].into_iter().collect();
64
65        assert_eq!(arr, [1, 2, 4]);
66
67        let (ExtendSome::<Vec<_>>(even), ExtendSome::<Vec<_>>(odd)) =
68            [Some(1), Some(2), None, Some(4), Some(5), None]
69                .into_iter()
70                .partition(|v| v.map_or(false, |idx| idx % 2 == 0));
71
72        assert_eq!(even, vec![2, 4]);
73        assert_eq!(odd, vec![1, 5])
74    }
75}