itertools/
format.rs

1use std::cell::Cell;
2use std::fmt;
3
4/// Format all iterator elements lazily, separated by `sep`.
5///
6/// The format value can only be formatted once, after that the iterator is
7/// exhausted.
8///
9/// See [`.format_with()`](crate::Itertools::format_with) for more information.
10pub struct FormatWith<'a, I, F> {
11    sep: &'a str,
12    /// FormatWith uses interior mutability because Display::fmt takes &self.
13    inner: Cell<Option<(I, F)>>,
14}
15
16/// Format all iterator elements lazily, separated by `sep`.
17///
18/// The format value can only be formatted once, after that the iterator is
19/// exhausted.
20///
21/// See [`.format()`](crate::Itertools::format)
22/// for more information.
23pub struct Format<'a, I> {
24    sep: &'a str,
25    /// Format uses interior mutability because Display::fmt takes &self.
26    inner: Cell<Option<I>>,
27}
28
29pub fn new_format<I, F>(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F>
30where
31    I: Iterator,
32    F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result,
33{
34    FormatWith {
35        sep: separator,
36        inner: Cell::new(Some((iter, f))),
37    }
38}
39
40pub fn new_format_default<I>(iter: I, separator: &str) -> Format<'_, I>
41where
42    I: Iterator,
43{
44    Format {
45        sep: separator,
46        inner: Cell::new(Some(iter)),
47    }
48}
49
50impl<'a, I, F> fmt::Display for FormatWith<'a, I, F>
51where
52    I: Iterator,
53    F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result,
54{
55    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56        let (mut iter, mut format) = match self.inner.take() {
57            Some(t) => t,
58            None => panic!("FormatWith: was already formatted once"),
59        };
60
61        if let Some(fst) = iter.next() {
62            format(fst, &mut |disp: &dyn fmt::Display| disp.fmt(f))?;
63            iter.try_for_each(|elt| {
64                if !self.sep.is_empty() {
65                    f.write_str(self.sep)?;
66                }
67                format(elt, &mut |disp: &dyn fmt::Display| disp.fmt(f))
68            })?;
69        }
70        Ok(())
71    }
72}
73
74impl<'a, I> Format<'a, I>
75where
76    I: Iterator,
77{
78    fn format(
79        &self,
80        f: &mut fmt::Formatter,
81        cb: fn(&I::Item, &mut fmt::Formatter) -> fmt::Result,
82    ) -> fmt::Result {
83        let mut iter = match self.inner.take() {
84            Some(t) => t,
85            None => panic!("Format: was already formatted once"),
86        };
87
88        if let Some(fst) = iter.next() {
89            cb(&fst, f)?;
90            iter.try_for_each(|elt| {
91                if !self.sep.is_empty() {
92                    f.write_str(self.sep)?;
93                }
94                cb(&elt, f)
95            })?;
96        }
97        Ok(())
98    }
99}
100
101macro_rules! impl_format {
102    ($($fmt_trait:ident)*) => {
103        $(
104            impl<'a, I> fmt::$fmt_trait for Format<'a, I>
105                where I: Iterator,
106                      I::Item: fmt::$fmt_trait,
107            {
108                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109                    self.format(f, fmt::$fmt_trait::fmt)
110                }
111            }
112        )*
113    }
114}
115
116impl_format! {Display Debug UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer}
117
118impl<'a, I, F> Clone for FormatWith<'a, I, F>
119where
120    (I, F): Clone,
121{
122    fn clone(&self) -> Self {
123        struct PutBackOnDrop<'r, 'a, I, F> {
124            into: &'r FormatWith<'a, I, F>,
125            inner: Option<(I, F)>,
126        }
127        // This ensures we preserve the state of the original `FormatWith` if `Clone` panics
128        impl<'r, 'a, I, F> Drop for PutBackOnDrop<'r, 'a, I, F> {
129            fn drop(&mut self) {
130                self.into.inner.set(self.inner.take())
131            }
132        }
133        let pbod = PutBackOnDrop {
134            inner: self.inner.take(),
135            into: self,
136        };
137        Self {
138            inner: Cell::new(pbod.inner.clone()),
139            sep: self.sep,
140        }
141    }
142}
143
144impl<'a, I> Clone for Format<'a, I>
145where
146    I: Clone,
147{
148    fn clone(&self) -> Self {
149        struct PutBackOnDrop<'r, 'a, I> {
150            into: &'r Format<'a, I>,
151            inner: Option<I>,
152        }
153        // This ensures we preserve the state of the original `FormatWith` if `Clone` panics
154        impl<'r, 'a, I> Drop for PutBackOnDrop<'r, 'a, I> {
155            fn drop(&mut self) {
156                self.into.inner.set(self.inner.take())
157            }
158        }
159        let pbod = PutBackOnDrop {
160            inner: self.inner.take(),
161            into: self,
162        };
163        Self {
164            inner: Cell::new(pbod.inner.clone()),
165            sep: self.sep,
166        }
167    }
168}