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<I, F> fmt::Display for FormatWith<'_, 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<I, F> fmt::Debug for FormatWith<'_, I, F>
75where
76    I: Iterator,
77    F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result,
78{
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80        fmt::Display::fmt(self, f)
81    }
82}
83
84impl<I> Format<'_, I>
85where
86    I: Iterator,
87{
88    fn format(
89        &self,
90        f: &mut fmt::Formatter,
91        cb: fn(&I::Item, &mut fmt::Formatter) -> fmt::Result,
92    ) -> fmt::Result {
93        let mut iter = match self.inner.take() {
94            Some(t) => t,
95            None => panic!("Format: was already formatted once"),
96        };
97
98        if let Some(fst) = iter.next() {
99            cb(&fst, f)?;
100            iter.try_for_each(|elt| {
101                if !self.sep.is_empty() {
102                    f.write_str(self.sep)?;
103                }
104                cb(&elt, f)
105            })?;
106        }
107        Ok(())
108    }
109}
110
111macro_rules! impl_format {
112    ($($fmt_trait:ident)*) => {
113        $(
114            impl<'a, I> fmt::$fmt_trait for Format<'a, I>
115                where I: Iterator,
116                      I::Item: fmt::$fmt_trait,
117            {
118                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119                    self.format(f, fmt::$fmt_trait::fmt)
120                }
121            }
122        )*
123    }
124}
125
126impl_format! {Display Debug UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer}
127
128impl<I, F> Clone for FormatWith<'_, I, F>
129where
130    (I, F): Clone,
131{
132    fn clone(&self) -> Self {
133        struct PutBackOnDrop<'r, 'a, I, F> {
134            into: &'r FormatWith<'a, I, F>,
135            inner: Option<(I, F)>,
136        }
137        // This ensures we preserve the state of the original `FormatWith` if `Clone` panics
138        impl<I, F> Drop for PutBackOnDrop<'_, '_, I, F> {
139            fn drop(&mut self) {
140                self.into.inner.set(self.inner.take())
141            }
142        }
143        let pbod = PutBackOnDrop {
144            inner: self.inner.take(),
145            into: self,
146        };
147        Self {
148            inner: Cell::new(pbod.inner.clone()),
149            sep: self.sep,
150        }
151    }
152}
153
154impl<I> Clone for Format<'_, I>
155where
156    I: Clone,
157{
158    fn clone(&self) -> Self {
159        struct PutBackOnDrop<'r, 'a, I> {
160            into: &'r Format<'a, I>,
161            inner: Option<I>,
162        }
163        // This ensures we preserve the state of the original `FormatWith` if `Clone` panics
164        impl<I> Drop for PutBackOnDrop<'_, '_, I> {
165            fn drop(&mut self) {
166                self.into.inner.set(self.inner.take())
167            }
168        }
169        let pbod = PutBackOnDrop {
170            inner: self.inner.take(),
171            into: self,
172        };
173        Self {
174            inner: Cell::new(pbod.inner.clone()),
175            sep: self.sep,
176        }
177    }
178}