1use std::cell::Cell;
2use std::fmt;
3
4pub struct FormatWith<'a, I, F> {
11 sep: &'a str,
12 inner: Cell<Option<(I, F)>>,
14}
15
16pub struct Format<'a, I> {
24 sep: &'a str,
25 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 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 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}