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
new_format<I, F>(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F> where I: Iterator, F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result,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
new_format_default<I>(iter: I, separator: &str) -> Format<'_, I> where I: Iterator,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 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result55 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
74 impl<'a, I> Format<'a, I>
75 where
76 I: Iterator,
77 {
format( &self, f: &mut fmt::Formatter, cb: fn(&I::Item, &mut fmt::Formatter) -> fmt::Result, ) -> fmt::Result78 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
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 {
clone(&self) -> Self122 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
144 impl<'a, I> Clone for Format<'a, I>
145 where
146 I: Clone,
147 {
clone(&self) -> Self148 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 }
169