/rust/registry/src/index.crates.io-6f17d22bba15001f/itertools-0.11.0/src/format.rs
Line | Count | Source (jump to first uncovered line) |
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 | 0 | pub fn new_format<I, F>(iter: I, separator: &str, f: F) -> FormatWith<'_, I, F> |
30 | 0 | where |
31 | 0 | I: Iterator, |
32 | 0 | F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, |
33 | 0 | { |
34 | 0 | FormatWith { |
35 | 0 | sep: separator, |
36 | 0 | inner: Cell::new(Some((iter, f))), |
37 | 0 | } |
38 | 0 | } |
39 | | |
40 | 0 | pub fn new_format_default<I>(iter: I, separator: &str) -> Format<'_, I> |
41 | 0 | where |
42 | 0 | I: Iterator, |
43 | 0 | { |
44 | 0 | Format { |
45 | 0 | sep: separator, |
46 | 0 | inner: Cell::new(Some(iter)), |
47 | 0 | } |
48 | 0 | } |
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 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
56 | 0 | let (mut iter, mut format) = match self.inner.take() { |
57 | 0 | Some(t) => t, |
58 | 0 | None => panic!("FormatWith: was already formatted once"), |
59 | | }; |
60 | | |
61 | 0 | if let Some(fst) = iter.next() { |
62 | 0 | format(fst, &mut |disp: &dyn fmt::Display| disp.fmt(f))?; |
63 | 0 | iter.try_for_each(|elt| { |
64 | 0 | if !self.sep.is_empty() { |
65 | 0 | f.write_str(self.sep)?; |
66 | 0 | } |
67 | 0 | format(elt, &mut |disp: &dyn fmt::Display| disp.fmt(f)) |
68 | 0 | })?; |
69 | 0 | } |
70 | 0 | Ok(()) |
71 | 0 | } |
72 | | } |
73 | | |
74 | | impl<'a, I> Format<'a, I> |
75 | | where |
76 | | I: Iterator, |
77 | | { |
78 | 0 | fn format( |
79 | 0 | &self, |
80 | 0 | f: &mut fmt::Formatter, |
81 | 0 | cb: fn(&I::Item, &mut fmt::Formatter) -> fmt::Result, |
82 | 0 | ) -> fmt::Result { |
83 | 0 | let mut iter = match self.inner.take() { |
84 | 0 | Some(t) => t, |
85 | 0 | None => panic!("Format: was already formatted once"), |
86 | | }; |
87 | | |
88 | 0 | if let Some(fst) = iter.next() { |
89 | 0 | cb(&fst, f)?; |
90 | 0 | iter.try_for_each(|elt| { |
91 | 0 | if !self.sep.is_empty() { |
92 | 0 | f.write_str(self.sep)?; |
93 | 0 | } |
94 | 0 | cb(&elt, f) |
95 | 0 | })?; |
96 | 0 | } |
97 | 0 | Ok(()) |
98 | 0 | } |
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 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
109 | 0 | self.format(f, fmt::$fmt_trait::fmt) |
110 | 0 | } Unexecuted instantiation: <itertools::format::Format<_> as core::fmt::Octal>::fmt Unexecuted instantiation: <itertools::format::Format<_> as core::fmt::UpperHex>::fmt Unexecuted instantiation: <itertools::format::Format<_> as core::fmt::Binary>::fmt Unexecuted instantiation: <itertools::format::Format<_> as core::fmt::LowerExp>::fmt Unexecuted instantiation: <itertools::format::Format<_> as core::fmt::Pointer>::fmt Unexecuted instantiation: <itertools::format::Format<_> as core::fmt::Debug>::fmt Unexecuted instantiation: <itertools::format::Format<_> as core::fmt::LowerHex>::fmt Unexecuted instantiation: <itertools::format::Format<_> as core::fmt::UpperExp>::fmt Unexecuted instantiation: <itertools::format::Format<_> as core::fmt::Display>::fmt |
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 | 0 | fn clone(&self) -> Self { |
123 | 0 | struct PutBackOnDrop<'r, 'a, I, F> { |
124 | 0 | into: &'r FormatWith<'a, I, F>, |
125 | 0 | inner: Option<(I, F)>, |
126 | 0 | } |
127 | 0 | // This ensures we preserve the state of the original `FormatWith` if `Clone` panics |
128 | 0 | impl<'r, 'a, I, F> Drop for PutBackOnDrop<'r, 'a, I, F> { |
129 | 0 | fn drop(&mut self) { |
130 | 0 | self.into.inner.set(self.inner.take()) |
131 | 0 | } |
132 | 0 | } |
133 | 0 | let pbod = PutBackOnDrop { |
134 | 0 | inner: self.inner.take(), |
135 | 0 | into: self, |
136 | 0 | }; |
137 | 0 | Self { |
138 | 0 | inner: Cell::new(pbod.inner.clone()), |
139 | 0 | sep: self.sep, |
140 | 0 | } |
141 | 0 | } |
142 | | } |
143 | | |
144 | | impl<'a, I> Clone for Format<'a, I> |
145 | | where |
146 | | I: Clone, |
147 | | { |
148 | 0 | fn clone(&self) -> Self { |
149 | 0 | struct PutBackOnDrop<'r, 'a, I> { |
150 | 0 | into: &'r Format<'a, I>, |
151 | 0 | inner: Option<I>, |
152 | 0 | } |
153 | 0 | // This ensures we preserve the state of the original `FormatWith` if `Clone` panics |
154 | 0 | impl<'r, 'a, I> Drop for PutBackOnDrop<'r, 'a, I> { |
155 | 0 | fn drop(&mut self) { |
156 | 0 | self.into.inner.set(self.inner.take()) |
157 | 0 | } |
158 | 0 | } |
159 | 0 | let pbod = PutBackOnDrop { |
160 | 0 | inner: self.inner.take(), |
161 | 0 | into: self, |
162 | 0 | }; |
163 | 0 | Self { |
164 | 0 | inner: Cell::new(pbod.inner.clone()), |
165 | 0 | sep: self.sep, |
166 | 0 | } |
167 | 0 | } |
168 | | } |