11use crate :: fmt;
22
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 {
59 on_newline : bool ,
610}
711
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 > {
1124 fmt. wrap_buf ( move |buf| {
1225 * slot = Some ( PadAdapter {
1326 buf,
14- on_newline : true ,
27+ state ,
1528 } ) ;
1629 slot. as_mut ( ) . unwrap ( )
1730 } )
1831 }
1932}
2033
21- impl fmt:: Write for PadAdapter < ' _ > {
34+ impl fmt:: Write for PadAdapter < ' _ , ' _ > {
2235 fn write_str ( & mut self , mut s : & str ) -> fmt:: Result {
2336 while !s. is_empty ( ) {
24- if self . on_newline {
37+ if self . state . on_newline {
2538 self . buf . write_str ( " " ) ?;
2639 }
2740
2841 let split = match s. find ( '\n' ) {
2942 Some ( pos) => {
30- self . on_newline = true ;
43+ self . state . on_newline = true ;
3144 pos + 1
3245 }
3346 None => {
34- self . on_newline = false ;
47+ self . state . on_newline = false ;
3548 s. len ( )
3649 }
3750 } ;
@@ -133,7 +146,8 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
133146 self . fmt . write_str ( " {\n " ) ?;
134147 }
135148 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) ;
137151 writer. write_str ( name) ?;
138152 writer. write_str ( ": " ) ?;
139153 value. fmt ( & mut writer) ?;
@@ -279,7 +293,8 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
279293 self . fmt . write_str ( "(\n " ) ?;
280294 }
281295 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) ;
283298 value. fmt ( & mut writer) ?;
284299 writer. write_str ( ",\n " )
285300 } else {
@@ -349,7 +364,8 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
349364 self . fmt . write_str ( "\n " ) ?;
350365 }
351366 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) ;
353369 entry. fmt ( & mut writer) ?;
354370 writer. write_str ( ",\n " )
355371 } else {
@@ -676,6 +692,9 @@ pub struct DebugMap<'a, 'b: 'a> {
676692 fmt : & ' a mut fmt:: Formatter < ' b > ,
677693 result : fmt:: Result ,
678694 has_fields : bool ,
695+ has_key : bool ,
696+ // The state of newlines is tracked between keys and values
697+ state : PadAdapterState ,
679698}
680699
681700pub 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
684703 fmt,
685704 result,
686705 has_fields : false ,
706+ has_key : false ,
707+ state : Default :: default ( ) ,
687708 }
688709}
689710
@@ -712,25 +733,121 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
712733 /// ```
713734 #[ stable( feature = "debug_builders" , since = "1.2.0" ) ]
714735 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+
715777 self . result = self . result . and_then ( |_| {
716778 if self . is_pretty ( ) {
717779 if !self . has_fields {
718780 self . fmt . write_str ( "\n " ) ?;
719781 }
720782 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 ) ;
722785 key. fmt ( & mut writer) ?;
723786 writer. write_str ( ": " ) ?;
724- value. fmt ( & mut writer) ?;
725- writer. write_str ( ",\n " )
726787 } else {
727788 if self . has_fields {
728789 self . fmt . write_str ( ", " ) ?
729790 }
730791 key. fmt ( self . fmt ) ?;
731792 self . fmt . write_str ( ": " ) ?;
732- value. fmt ( self . fmt )
733793 }
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 ( ( ) )
734851 } ) ;
735852
736853 self . has_fields = true ;
@@ -775,6 +892,11 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
775892
776893 /// Finishes output and returns any error encountered.
777894 ///
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+ ///
778900 /// # Examples
779901 ///
780902 /// ```
@@ -797,6 +919,8 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
797919 /// ```
798920 #[ stable( feature = "debug_builders" , since = "1.2.0" ) ]
799921 pub fn finish ( & mut self ) -> fmt:: Result {
922+ assert ! ( !self . has_key, "attempted to finish a map with a partial entry" ) ;
923+
800924 self . result . and_then ( |_| self . fmt . write_str ( "}" ) )
801925 }
802926
0 commit comments