@@ -49,7 +49,7 @@ pub(crate) fn create_diff(
4949 "\n Difference({} / {}):{}" ,
5050 LineStyle :: extra_actual_style( ) . style( "actual" ) ,
5151 LineStyle :: extra_expected_style( ) . style( "expected" ) ,
52- edit_list_summary ( & edit_list)
52+ edit_list. into_iter ( ) . collect :: < BufferedSummary > ( ) ,
5353 )
5454 . into ( ) ,
5555 edit_distance:: Difference :: Unrelated => "" . into ( ) ,
@@ -85,73 +85,138 @@ pub(crate) fn create_diff_reversed(
8585 "\n Difference({} / {}):{}" ,
8686 LineStyle :: extra_actual_style( ) . style( "actual" ) ,
8787 LineStyle :: extra_expected_style( ) . style( "expected" ) ,
88- edit_list_summary ( & edit_list)
88+ edit_list. into_iter ( ) . collect :: < BufferedSummary > ( ) ,
8989 )
9090 . into ( )
9191 }
9292 edit_distance:: Difference :: Unrelated => "" . into ( ) ,
9393 }
9494}
9595
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+ }
115121
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 ( ) ;
117130 }
118- summary. push_str ( & compress_common_lines ( common_line_buffer) ) ;
119131
120- summary
132+ fn flush_buffer ( & mut self ) {
133+ self . buffer . flush ( & mut self . summary ) . unwrap ( ) ;
134+ }
121135}
122136
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+ }
125161
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." )
131166 }
132- return all_lines ;
167+ self . summary . fmt ( f )
133168 }
169+ }
134170
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+ }
136175
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 ( ( ) )
139184 }
140185
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 ( ( ) )
153219 }
154- truncated_lines
155220}
156221
157222struct LineStyle {
0 commit comments