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> Format<'a, I> |
75 | where |
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: I = match self.inner.take() { |
84 | Some(t: I) => t, |
85 | None => panic!("Format: was already formatted once" ), |
86 | }; |
87 | |
88 | if let Some(fst: ::Item) = iter.next() { |
89 | cb(&fst, f)?; |
90 | iter.try_for_each(|elt: ::Item| { |
91 | if !self.sep.is_empty() { |
92 | f.write_str(self.sep)?; |
93 | } |
94 | cb(&elt, f) |
95 | })?; |
96 | } |
97 | Ok(()) |
98 | } |
99 | } |
100 | |
101 | macro_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 | |
116 | impl_format! {Display Debug UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer} |
117 | |
118 | impl<'a, I, F> Clone for FormatWith<'a, I, F> |
119 | where |
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<'_, '_, I, …> = 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 | |
144 | impl<'a, I> Clone for Format<'a, I> |
145 | where |
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<'_, '_, I> = 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 | } |
169 | |