@@ -49,7 +49,7 @@ pub(crate) fn create_diff(
49
49
"\n Difference({} / {}):{}" ,
50
50
LineStyle :: extra_actual_style( ) . style( "actual" ) ,
51
51
LineStyle :: extra_expected_style( ) . style( "expected" ) ,
52
- edit_list_summary ( & edit_list)
52
+ edit_list. into_iter ( ) . collect :: < BufferedSummary > ( ) ,
53
53
)
54
54
. into ( ) ,
55
55
edit_distance:: Difference :: Unrelated => "" . into ( ) ,
@@ -85,73 +85,138 @@ pub(crate) fn create_diff_reversed(
85
85
"\n Difference({} / {}):{}" ,
86
86
LineStyle :: extra_actual_style( ) . style( "actual" ) ,
87
87
LineStyle :: extra_expected_style( ) . style( "expected" ) ,
88
- edit_list_summary ( & edit_list)
88
+ edit_list. into_iter ( ) . collect :: < BufferedSummary > ( ) ,
89
89
)
90
90
. into ( )
91
91
}
92
92
edit_distance:: Difference :: Unrelated => "" . into ( ) ,
93
93
}
94
94
}
95
95
96
- fn edit_list_summary ( edit_list : & [ edit_distance:: Edit < & str > ] ) -> String {
97
- let mut summary = String :: new ( ) ;
98
- // Use to collect common line and compress them.
99
- let mut common_line_buffer = vec ! [ ] ;
100
- for edit in edit_list {
101
- let ( style, line) = match edit {
102
- edit_distance:: Edit :: Both ( same) => {
103
- common_line_buffer. push ( * same) ;
104
- continue ;
105
- }
106
- edit_distance:: Edit :: ExtraActual ( actual) => ( LineStyle :: extra_actual_style ( ) , * actual) ,
107
- edit_distance:: Edit :: ExtraExpected ( expected) => {
108
- ( LineStyle :: extra_expected_style ( ) , * expected)
109
- }
110
- edit_distance:: Edit :: AdditionalActual => {
111
- ( LineStyle :: comment_style ( ) , "<---- remaining lines omitted ---->" )
112
- }
113
- } ;
114
- summary. push_str ( & compress_common_lines ( std:: mem:: take ( & mut common_line_buffer) ) ) ;
96
+ struct BufferedSummary < ' a > {
97
+ summary : String ,
98
+ buffer : Buffer < ' a > ,
99
+ }
100
+
101
+ impl < ' a > BufferedSummary < ' a > {
102
+ fn new ( ) -> Self {
103
+ Self { summary : String :: new ( ) , buffer : Buffer :: CommonLineBuffer ( vec ! [ ] ) }
104
+ }
105
+
106
+ fn feed_common_lines ( & mut self , common_line : & ' a str ) {
107
+ let Buffer :: CommonLineBuffer ( ref mut common_lines) = self . buffer ;
108
+ common_lines. push ( common_line) ;
109
+ }
110
+ fn feed_extra_actual ( & mut self , extra_actual : & ' a str ) {
111
+ self . buffer . flush ( & mut self . summary ) . unwrap ( ) ;
112
+ write ! ( & mut self . summary, "\n {}" , LineStyle :: extra_actual_style( ) . style( extra_actual) )
113
+ . unwrap ( ) ;
114
+ }
115
+
116
+ fn feed_extra_expected ( & mut self , extra_expected : & str ) {
117
+ self . flush_buffer ( ) ;
118
+ write ! ( & mut self . summary, "\n {}" , LineStyle :: extra_expected_style( ) . style( extra_expected) )
119
+ . unwrap ( ) ;
120
+ }
115
121
116
- write ! ( & mut summary, "\n {}" , style. style( line) ) . unwrap ( ) ;
122
+ fn feed_additional_actual ( & mut self ) {
123
+ self . flush_buffer ( ) ;
124
+ write ! (
125
+ & mut self . summary,
126
+ "\n {}" ,
127
+ LineStyle :: comment_style( ) . style( "<---- remaining lines omitted ---->" )
128
+ )
129
+ . unwrap ( ) ;
117
130
}
118
- summary. push_str ( & compress_common_lines ( common_line_buffer) ) ;
119
131
120
- summary
132
+ fn flush_buffer ( & mut self ) {
133
+ self . buffer . flush ( & mut self . summary ) . unwrap ( ) ;
134
+ }
121
135
}
122
136
123
- // The number of the lines kept before and after the compressed lines.
124
- const COMMON_LINES_CONTEXT_SIZE : usize = 2 ;
137
+ impl < ' a > FromIterator < edit_distance:: Edit < & ' a str > > for BufferedSummary < ' a > {
138
+ fn from_iter < T : IntoIterator < Item = edit_distance:: Edit < & ' a str > > > ( iter : T ) -> Self {
139
+ let mut buffered_summary = BufferedSummary :: new ( ) ;
140
+ for edit in iter {
141
+ match edit {
142
+ edit_distance:: Edit :: Both ( same) => {
143
+ buffered_summary. feed_common_lines ( same) ;
144
+ }
145
+ edit_distance:: Edit :: ExtraActual ( actual) => {
146
+ buffered_summary. feed_extra_actual ( actual) ;
147
+ }
148
+ edit_distance:: Edit :: ExtraExpected ( expected) => {
149
+ buffered_summary. feed_extra_expected ( expected) ;
150
+ }
151
+ edit_distance:: Edit :: AdditionalActual => {
152
+ buffered_summary. feed_additional_actual ( ) ;
153
+ }
154
+ } ;
155
+ }
156
+ buffered_summary. flush_buffer ( ) ;
157
+
158
+ buffered_summary
159
+ }
160
+ }
125
161
126
- fn compress_common_lines ( common_lines : Vec < & str > ) -> String {
127
- if common_lines. len ( ) <= 2 * COMMON_LINES_CONTEXT_SIZE + 1 {
128
- let mut all_lines = String :: new ( ) ;
129
- for line in common_lines {
130
- write ! ( & mut all_lines, "\n {}" , LineStyle :: unchanged_style( ) . style( line) ) . unwrap ( ) ;
162
+ impl < ' a > Display for BufferedSummary < ' a > {
163
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
164
+ if !matches ! ( self . buffer, Buffer :: CommonLineBuffer ( ref b) if b. is_empty( ) ) {
165
+ panic ! ( "Buffer is not empty. This is a bug in gtest_rust." )
131
166
}
132
- return all_lines ;
167
+ self . summary . fmt ( f )
133
168
}
169
+ }
134
170
135
- let mut truncated_lines = String :: new ( ) ;
171
+ // This needs to be an enum as there will be in a follow-up PR new types of buffer, most likely actual and expected lines, to be compared with expected and actual lines for line to line comparison.
172
+ enum Buffer < ' a > {
173
+ CommonLineBuffer ( Vec < & ' a str > ) ,
174
+ }
136
175
137
- for line in & common_lines[ 0 ..COMMON_LINES_CONTEXT_SIZE ] {
138
- write ! ( & mut truncated_lines, "\n {}" , LineStyle :: unchanged_style( ) . style( line) ) . unwrap ( ) ;
176
+ impl < ' a > Buffer < ' a > {
177
+ fn flush ( & mut self , writer : impl std:: fmt:: Write ) -> std:: fmt:: Result {
178
+ match self {
179
+ Buffer :: CommonLineBuffer ( common_lines) => {
180
+ Self :: flush_common_lines ( std:: mem:: take ( common_lines) , writer) ?
181
+ }
182
+ } ;
183
+ Ok ( ( ) )
139
184
}
140
185
141
- write ! (
142
- & mut truncated_lines,
143
- "\n {}" ,
144
- LineStyle :: comment_style( ) . style( & format!(
145
- "<---- {} common lines omitted ---->" ,
146
- common_lines. len( ) - 2 * COMMON_LINES_CONTEXT_SIZE
147
- ) ) ,
148
- )
149
- . unwrap ( ) ;
150
-
151
- for line in & common_lines[ common_lines. len ( ) - COMMON_LINES_CONTEXT_SIZE ..common_lines. len ( ) ] {
152
- write ! ( & mut truncated_lines, "\n {}" , LineStyle :: unchanged_style( ) . style( line) ) . unwrap ( ) ;
186
+ fn flush_common_lines (
187
+ common_lines : Vec < & ' a str > ,
188
+ mut writer : impl std:: fmt:: Write ,
189
+ ) -> std:: fmt:: Result {
190
+ // The number of the lines kept before and after the compressed lines.
191
+ const COMMON_LINES_CONTEXT_SIZE : usize = 2 ;
192
+
193
+ if common_lines. len ( ) <= 2 * COMMON_LINES_CONTEXT_SIZE + 1 {
194
+ for line in common_lines {
195
+ write ! ( writer, "\n {}" , LineStyle :: unchanged_style( ) . style( line) ) ?;
196
+ }
197
+ return Ok ( ( ) ) ;
198
+ }
199
+
200
+ for line in & common_lines[ 0 ..COMMON_LINES_CONTEXT_SIZE ] {
201
+ write ! ( writer, "\n {}" , LineStyle :: unchanged_style( ) . style( line) ) ?;
202
+ }
203
+
204
+ write ! (
205
+ writer,
206
+ "\n {}" ,
207
+ LineStyle :: comment_style( ) . style( & format!(
208
+ "<---- {} common lines omitted ---->" ,
209
+ common_lines. len( ) - 2 * COMMON_LINES_CONTEXT_SIZE
210
+ ) ) ,
211
+ ) ?;
212
+
213
+ for line in
214
+ & common_lines[ common_lines. len ( ) - COMMON_LINES_CONTEXT_SIZE ..common_lines. len ( ) ]
215
+ {
216
+ write ! ( writer, "\n {}" , LineStyle :: unchanged_style( ) . style( line) ) ?;
217
+ }
218
+ Ok ( ( ) )
153
219
}
154
- truncated_lines
155
220
}
156
221
157
222
struct LineStyle {
0 commit comments