]> git.lizzy.rs Git - rust.git/commitdiff
Add hexadecimal formatting of integers with fmt::Debug
authorSimon Sapin <simon.sapin@exyr.org>
Tue, 13 Mar 2018 13:08:15 +0000 (14:08 +0100)
committerSimon Sapin <simon.sapin@exyr.org>
Tue, 13 Mar 2018 13:53:06 +0000 (14:53 +0100)
This can be used for integers within a larger types which implements Debug
(possibly through derive) but not fmt::UpperHex or fmt::LowerHex.

```rust
assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]");
assert!(format!("{:02X?}", b"Foo\0") == "[46, 6F, 6F, 00]");
```

RFC: https://github.com/rust-lang/rfcs/pull/2226

src/liballoc/fmt.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/tests/fmt/num.rs
src/libfmt_macros/lib.rs

index a092bfb3b0a8a5899da6d8d5955cd5101bc4cc6e..2c4cdef03b0f7d3f7ed331a5f2e0ef2c47963970 100644 (file)
 //!
 //! * *nothing* ⇒ [`Display`]
 //! * `?` ⇒ [`Debug`]
+//! * `x?` ⇒ [`Debug`] with lower-case hexadecimal integers
+//! * `X?` ⇒ [`Debug`] with lower-case hexadecimal integers
 //! * `o` ⇒ [`Octal`](trait.Octal.html)
 //! * `x` ⇒ [`LowerHex`](trait.LowerHex.html)
 //! * `X` ⇒ [`UpperHex`](trait.UpperHex.html)
index 8ad5a9861a02f07c586f3b9457d3f6f988f71c45..a31be0e216f27ea0eefc1f86f857ef91d87adf50 100644 (file)
@@ -333,7 +333,7 @@ fn as_usize(&self) -> Option<usize> {
 
 // flags available in the v1 format of format_args
 #[derive(Copy, Clone)]
-enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, }
+enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, DebugLowerHex, DebugUpperHex }
 
 impl<'a> Arguments<'a> {
     /// When using the format_args!() macro, this function is used to generate the
@@ -1401,6 +1401,12 @@ pub fn sign_aware_zero_pad(&self) -> bool {
         self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0
     }
 
+    // FIXME: Decide what public API we want for these two flags.
+    // https://github.com/rust-lang/rust/issues/48584
+    fn debug_lower_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0 }
+
+    fn debug_upper_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0 }
+
     /// Creates a [`DebugStruct`] builder designed to assist with creation of
     /// [`fmt::Debug`] implementations for structs.
     ///
index 2992e7cf8db341cf0fde7730212752b19ed70096..86f1b5a8f287546db828de5f0f7b9bbf7df448e4 100644 (file)
@@ -159,7 +159,13 @@ macro_rules! debug {
         impl fmt::Debug for $T {
             #[inline]
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-                fmt::Display::fmt(self, f)
+                if f.debug_lower_hex() {
+                    fmt::LowerHex::fmt(self, f)
+                } else if f.debug_upper_hex() {
+                    fmt::UpperHex::fmt(self, f)
+                } else {
+                    fmt::Display::fmt(self, f)
+                }
             }
         }
     }
index 4ddedd9100486ea8640a712a390310f89b7305a2..bc205ec0582ea8c7ae1405c323494fa62eb67aff 100644 (file)
@@ -150,3 +150,9 @@ fn test_format_int_twos_complement() {
     assert!(format!("{}", i32::MIN) == "-2147483648");
     assert!(format!("{}", i64::MIN) == "-9223372036854775808");
 }
+
+#[test]
+fn test_format_debug_hex() {
+    assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]");
+    assert!(format!("{:02X?}", b"Foo\0") == "[46, 6F, 6F, 00]");
+}
index 71519ab21fef99d60ae47e3f55a11b26d3f752d7..0f45f965104cadff7b8cce5e168e73a0036cf36b 100644 (file)
@@ -108,6 +108,10 @@ pub enum Flag {
     /// For numbers, this means that the number will be padded with zeroes,
     /// and the sign (`+` or `-`) will precede them.
     FlagSignAwareZeroPad,
+    /// For Debug / `?`, format integers in lower-case hexadecimal.
+    FlagDebugLowerHex,
+    /// For Debug / `?`, format integers in upper-case hexadecimal.
+    FlagDebugUpperHex,
 }
 
 /// A count is used for the precision and width parameters of an integer, and
@@ -377,8 +381,22 @@ fn format(&mut self) -> FormatSpec<'a> {
                 spec.precision = self.count();
             }
         }
-        // Finally the actual format specifier
-        if self.consume('?') {
+        // Optional radix followed by the actual format specifier
+        if self.consume('x') {
+            if self.consume('?') {
+                spec.flags |= 1 << (FlagDebugLowerHex as u32);
+                spec.ty = "?";
+            } else {
+                spec.ty = "x";
+            }
+        } else if self.consume('X') {
+            if self.consume('?') {
+                spec.flags |= 1 << (FlagDebugUpperHex as u32);
+                spec.ty = "?";
+            } else {
+                spec.ty = "X";
+            }
+        } else if self.consume('?') {
             spec.ty = "?";
         } else {
             spec.ty = self.word();