@@ -261,10 +261,6 @@ impl<T: Write> JsonFormatter<T> {
261261 }
262262}
263263
264- fn naive_json_escape ( input : & str ) -> String {
265- input. replace ( "\\ " , "\\ \\ " ) . replace ( "\" " , "\\ \" " )
266- }
267-
268264impl < T : Write > OutputFormatter for JsonFormatter < T > {
269265 fn write_run_start ( & mut self , len : usize ) -> io:: Result < ( ) > {
270266 self . write_str (
@@ -294,7 +290,7 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
294290 TrFailedMsg ( ref m) => {
295291 format ! ( r#"{{ "type": "test", "event": "failed", "name": "{}", "message": "{}" }}"# ,
296292 desc. name,
297- naive_json_escape ( m) )
293+ EscapedString ( m) )
298294 } ,
299295
300296 TrIgnored => {
@@ -307,16 +303,22 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
307303 desc. name)
308304 } ,
309305
310- TrMetrics ( ref mm) => {
311- format ! ( r#"{{ "type": "metrics", "name": "{}", "metrics": "{}" }}"# ,
312- desc. name,
313- mm. fmt_metrics( ) )
314- } ,
315-
316306 TrBench ( ref bs) => {
317- format ! ( r#"{{ "type": "bench", "name": "{}", "bench": "{}" }}"# ,
307+ let median = bs. ns_iter_summ . median as usize ;
308+ let deviation = ( bs. ns_iter_summ . max - bs. ns_iter_summ . min ) as usize ;
309+
310+ let mbps = if bs. mb_s == 0 {
311+ "" . into ( )
312+ }
313+ else {
314+ format ! ( r#", "mib_per_second": {}"# , bs. mb_s)
315+ } ;
316+
317+ format ! ( r#"{{ "type": "bench", "name": "{}", "median": {}, "deviation": {}{} }}"# ,
318318 desc. name,
319- fmt_bench_samples( bs) )
319+ median,
320+ deviation,
321+ mbps)
320322 } ,
321323 } ;
322324
@@ -330,7 +332,7 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
330332
331333 fn write_run_finish ( & mut self , state : & ConsoleTestState ) -> io:: Result < bool > {
332334
333- self . write_str ( & * format ! ( "{{ \" type\" : \" suite\" ,\
335+ self . write_str ( & * format ! ( "{{ \" type\" : \" suite\" , \
334336 \" event\" : \" {}\" , \
335337 \" passed\" : {}, \
336338 \" failed\" : {}, \
@@ -348,15 +350,78 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
348350
349351 for & ( ref f, ref stdout) in & state. failures {
350352 if !stdout. is_empty ( ) {
351- let output = naive_json_escape ( & * String :: from_utf8_lossy ( stdout) ) ;
352-
353353 self . write_str (
354354 & * format ! ( r#"{{ "type": "test_output", "name": "{}", "output": "{}" }}"# ,
355355 f. name,
356- output ) ) ?;
356+ EscapedString ( & * String :: from_utf8_lossy ( stdout ) ) ) ) ?;
357357 }
358358 }
359359
360360 Ok ( state. failed == 0 )
361361 }
362362}
363+
364+ /// A formatting utility used to print strings with characters in need of escaping.
365+ /// Base code taken form `libserialize::json::escape_str`
366+ struct EscapedString < ' a > ( & ' a str ) ;
367+
368+ impl < ' a > :: std:: fmt:: Display for EscapedString < ' a > {
369+ fn fmt ( & self , f : & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result {
370+ let mut start = 0 ;
371+
372+ for ( i, byte) in self . 0 . bytes ( ) . enumerate ( ) {
373+ let escaped = match byte {
374+ b'"' => "\\ \" " ,
375+ b'\\' => "\\ \\ " ,
376+ b'\x00' => "\\ u0000" ,
377+ b'\x01' => "\\ u0001" ,
378+ b'\x02' => "\\ u0002" ,
379+ b'\x03' => "\\ u0003" ,
380+ b'\x04' => "\\ u0004" ,
381+ b'\x05' => "\\ u0005" ,
382+ b'\x06' => "\\ u0006" ,
383+ b'\x07' => "\\ u0007" ,
384+ b'\x08' => "\\ b" ,
385+ b'\t' => "\\ t" ,
386+ b'\n' => "\\ n" ,
387+ b'\x0b' => "\\ u000b" ,
388+ b'\x0c' => "\\ f" ,
389+ b'\r' => "\\ r" ,
390+ b'\x0e' => "\\ u000e" ,
391+ b'\x0f' => "\\ u000f" ,
392+ b'\x10' => "\\ u0010" ,
393+ b'\x11' => "\\ u0011" ,
394+ b'\x12' => "\\ u0012" ,
395+ b'\x13' => "\\ u0013" ,
396+ b'\x14' => "\\ u0014" ,
397+ b'\x15' => "\\ u0015" ,
398+ b'\x16' => "\\ u0016" ,
399+ b'\x17' => "\\ u0017" ,
400+ b'\x18' => "\\ u0018" ,
401+ b'\x19' => "\\ u0019" ,
402+ b'\x1a' => "\\ u001a" ,
403+ b'\x1b' => "\\ u001b" ,
404+ b'\x1c' => "\\ u001c" ,
405+ b'\x1d' => "\\ u001d" ,
406+ b'\x1e' => "\\ u001e" ,
407+ b'\x1f' => "\\ u001f" ,
408+ b'\x7f' => "\\ u007f" ,
409+ _ => { continue ; }
410+ } ;
411+
412+ if start < i {
413+ f. write_str ( & self . 0 [ start..i] ) ?;
414+ }
415+
416+ f. write_str ( escaped) ?;
417+
418+ start = i + 1 ;
419+ }
420+
421+ if start != self . 0 . len ( ) {
422+ f. write_str ( & self . 0 [ start..] ) ?;
423+ }
424+
425+ Ok ( ( ) )
426+ }
427+ }
0 commit comments