1
1
use crate :: fmt;
2
2
3
- struct PadAdapter < ' a > {
4
- buf : & ' a mut ( dyn fmt:: Write + ' a ) ,
3
+ struct PadAdapter < ' buf , ' state > {
4
+ buf : & ' buf mut ( dyn fmt:: Write + ' buf ) ,
5
+ state : & ' state mut PadAdapterState ,
6
+ }
7
+
8
+ struct PadAdapterState {
5
9
on_newline : bool ,
6
10
}
7
11
8
- impl < ' a > PadAdapter < ' a > {
9
- fn wrap < ' b , ' c : ' a +' b > ( fmt : & ' c mut fmt:: Formatter < ' _ > , slot : & ' b mut Option < Self > )
10
- -> fmt:: Formatter < ' b > {
12
+ impl Default for PadAdapterState {
13
+ fn default ( ) -> Self {
14
+ PadAdapterState {
15
+ on_newline : true ,
16
+ }
17
+ }
18
+ }
19
+
20
+ impl < ' buf , ' state > PadAdapter < ' buf , ' state > {
21
+ fn wrap < ' slot , ' fmt : ' buf +' slot > ( fmt : & ' fmt mut fmt:: Formatter < ' _ > ,
22
+ slot : & ' slot mut Option < Self > ,
23
+ state : & ' state mut PadAdapterState ) -> fmt:: Formatter < ' slot > {
11
24
fmt. wrap_buf ( move |buf| {
12
25
* slot = Some ( PadAdapter {
13
26
buf,
14
- on_newline : true ,
27
+ state ,
15
28
} ) ;
16
29
slot. as_mut ( ) . unwrap ( )
17
30
} )
18
31
}
19
32
}
20
33
21
- impl fmt:: Write for PadAdapter < ' _ > {
34
+ impl fmt:: Write for PadAdapter < ' _ , ' _ > {
22
35
fn write_str ( & mut self , mut s : & str ) -> fmt:: Result {
23
36
while !s. is_empty ( ) {
24
- if self . on_newline {
37
+ if self . state . on_newline {
25
38
self . buf . write_str ( " " ) ?;
26
39
}
27
40
28
41
let split = match s. find ( '\n' ) {
29
42
Some ( pos) => {
30
- self . on_newline = true ;
43
+ self . state . on_newline = true ;
31
44
pos + 1
32
45
}
33
46
None => {
34
- self . on_newline = false ;
47
+ self . state . on_newline = false ;
35
48
s. len ( )
36
49
}
37
50
} ;
@@ -133,7 +146,8 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
133
146
self . fmt . write_str ( " {\n " ) ?;
134
147
}
135
148
let mut slot = None ;
136
- let mut writer = PadAdapter :: wrap ( & mut self . fmt , & mut slot) ;
149
+ let mut state = Default :: default ( ) ;
150
+ let mut writer = PadAdapter :: wrap ( & mut self . fmt , & mut slot, & mut state) ;
137
151
writer. write_str ( name) ?;
138
152
writer. write_str ( ": " ) ?;
139
153
value. fmt ( & mut writer) ?;
@@ -279,7 +293,8 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
279
293
self . fmt . write_str ( "(\n " ) ?;
280
294
}
281
295
let mut slot = None ;
282
- let mut writer = PadAdapter :: wrap ( & mut self . fmt , & mut slot) ;
296
+ let mut state = Default :: default ( ) ;
297
+ let mut writer = PadAdapter :: wrap ( & mut self . fmt , & mut slot, & mut state) ;
283
298
value. fmt ( & mut writer) ?;
284
299
writer. write_str ( ",\n " )
285
300
} else {
@@ -349,7 +364,8 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
349
364
self . fmt . write_str ( "\n " ) ?;
350
365
}
351
366
let mut slot = None ;
352
- let mut writer = PadAdapter :: wrap ( & mut self . fmt , & mut slot) ;
367
+ let mut state = Default :: default ( ) ;
368
+ let mut writer = PadAdapter :: wrap ( & mut self . fmt , & mut slot, & mut state) ;
353
369
entry. fmt ( & mut writer) ?;
354
370
writer. write_str ( ",\n " )
355
371
} else {
@@ -676,6 +692,9 @@ pub struct DebugMap<'a, 'b: 'a> {
676
692
fmt : & ' a mut fmt:: Formatter < ' b > ,
677
693
result : fmt:: Result ,
678
694
has_fields : bool ,
695
+ has_key : bool ,
696
+ // The state of newlines is tracked between keys and values
697
+ state : PadAdapterState ,
679
698
}
680
699
681
700
pub fn debug_map_new < ' a , ' b > ( fmt : & ' a mut fmt:: Formatter < ' b > ) -> DebugMap < ' a , ' b > {
@@ -684,6 +703,8 @@ pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b
684
703
fmt,
685
704
result,
686
705
has_fields : false ,
706
+ has_key : false ,
707
+ state : Default :: default ( ) ,
687
708
}
688
709
}
689
710
@@ -712,25 +733,121 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
712
733
/// ```
713
734
#[ stable( feature = "debug_builders" , since = "1.2.0" ) ]
714
735
pub fn entry ( & mut self , key : & dyn fmt:: Debug , value : & dyn fmt:: Debug ) -> & mut DebugMap < ' a , ' b > {
736
+ self . key ( key) . value ( value)
737
+ }
738
+
739
+ /// Adds the key part of a new entry to the map output.
740
+ ///
741
+ /// This method, together with `value`, is an alternative to `entry` that
742
+ /// can be used when the complete entry isn't known upfront. Prefer the `entry`
743
+ /// method when it's possible to use.
744
+ ///
745
+ /// # Panics
746
+ ///
747
+ /// `key` must be called before `value` and each call to `key` must be followed
748
+ /// by a corresponding call to `value`. Otherwise this method will panic.
749
+ ///
750
+ /// # Examples
751
+ ///
752
+ /// ```
753
+ /// use std::fmt;
754
+ ///
755
+ /// struct Foo(Vec<(String, i32)>);
756
+ ///
757
+ /// impl fmt::Debug for Foo {
758
+ /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
759
+ /// fmt.debug_map()
760
+ /// .key(&"whole").value(&self.0) // We add the "whole" entry.
761
+ /// .finish()
762
+ /// }
763
+ /// }
764
+ ///
765
+ /// assert_eq!(
766
+ /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
767
+ /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
768
+ /// );
769
+ /// ```
770
+ #[ unstable( feature = "debug_map_key_value" ,
771
+ reason = "recently added" ,
772
+ issue = "62482" ) ]
773
+ pub fn key ( & mut self , key : & dyn fmt:: Debug ) -> & mut DebugMap < ' a , ' b > {
774
+ assert ! ( !self . has_key, "attempted to begin a new map entry \
775
+ without completing the previous one") ;
776
+
715
777
self . result = self . result . and_then ( |_| {
716
778
if self . is_pretty ( ) {
717
779
if !self . has_fields {
718
780
self . fmt . write_str ( "\n " ) ?;
719
781
}
720
782
let mut slot = None ;
721
- let mut writer = PadAdapter :: wrap ( & mut self . fmt , & mut slot) ;
783
+ self . state = Default :: default ( ) ;
784
+ let mut writer = PadAdapter :: wrap ( & mut self . fmt , & mut slot, & mut self . state ) ;
722
785
key. fmt ( & mut writer) ?;
723
786
writer. write_str ( ": " ) ?;
724
- value. fmt ( & mut writer) ?;
725
- writer. write_str ( ",\n " )
726
787
} else {
727
788
if self . has_fields {
728
789
self . fmt . write_str ( ", " ) ?
729
790
}
730
791
key. fmt ( self . fmt ) ?;
731
792
self . fmt . write_str ( ": " ) ?;
732
- value. fmt ( self . fmt )
733
793
}
794
+
795
+ self . has_key = true ;
796
+ Ok ( ( ) )
797
+ } ) ;
798
+
799
+ self
800
+ }
801
+
802
+ /// Adds the value part of a new entry to the map output.
803
+ ///
804
+ /// This method, together with `key`, is an alternative to `entry` that
805
+ /// can be used when the complete entry isn't known upfront. Prefer the `entry`
806
+ /// method when it's possible to use.
807
+ ///
808
+ /// # Panics
809
+ ///
810
+ /// `key` must be called before `value` and each call to `key` must be followed
811
+ /// by a corresponding call to `value`. Otherwise this method will panic.
812
+ ///
813
+ /// # Examples
814
+ ///
815
+ /// ```
816
+ /// use std::fmt;
817
+ ///
818
+ /// struct Foo(Vec<(String, i32)>);
819
+ ///
820
+ /// impl fmt::Debug for Foo {
821
+ /// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
822
+ /// fmt.debug_map()
823
+ /// .key(&"whole").value(&self.0) // We add the "whole" entry.
824
+ /// .finish()
825
+ /// }
826
+ /// }
827
+ ///
828
+ /// assert_eq!(
829
+ /// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
830
+ /// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
831
+ /// );
832
+ /// ```
833
+ #[ unstable( feature = "debug_map_key_value" ,
834
+ reason = "recently added" ,
835
+ issue = "62482" ) ]
836
+ pub fn value ( & mut self , value : & dyn fmt:: Debug ) -> & mut DebugMap < ' a , ' b > {
837
+ assert ! ( self . has_key, "attempted to format a map value before its key" ) ;
838
+
839
+ self . result = self . result . and_then ( |_| {
840
+ if self . is_pretty ( ) {
841
+ let mut slot = None ;
842
+ let mut writer = PadAdapter :: wrap ( & mut self . fmt , & mut slot, & mut self . state ) ;
843
+ value. fmt ( & mut writer) ?;
844
+ writer. write_str ( ",\n " ) ?;
845
+ } else {
846
+ value. fmt ( self . fmt ) ?;
847
+ }
848
+
849
+ self . has_key = false ;
850
+ Ok ( ( ) )
734
851
} ) ;
735
852
736
853
self . has_fields = true ;
@@ -775,6 +892,11 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
775
892
776
893
/// Finishes output and returns any error encountered.
777
894
///
895
+ /// # Panics
896
+ ///
897
+ /// `key` must be called before `value` and each call to `key` must be followed
898
+ /// by a corresponding call to `value`. Otherwise this method will panic.
899
+ ///
778
900
/// # Examples
779
901
///
780
902
/// ```
@@ -797,6 +919,8 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
797
919
/// ```
798
920
#[ stable( feature = "debug_builders" , since = "1.2.0" ) ]
799
921
pub fn finish ( & mut self ) -> fmt:: Result {
922
+ assert ! ( !self . has_key, "attempted to finish a map with a partial entry" ) ;
923
+
800
924
self . result . and_then ( |_| self . fmt . write_str ( "}" ) )
801
925
}
802
926
0 commit comments