@@ -595,13 +595,23 @@ impl<'a> ::Encoder<io::IoError> for Encoder<'a> {
595
595
/// compact data
596
596
pub struct PrettyEncoder < ' a > {
597
597
writer : & ' a mut io:: Writer ,
598
+ curr_indent : uint ,
598
599
indent : uint ,
599
600
}
600
601
601
602
impl < ' a > PrettyEncoder < ' a > {
602
603
/// Creates a new encoder whose output will be written to the specified writer
603
604
pub fn new < ' a > ( writer : & ' a mut io:: Writer ) -> PrettyEncoder < ' a > {
604
- PrettyEncoder { writer : writer, indent : 0 }
605
+ PrettyEncoder { writer : writer, curr_indent : 0 , indent : 2 , }
606
+ }
607
+
608
+ /// Set the number of spaces to indent for each level.
609
+ /// This is safe to set during encoding.
610
+ pub fn set_indent < ' a > ( & mut self , indent : uint ) {
611
+ // self.indent very well could be 0 so we need to use checked division.
612
+ let level = self . curr_indent . checked_div ( & self . indent ) . unwrap_or ( 0 ) ;
613
+ self . indent = indent;
614
+ self . curr_indent = level * self . indent ;
605
615
}
606
616
}
607
617
@@ -656,15 +666,15 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
656
666
if cnt == 0 {
657
667
escape_str( self . writer, name)
658
668
} else {
659
- self . indent += 2 ;
669
+ self . curr_indent += self . indent ;
660
670
try!( write ! ( self . writer, "[\n " ) ) ;
661
- try!( spaces( self . writer, self . indent ) ) ;
671
+ try!( spaces( self . writer, self . curr_indent ) ) ;
662
672
try!( escape_str( self . writer, name) ) ;
663
673
try!( write ! ( self . writer, ",\n " ) ) ;
664
674
try!( f ( self ) ) ;
665
- self . indent -= 2 ;
675
+ self . curr_indent -= self . indent ;
666
676
try ! ( write!( self . writer, "\n " ) ) ;
667
- try!( spaces( self . writer, self . indent ) ) ;
677
+ try ! ( spaces( self . writer, self . curr_indent ) ) ;
668
678
write ! ( self . writer, "]" )
669
679
}
670
680
}
@@ -675,7 +685,7 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
675
685
if idx != 0 {
676
686
try!( write ! ( self . writer, ",\n " ) ) ;
677
687
}
678
- try!( spaces( self . writer, self . indent ) ) ;
688
+ try!( spaces( self . writer, self . curr_indent ) ) ;
679
689
f ( self )
680
690
}
681
691
@@ -703,11 +713,11 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
703
713
write ! ( self . writer, "{{}}" )
704
714
} else {
705
715
try!( write ! ( self . writer, "{{" ) ) ;
706
- self . indent += 2 ;
716
+ self . curr_indent += self . indent ;
707
717
try!( f ( self ) ) ;
708
- self . indent -= 2 ;
718
+ self . curr_indent -= self . indent ;
709
719
try!( write ! ( self . writer, "\n " ) ) ;
710
- try!( spaces( self . writer, self . indent ) ) ;
720
+ try!( spaces( self . writer, self . curr_indent ) ) ;
711
721
write ! ( self . writer, "}}" )
712
722
}
713
723
}
@@ -721,7 +731,7 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
721
731
} else {
722
732
try!( write ! ( self . writer, ",\n " ) ) ;
723
733
}
724
- try!( spaces( self . writer, self . indent ) ) ;
734
+ try!( spaces( self . writer, self . curr_indent ) ) ;
725
735
try!( escape_str( self . writer, name) ) ;
726
736
try!( write ! ( self . writer, ": " ) ) ;
727
737
f ( self )
@@ -765,11 +775,11 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
765
775
write ! ( self . writer, "[]" )
766
776
} else {
767
777
try!( write ! ( self . writer, "[" ) ) ;
768
- self . indent += 2 ;
778
+ self . curr_indent += self . indent ;
769
779
try!( f( self ) ) ;
770
- self . indent -= 2 ;
780
+ self . curr_indent -= self . indent ;
771
781
try!( write ! ( self . writer, "\n " ) ) ;
772
- try!( spaces( self . writer, self . indent ) ) ;
782
+ try!( spaces( self . writer, self . curr_indent ) ) ;
773
783
write ! ( self . writer, "]" )
774
784
}
775
785
}
@@ -782,7 +792,7 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
782
792
} else {
783
793
try!( write ! ( self . writer, ",\n " ) ) ;
784
794
}
785
- try!( spaces( self . writer, self . indent ) ) ;
795
+ try!( spaces( self . writer, self . curr_indent ) ) ;
786
796
f( self )
787
797
}
788
798
@@ -793,11 +803,11 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
793
803
write ! ( self . writer, "{{}}" )
794
804
} else {
795
805
try!( write ! ( self . writer, "{{" ) ) ;
796
- self . indent += 2 ;
806
+ self . curr_indent += self . indent ;
797
807
try!( f( self ) ) ;
798
- self . indent -= 2 ;
808
+ self . curr_indent -= self . indent ;
799
809
try!( write ! ( self . writer, "\n " ) ) ;
800
- try!( spaces( self . writer, self . indent ) ) ;
810
+ try!( spaces( self . writer, self . curr_indent ) ) ;
801
811
write ! ( self . writer, "}}" )
802
812
}
803
813
}
@@ -810,7 +820,7 @@ impl<'a> ::Encoder<io::IoError> for PrettyEncoder<'a> {
810
820
} else {
811
821
try!( write ! ( self . writer, ",\n " ) ) ;
812
822
}
813
- try!( spaces( self . writer, self . indent ) ) ;
823
+ try!( spaces( self . writer, self . curr_indent ) ) ;
814
824
// ref #12967, make sure to wrap a key in double quotes,
815
825
// in the event that its of a type that omits them (eg numbers)
816
826
let mut buf = MemWriter :: new( ) ;
@@ -3197,6 +3207,63 @@ mod tests {
3197
3207
}
3198
3208
}
3199
3209
3210
+ #[ test]
3211
+ fn test_prettyencoder_indent_level_param ( ) {
3212
+ use std:: str:: from_utf8;
3213
+ use std:: io:: MemWriter ;
3214
+ use std:: collections:: TreeMap ;
3215
+
3216
+ let mut tree = TreeMap :: new ( ) ;
3217
+
3218
+ tree. insert ( "hello" . into_string ( ) , String ( "guten tag" . into_string ( ) ) ) ;
3219
+ tree. insert ( "goodbye" . into_string ( ) , String ( "sayonara" . into_string ( ) ) ) ;
3220
+
3221
+ let json = List (
3222
+ // The following layout below should look a lot like
3223
+ // the pretty-printed JSON (indent * x)
3224
+ vec !
3225
+ ( // 0x
3226
+ String ( "greetings" . into_string( ) ) , // 1x
3227
+ Object ( tree) , // 1x + 2x + 2x + 1x
3228
+ ) // 0x
3229
+ // End JSON list (7 lines)
3230
+ ) ;
3231
+
3232
+ // Helper function for counting indents
3233
+ fn indents ( source : & str ) -> uint {
3234
+ let trimmed = source. trim_left_chars ( ' ' ) ;
3235
+ source. len ( ) - trimmed. len ( )
3236
+ }
3237
+
3238
+ // Test up to 4 spaces of indents (more?)
3239
+ for i in range ( 0 , 4 u) {
3240
+ let mut writer = MemWriter :: new ( ) ;
3241
+ {
3242
+ let ref mut encoder = PrettyEncoder :: new ( & mut writer) ;
3243
+ encoder. set_indent ( i) ;
3244
+ json. encode ( encoder) . unwrap ( ) ;
3245
+ }
3246
+
3247
+ let bytes = writer. unwrap ( ) ;
3248
+ let printed = from_utf8 ( bytes. as_slice ( ) ) . unwrap ( ) ;
3249
+
3250
+ // Check for indents at each line
3251
+ let lines: Vec < & str > = printed. lines ( ) . collect ( ) ;
3252
+ assert_eq ! ( lines. len( ) , 7 ) ; // JSON should be 7 lines
3253
+
3254
+ assert_eq ! ( indents( lines[ 0 ] ) , 0 * i) ; // [
3255
+ assert_eq ! ( indents( lines[ 1 ] ) , 1 * i) ; // "greetings",
3256
+ assert_eq ! ( indents( lines[ 2 ] ) , 1 * i) ; // {
3257
+ assert_eq ! ( indents( lines[ 3 ] ) , 2 * i) ; // "hello": "guten tag",
3258
+ assert_eq ! ( indents( lines[ 4 ] ) , 2 * i) ; // "goodbye": "sayonara"
3259
+ assert_eq ! ( indents( lines[ 5 ] ) , 1 * i) ; // },
3260
+ assert_eq ! ( indents( lines[ 6 ] ) , 0 * i) ; // ]
3261
+
3262
+ // Finally, test that the pretty-printed JSON is valid
3263
+ from_str ( printed) . ok ( ) . expect ( "Pretty-printed JSON is invalid!" ) ;
3264
+ }
3265
+ }
3266
+
3200
3267
#[ test]
3201
3268
fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key ( ) {
3202
3269
use std:: collections:: HashMap ;
0 commit comments