1
+ use std:: cell:: Cell ;
1
2
use std:: fmt;
2
- use std:: cell:: RefCell ;
3
3
4
4
/// Format all iterator elements lazily, separated by `sep`.
5
5
///
6
6
/// The format value can only be formatted once, after that the iterator is
7
7
/// exhausted.
8
8
///
9
9
/// See [`.format_with()`](crate::Itertools::format_with) for more information.
10
- #[ derive( Clone ) ]
11
10
pub struct FormatWith < ' a , I , F > {
12
11
sep : & ' a str ,
13
12
/// FormatWith uses interior mutability because Display::fmt takes &self.
14
- inner : RefCell < Option < ( I , F ) > > ,
13
+ inner : Cell < Option < ( I , F ) > > ,
15
14
}
16
15
17
16
/// Format all iterator elements lazily, separated by `sep`.
@@ -21,38 +20,40 @@ pub struct FormatWith<'a, I, F> {
21
20
///
22
21
/// See [`.format()`](crate::Itertools::format)
23
22
/// for more information.
24
- #[ derive( Clone ) ]
25
23
pub struct Format < ' a , I > {
26
24
sep : & ' a str ,
27
25
/// Format uses interior mutability because Display::fmt takes &self.
28
- inner : RefCell < Option < I > > ,
26
+ inner : Cell < Option < I > > ,
29
27
}
30
28
31
29
pub fn new_format < I , F > ( iter : I , separator : & str , f : F ) -> FormatWith < ' _ , I , F >
32
- where I : Iterator ,
33
- F : FnMut ( I :: Item , & mut dyn FnMut ( & dyn fmt:: Display ) -> fmt:: Result ) -> fmt:: Result
30
+ where
31
+ I : Iterator ,
32
+ F : FnMut ( I :: Item , & mut dyn FnMut ( & dyn fmt:: Display ) -> fmt:: Result ) -> fmt:: Result ,
34
33
{
35
34
FormatWith {
36
35
sep : separator,
37
- inner : RefCell :: new ( Some ( ( iter, f) ) ) ,
36
+ inner : Cell :: new ( Some ( ( iter, f) ) ) ,
38
37
}
39
38
}
40
39
41
40
pub fn new_format_default < I > ( iter : I , separator : & str ) -> Format < ' _ , I >
42
- where I : Iterator ,
41
+ where
42
+ I : Iterator ,
43
43
{
44
44
Format {
45
45
sep : separator,
46
- inner : RefCell :: new ( Some ( iter) ) ,
46
+ inner : Cell :: new ( Some ( iter) ) ,
47
47
}
48
48
}
49
49
50
50
impl < ' a , I , F > fmt:: Display for FormatWith < ' a , I , F >
51
- where I : Iterator ,
52
- F : FnMut ( I :: Item , & mut dyn FnMut ( & dyn fmt:: Display ) -> fmt:: Result ) -> fmt:: Result
51
+ where
52
+ I : Iterator ,
53
+ F : FnMut ( I :: Item , & mut dyn FnMut ( & dyn fmt:: Display ) -> fmt:: Result ) -> fmt:: Result ,
53
54
{
54
55
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
55
- let ( mut iter, mut format) = match self . inner . borrow_mut ( ) . take ( ) {
56
+ let ( mut iter, mut format) = match self . inner . take ( ) {
56
57
Some ( t) => t,
57
58
None => panic ! ( "FormatWith: was already formatted once" ) ,
58
59
} ;
@@ -71,12 +72,15 @@ impl<'a, I, F> fmt::Display for FormatWith<'a, I, F>
71
72
}
72
73
73
74
impl < ' a , I > Format < ' a , I >
74
- where I : Iterator ,
75
+ where
76
+ I : Iterator ,
75
77
{
76
- fn format < F > ( & self , f : & mut fmt:: Formatter , mut cb : F ) -> fmt:: Result
77
- where F : FnMut ( & I :: Item , & mut fmt:: Formatter ) -> fmt:: Result ,
78
- {
79
- let mut iter = match self . inner . borrow_mut ( ) . take ( ) {
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 = match self . inner . take ( ) {
80
84
Some ( t) => t,
81
85
None => panic ! ( "Format: was already formatted once" ) ,
82
86
} ;
@@ -109,5 +113,56 @@ macro_rules! impl_format {
109
113
}
110
114
}
111
115
112
- impl_format ! { Display Debug
113
- UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer }
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 {
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 {
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
+ }
0 commit comments