1 | use std::cell::Cell; |
2 | use 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. |
10 | pub 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. |
23 | pub 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 | |
29 | pub fn new_format<I, F>(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F> |
30 | where |
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 | |
40 | pub fn new_format_default<I>(iter: I, separator: &str) -> Format<'_, I> |
41 | where |
42 | I: Iterator, |
43 | { |
44 | Format { |
45 | sep: separator, |
46 | inner: Cell::new(Some(iter)), |
47 | } |
48 | } |
49 | |
50 | impl<'a, I, F> fmt::Display for FormatWith<'a, I, F> |
51 | where |
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: I, mut format: F) = match self.inner.take() { |
57 | Some(t: (I, F)) => t, |
58 | None => panic!("FormatWith: was already formatted once" ), |
59 | }; |
60 | |
61 | if let Some(fst: ::Item) = iter.next() { |
62 | format(fst, &mut |disp: &dyn fmt::Display| disp.fmt(f))?; |
63 | iter.try_for_each(|elt: ::Item| { |
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 | |
74 | impl<'a, I, F> fmt::Debug for FormatWith<'a, I, F> |
75 | where |
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 | |
84 | impl<'a, I> Format<'a, I> |
85 | where |
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: I = match self.inner.take() { |
94 | Some(t: I) => t, |
95 | None => panic!("Format: was already formatted once" ), |
96 | }; |
97 | |
98 | if let Some(fst: ::Item) = iter.next() { |
99 | cb(&fst, f)?; |
100 | iter.try_for_each(|elt: ::Item| { |
101 | if !self.sep.is_empty() { |
102 | f.write_str(self.sep)?; |
103 | } |
104 | cb(&elt, f) |
105 | })?; |
106 | } |
107 | Ok(()) |
108 | } |
109 | } |
110 | |
111 | macro_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 | |
126 | impl_format! {Display Debug UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} |
127 | |
128 | impl<'a, I, F> Clone for FormatWith<'a, I, F> |
129 | where |
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<'r, 'a, I, F> Drop for PutBackOnDrop<'r, 'a, I, F> { |
139 | fn drop(&mut self) { |
140 | self.into.inner.set(self.inner.take()) |
141 | } |
142 | } |
143 | let pbod: PutBackOnDrop<'_, '_, I, …> = 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 | |
154 | impl<'a, I> Clone for Format<'a, I> |
155 | where |
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<'r, 'a, I> Drop for PutBackOnDrop<'r, 'a, I> { |
165 | fn drop(&mut self) { |
166 | self.into.inner.set(self.inner.take()) |
167 | } |
168 | } |
169 | let pbod: PutBackOnDrop<'_, '_, I> = 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 | } |
179 | |