bon_macros/util/
iterator.rs

1use crate::util::prelude::*;
2use std::fmt::Write;
3
4pub(crate) trait IteratorExt: Iterator + Sized {
5    /// Based on itertools:
6    /// <https://github.com/rust-itertools/itertools/blob/a4a82e4b97eb76687c2a57cdfd2e5343ff507827/src/lib.rs#L2301-L2330>
7    fn join(mut self, sep: &str) -> String
8    where
9        Self::Item: std::fmt::Display,
10    {
11        let first = match self.next() {
12            Some(first) => first,
13            _ => return String::new(),
14        };
15
16        // estimate lower bound of capacity needed
17        let (lower, _) = self.size_hint();
18        let mut result = String::with_capacity(sep.len() * lower);
19
20        write!(&mut result, "{first}").unwrap();
21
22        for elt in self {
23            result.push_str(sep);
24            write!(&mut result, "{elt}").unwrap();
25        }
26
27        result
28    }
29}
30
31impl<I: Iterator> IteratorExt for I {}
32
33pub(crate) trait IntoIteratorExt: IntoIterator + Sized {
34    fn try_equals_with<O>(
35        self,
36        other: O,
37        compare: impl Fn(Self::Item, O::Item) -> Result<bool>,
38    ) -> Result<bool>
39    where
40        O: IntoIterator,
41        O::IntoIter: ExactSizeIterator,
42        Self::IntoIter: ExactSizeIterator,
43    {
44        let me = self.into_iter();
45        let other = other.into_iter();
46
47        if me.len() != other.len() {
48            return Ok(false);
49        }
50
51        for (a, b) in me.zip(other) {
52            if !compare(a, b)? {
53                return Ok(false);
54            }
55        }
56
57        Ok(true)
58    }
59
60    fn concat(self) -> Self::Item
61    where
62        Self::Item: Extend<<Self::Item as IntoIterator>::Item> + IntoIterator + Default,
63    {
64        self.into_iter()
65            .reduce(|mut a, b| {
66                a.extend(b);
67                a
68            })
69            .unwrap_or_default()
70    }
71}
72
73impl<I: IntoIterator> IntoIteratorExt for I {}