kaspa_utils/
iter.rs

1use itertools::Itertools;
2
3/// Format all iterator elements, separated by `sep`.
4///
5/// Unlike the underlying `itertools::format`, **does not panic** if `fmt` is called more than once.
6/// Should be used for logging purposes since `itertools::format` will panic when used by multiple loggers.
7pub trait IterExtensions: Iterator {
8    fn reusable_format(self, sep: &str) -> ReusableIterFormat<Self>
9    where
10        Self: Sized,
11    {
12        ReusableIterFormat::new(self.format(sep))
13    }
14}
15
16impl<T: ?Sized> IterExtensions for T where T: Iterator {}
17
18pub struct ReusableIterFormat<'a, I> {
19    inner: itertools::Format<'a, I>,
20}
21
22impl<'a, I> ReusableIterFormat<'a, I> {
23    pub fn new(inner: itertools::Format<'a, I>) -> Self {
24        Self { inner }
25    }
26}
27
28impl<'a, I> std::fmt::Display for ReusableIterFormat<'a, I>
29where
30    I: std::clone::Clone,
31    I: Iterator,
32    I::Item: std::fmt::Display,
33{
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        // Clone the inner format to workaround the `Format: was already formatted once` internal error
36        self.inner.clone().fmt(f)
37    }
38}
39
40impl<'a, I> std::fmt::Debug for ReusableIterFormat<'a, I>
41where
42    I: std::clone::Clone,
43    I: Iterator,
44    I::Item: std::fmt::Debug,
45{
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        // Clone the inner format to workaround the `Format: was already formatted once` internal error
48        self.inner.clone().fmt(f)
49    }
50}