diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6956a1fb..6cae6833 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -124,8 +124,7 @@ jobs: - name: Run QEMU snapshot tests run: cargo xtask test-snapshot - name: install decoder v0.2.0 - working-directory: firmware/qemu - run: cargo install --debug --git https://github.com/knurling-rs/defmt --rev v0.2.0-with-qemu-run-ignore-version qemu-run + run: cargo install --debug --path qemu-run - name: Backward compatibility check against decoder v0.2.0 env: CARGO_TARGET_THUMBV7M_NONE_EABI_RUNNER: qemu-run diff --git a/book/src/hints.md b/book/src/hints.md index ecbb484e..0de58de2 100644 --- a/book/src/hints.md +++ b/book/src/hints.md @@ -17,9 +17,10 @@ The first 4 display hints resemble what's supported in `core::fmt`. Examples bel ``` rust # extern crate defmt; -defmt::info!("{=u8:x}", 42); // -> INFO 0x2a -defmt::info!("{=u8:X}", 42); // -> INFO 0x2A -defmt::info!("{=u8:b}", 42); // -> INFO 0b101010 +defmt::info!("{=u8:x}", 42); // -> INFO 2a +defmt::info!("{=u8:X}", 42); // -> INFO 2A +defmt::info!("{=u8:#x}", 42); // -> INFO 0x2a +defmt::info!("{=u8:b}", 42); // -> INFO 101010 defmt::info!("{=str}", "hello\tworld"); // -> INFO hello world defmt::info!("{=str:?}", "hello\tworld"); // -> INFO "hello\tworld" @@ -30,10 +31,13 @@ Leading zeros are supported, for example ``` rust # extern crate defmt; defmt::info!("{=u8:03}", 42); // -> INFO 042 -defmt::info!("{=u8:08X}", 42); // -> INFO 0x0000002A +defmt::info!("{=u8:08X}", 42); // -> INFO 0000002A +defmt::info!("{=u8:#010X}", 42); // -> INFO 0x0000002A ``` -No further customization like padding is supported (at the moment). +When the alternate form is used for hex and binary, the `0x`/`0b` length is subtracted from the +leading zeros. This matches [`core::fmt` behavior](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b11809759f975e266251f7968e542756). No further +customization is supported (at the moment). The ASCII display hint formats byte slices (and arrays) using Rust's byte string syntax. @@ -58,7 +62,7 @@ let x = S { x: 42 }; defmt::info!("{}", x); // -> INFO S { x: 42 } -defmt::info!("{:x}", x); +defmt::info!("{:#x}", x); // -> INFO S { x: 0x2a } ``` @@ -75,8 +79,8 @@ impl defmt::Format for S { let x = S { x: 42, y: 42 }; defmt::info!("{}", x); -// -> INFO S { x: 42, y: 0x2a } +// -> INFO S { x: 42, y: 2a } -defmt::info!("{:x}", x); -// -> INFO S { x: 0b101010, y: 0x2a } +defmt::info!("{:b}", x); +// -> INFO S { x: 101010, y: 2a } ``` diff --git a/decoder/src/frame.rs b/decoder/src/frame.rs index 902a120a..aad1bf11 100644 --- a/decoder/src/frame.rs +++ b/decoder/src/frame.rs @@ -137,14 +137,23 @@ fn format_args_real( buf: &mut String, ) -> Result<(), fmt::Error> { match hint { - Some(DisplayHint::NoHint { zero_pad }) => write!(buf, "{:#01$}", x, zero_pad)?, - Some(DisplayHint::Binary { zero_pad }) => write!(buf, "{:#01$b}", x, zero_pad)?, + Some(DisplayHint::NoHint { zero_pad }) => write!(buf, "{:01$}", x, zero_pad)?, + Some(DisplayHint::Binary { + alternate, + zero_pad, + }) => match alternate { + true => write!(buf, "{:#01$b}", x, zero_pad)?, + false => write!(buf, "{:01$b}", x, zero_pad)?, + }, Some(DisplayHint::Hexadecimal { uppercase, + alternate, zero_pad, - }) => match uppercase { - false => write!(buf, "{:#01$x}", x, zero_pad)?, - true => write!(buf, "{:#01$X}", x, zero_pad)?, + }) => match (alternate, uppercase) { + (false, false) => write!(buf, "{:01$x}", x, zero_pad)?, + (false, true) => write!(buf, "{:01$X}", x, zero_pad)?, + (true, false) => write!(buf, "{:#01$x}", x, zero_pad)?, + (true, true) => write!(buf, "{:#01$X}", x, zero_pad)?, }, Some(DisplayHint::Microseconds) => { let seconds = x / 1_000_000; @@ -162,14 +171,23 @@ fn format_args_real( buf: &mut String, ) -> Result<(), fmt::Error> { match hint { - Some(DisplayHint::NoHint { zero_pad }) => write!(buf, "{:#01$}", x, zero_pad)?, - Some(DisplayHint::Binary { zero_pad }) => write!(buf, "{:#01$b}", x, zero_pad)?, + Some(DisplayHint::NoHint { zero_pad }) => write!(buf, "{:01$}", x, zero_pad)?, + Some(DisplayHint::Binary { + alternate, + zero_pad, + }) => match alternate { + true => write!(buf, "{:#01$b}", x, zero_pad)?, + false => write!(buf, "{:01$b}", x, zero_pad)?, + }, Some(DisplayHint::Hexadecimal { uppercase, + alternate, zero_pad, - }) => match uppercase { - false => write!(buf, "{:#01$x}", x, zero_pad)?, - true => write!(buf, "{:#01$X}", x, zero_pad)?, + }) => match (alternate, uppercase) { + (false, false) => write!(buf, "{:01$x}", x, zero_pad)?, + (false, true) => write!(buf, "{:01$X}", x, zero_pad)?, + (true, false) => write!(buf, "{:#01$x}", x, zero_pad)?, + (true, true) => write!(buf, "{:#01$X}", x, zero_pad)?, }, _ => write!(buf, "{}", x)?, } diff --git a/decoder/src/lib.rs b/decoder/src/lib.rs index 00bc4250..55139c51 100644 --- a/decoder/src/lib.rs +++ b/decoder/src/lib.rs @@ -751,9 +751,9 @@ mod tests { 0b1110_0101, // u8 ]; decode_and_expect( - "x: {0=0..4:b}, y: {0=3..8:b}", + "x: {0=0..4:b}, y: {0=3..8:#b}", &bytes, - "0.000002 INFO x: 0b101, y: 0b11100", + "0.000002 INFO x: 101, y: 0b11100", ); } @@ -767,7 +767,7 @@ mod tests { decode_and_expect( "x: {0=0..7:b}, y: {0=3..5:b}", &bytes, - "0.000002 INFO x: 0b1010010, y: 0b10", + "0.000002 INFO x: 1010010, y: 10", ); } @@ -782,7 +782,7 @@ mod tests { decode_and_expect( "#0: {0=0..5:b}, #1: {1=3..8:b}", &bytes, - "0.000002 INFO #0: 0b10000, #1: 0b11100", + "0.000002 INFO #0: 10000, #1: 11100", ); } @@ -794,7 +794,7 @@ mod tests { 0b1111_0000, 0b1110_0101, // u16 ]; - decode_and_expect("x: {0=7..12:b}", &bytes, "0.000002 INFO x: 0b1011"); + decode_and_expect("x: {0=7..12:b}", &bytes, "0.000002 INFO x: 1011"); } #[test] @@ -809,7 +809,7 @@ mod tests { decode_and_expect( "#0: {0=7..12:b}, #1: {1=0..5:b}", &bytes, - "0.000002 INFO #0: 0b1011, #1: 0b10001", + "0.000002 INFO #0: 1011, #1: 10001", ); } @@ -826,7 +826,7 @@ mod tests { decode_and_expect( "#0: {0=7..12:b}, #1: {1=u8}, #2: {2=0..5:b}", &bytes, - "0.000002 INFO #0: 0b1011, #1: 42, #2: 0b10001", + "0.000002 INFO #0: 1011, #1: 42, #2: 10001", ); } @@ -841,7 +841,7 @@ mod tests { decode_and_expect( "bitfields {0=0..7:b} {0=9..14:b}", &bytes, - "0.000002 INFO bitfields 0b1010010 0b10001", + "0.000002 INFO bitfields 1010010 10001", ); } @@ -857,7 +857,7 @@ mod tests { decode_and_expect( "bitfields {0=0..7:b} {0=9..14:b} {1=8..10:b}", &bytes, - "0.000002 INFO bitfields 0b1010010 0b10001 0b11", + "0.000002 INFO bitfields 1010010 10001 11", ); } @@ -871,7 +871,7 @@ mod tests { decode_and_expect( "bitfields {0=9..14:b}", &bytes, - "0.000002 INFO bitfields 0b10001", + "0.000002 INFO bitfields 10001", ); } @@ -888,7 +888,7 @@ mod tests { decode_and_expect( "bitfields {0=0..2:b} {0=28..31:b}", &bytes, - "0.000002 INFO bitfields 0b11 0b100", + "0.000002 INFO bitfields 11 100", ); } @@ -914,7 +914,7 @@ mod tests { 0b0000_0000, // 8..15 0b0000_0000, // 0..7 ]; - decode_and_expect("x: {0=119..124:b}", &bytes, "0.000002 INFO x: 0b1011"); + decode_and_expect("x: {0=119..124:b}", &bytes, "0.000002 INFO x: 1011"); } #[test] diff --git a/firmware/qemu/src/bin/hints.out b/firmware/qemu/src/bin/hints.out index 8a0c13f1..f496b4d5 100644 --- a/firmware/qemu/src/bin/hints.out +++ b/firmware/qemu/src/bin/hints.out @@ -1,44 +1,56 @@ 0.000000 INFO no hint 42 -0.000001 INFO hex 0x2a -0.000002 INFO HEX 0x2A -0.000003 INFO binary 0b101010 -0.000004 INFO ASCII 42 -0.000005 INFO Debug 42 -0.000006 INFO ---- -0.000007 INFO no-hint 42 -0.000008 INFO hex 0x2a -0.000009 INFO HEX 0x2A -0.000010 INFO binary 0b101010 -0.000011 INFO ASCII 42 -0.000012 INFO Debug 42 -0.000013 INFO ---- -0.000014 INFO no hint 42 -0.000015 INFO hex 0x2a -0.000016 INFO HEX 0x2A -0.000017 INFO binary 0b101010 -0.000018 INFO ASCII 42 -0.000019 INFO Debug 42 -0.000020 INFO ---- -0.000021 INFO S1 > S2 0b101010 -0.000022 INFO ---- -0.000023 INFO no hint [72, 101, 127, 108, 108, 111] -0.000024 INFO hex [0x48, 0x65, 0x7f, 0x6c, 0x6c, 0x6f] -0.000025 INFO HEX [0x48, 0x65, 0x7F, 0x6C, 0x6C, 0x6F] -0.000026 INFO binary [0b1001000, 0b1100101, 0b1111111, 0b1101100, 0b1101100, 0b1101111] -0.000027 INFO ASCII b"He\x7fllo" -0.000028 INFO Debug [72, 101, 127, 108, 108, 111] +0.000001 INFO hex 2a +0.000002 INFO hex alt 0x2a +0.000003 INFO HEX 2A +0.000004 INFO HEX alt 0x2A +0.000005 INFO binary 101010 +0.000006 INFO binary alt 0b101010 +0.000007 INFO ASCII 42 +0.000008 INFO Debug 42 +0.000009 INFO ---- +0.000010 INFO no-hint 42 +0.000011 INFO hex 2a +0.000012 INFO hex alt 0x2a +0.000013 INFO HEX 2A +0.000014 INFO HEX alt 0x2A +0.000015 INFO binary 101010 +0.000016 INFO binary alt 0b101010 +0.000017 INFO ASCII 42 +0.000018 INFO Debug 42 +0.000019 INFO ---- +0.000020 INFO no hint 42 +0.000021 INFO hex 2a +0.000022 INFO hex alt 0x2a +0.000023 INFO HEX 2A +0.000024 INFO HEX alt 0x2A +0.000025 INFO binary 101010 +0.000026 INFO binary alt 0b101010 +0.000027 INFO ASCII 42 +0.000028 INFO Debug 42 0.000029 INFO ---- -0.000030 INFO b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" -0.000031 INFO b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" -0.000032 INFO ---- -0.000033 INFO no hint Hello -0.000034 INFO Debug "Hello" -0.000035 INFO no hint world -0.000036 INFO Debug "world" -0.000037 INFO ---- -0.000038 INFO no hint 10 -0.000039 INFO hex 0xa -0.000040 INFO HEX 0xA -0.000041 INFO binary 0b1010 -0.000042 INFO ASCII b"\n" -0.000043 INFO Debug 10 +0.000030 INFO S1 > S2 101010 +0.000031 INFO ---- +0.000032 INFO no hint [72, 101, 127, 108, 108, 111] +0.000033 INFO hex [48, 65, 7f, 6c, 6c, 6f] +0.000034 INFO hex alt [0x48, 0x65, 0x7f, 0x6c, 0x6c, 0x6f] +0.000035 INFO HEX [48, 65, 7F, 6C, 6C, 6F] +0.000036 INFO HEX alt [0x48, 0x65, 0x7F, 0x6C, 0x6C, 0x6F] +0.000037 INFO binary [1001000, 1100101, 1111111, 1101100, 1101100, 1101111] +0.000038 INFO binary alt [0b1001000, 0b1100101, 0b1111111, 0b1101100, 0b1101100, 0b1101111] +0.000039 INFO ASCII b"He\x7fllo" +0.000040 INFO Debug [72, 101, 127, 108, 108, 111] +0.000041 INFO ---- +0.000042 INFO b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" +0.000043 INFO b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" +0.000044 INFO ---- +0.000045 INFO no hint Hello +0.000046 INFO Debug "Hello" +0.000047 INFO no hint world +0.000048 INFO Debug "world" +0.000049 INFO ---- +0.000050 INFO no hint 10 +0.000051 INFO hex a +0.000052 INFO HEX A +0.000053 INFO binary 1010 +0.000054 INFO ASCII b"\n" +0.000055 INFO Debug 10 diff --git a/firmware/qemu/src/bin/hints.release.out b/firmware/qemu/src/bin/hints.release.out index 8a0c13f1..f496b4d5 100644 --- a/firmware/qemu/src/bin/hints.release.out +++ b/firmware/qemu/src/bin/hints.release.out @@ -1,44 +1,56 @@ 0.000000 INFO no hint 42 -0.000001 INFO hex 0x2a -0.000002 INFO HEX 0x2A -0.000003 INFO binary 0b101010 -0.000004 INFO ASCII 42 -0.000005 INFO Debug 42 -0.000006 INFO ---- -0.000007 INFO no-hint 42 -0.000008 INFO hex 0x2a -0.000009 INFO HEX 0x2A -0.000010 INFO binary 0b101010 -0.000011 INFO ASCII 42 -0.000012 INFO Debug 42 -0.000013 INFO ---- -0.000014 INFO no hint 42 -0.000015 INFO hex 0x2a -0.000016 INFO HEX 0x2A -0.000017 INFO binary 0b101010 -0.000018 INFO ASCII 42 -0.000019 INFO Debug 42 -0.000020 INFO ---- -0.000021 INFO S1 > S2 0b101010 -0.000022 INFO ---- -0.000023 INFO no hint [72, 101, 127, 108, 108, 111] -0.000024 INFO hex [0x48, 0x65, 0x7f, 0x6c, 0x6c, 0x6f] -0.000025 INFO HEX [0x48, 0x65, 0x7F, 0x6C, 0x6C, 0x6F] -0.000026 INFO binary [0b1001000, 0b1100101, 0b1111111, 0b1101100, 0b1101100, 0b1101111] -0.000027 INFO ASCII b"He\x7fllo" -0.000028 INFO Debug [72, 101, 127, 108, 108, 111] +0.000001 INFO hex 2a +0.000002 INFO hex alt 0x2a +0.000003 INFO HEX 2A +0.000004 INFO HEX alt 0x2A +0.000005 INFO binary 101010 +0.000006 INFO binary alt 0b101010 +0.000007 INFO ASCII 42 +0.000008 INFO Debug 42 +0.000009 INFO ---- +0.000010 INFO no-hint 42 +0.000011 INFO hex 2a +0.000012 INFO hex alt 0x2a +0.000013 INFO HEX 2A +0.000014 INFO HEX alt 0x2A +0.000015 INFO binary 101010 +0.000016 INFO binary alt 0b101010 +0.000017 INFO ASCII 42 +0.000018 INFO Debug 42 +0.000019 INFO ---- +0.000020 INFO no hint 42 +0.000021 INFO hex 2a +0.000022 INFO hex alt 0x2a +0.000023 INFO HEX 2A +0.000024 INFO HEX alt 0x2A +0.000025 INFO binary 101010 +0.000026 INFO binary alt 0b101010 +0.000027 INFO ASCII 42 +0.000028 INFO Debug 42 0.000029 INFO ---- -0.000030 INFO b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" -0.000031 INFO b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" -0.000032 INFO ---- -0.000033 INFO no hint Hello -0.000034 INFO Debug "Hello" -0.000035 INFO no hint world -0.000036 INFO Debug "world" -0.000037 INFO ---- -0.000038 INFO no hint 10 -0.000039 INFO hex 0xa -0.000040 INFO HEX 0xA -0.000041 INFO binary 0b1010 -0.000042 INFO ASCII b"\n" -0.000043 INFO Debug 10 +0.000030 INFO S1 > S2 101010 +0.000031 INFO ---- +0.000032 INFO no hint [72, 101, 127, 108, 108, 111] +0.000033 INFO hex [48, 65, 7f, 6c, 6c, 6f] +0.000034 INFO hex alt [0x48, 0x65, 0x7f, 0x6c, 0x6c, 0x6f] +0.000035 INFO HEX [48, 65, 7F, 6C, 6C, 6F] +0.000036 INFO HEX alt [0x48, 0x65, 0x7F, 0x6C, 0x6C, 0x6F] +0.000037 INFO binary [1001000, 1100101, 1111111, 1101100, 1101100, 1101111] +0.000038 INFO binary alt [0b1001000, 0b1100101, 0b1111111, 0b1101100, 0b1101100, 0b1101111] +0.000039 INFO ASCII b"He\x7fllo" +0.000040 INFO Debug [72, 101, 127, 108, 108, 111] +0.000041 INFO ---- +0.000042 INFO b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" +0.000043 INFO b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" +0.000044 INFO ---- +0.000045 INFO no hint Hello +0.000046 INFO Debug "Hello" +0.000047 INFO no hint world +0.000048 INFO Debug "world" +0.000049 INFO ---- +0.000050 INFO no hint 10 +0.000051 INFO hex a +0.000052 INFO HEX A +0.000053 INFO binary 1010 +0.000054 INFO ASCII b"\n" +0.000055 INFO Debug 10 diff --git a/firmware/qemu/src/bin/hints.rs b/firmware/qemu/src/bin/hints.rs index 3299ee4f..b0566347 100644 --- a/firmware/qemu/src/bin/hints.rs +++ b/firmware/qemu/src/bin/hints.rs @@ -14,8 +14,11 @@ fn main() -> ! { let x = 42; defmt::info!("no hint {=u8}", x); defmt::info!("hex {=u8:x}", x); + defmt::info!("hex alt {=u8:#x}", x); defmt::info!("HEX {=u8:X}", x); + defmt::info!("HEX alt {=u8:#X}", x); defmt::info!("binary {=u8:b}", x); + defmt::info!("binary alt {=u8:#b}", x); defmt::info!("ASCII {=u8:a}", x); defmt::info!("Debug {=u8:?}", x); @@ -24,8 +27,11 @@ fn main() -> ! { let x = 42; defmt::info!("no-hint {=i8}", x); defmt::info!("hex {=i8:x}", x); + defmt::info!("hex alt {=i8:#x}", x); defmt::info!("HEX {=i8:X}", x); + defmt::info!("HEX alt {=i8:#X}", x); defmt::info!("binary {=i8:b}", x); + defmt::info!("binary alt {=i8:#b}", x); defmt::info!("ASCII {=i8:a}", x); defmt::info!("Debug {=i8:?}", x); @@ -36,8 +42,11 @@ fn main() -> ! { // the `Format` implementation of `i8` uses `{=i8}` as its format string defmt::info!("no hint {}", x); defmt::info!("hex {:x}", x); + defmt::info!("hex alt {:#x}", x); defmt::info!("HEX {:X}", x); + defmt::info!("HEX alt {:#X}", x); defmt::info!("binary {:b}", x); + defmt::info!("binary alt {:#b}", x); defmt::info!("ASCII {:a}", x); defmt::info!("Debug {:?}", x); @@ -71,8 +80,11 @@ fn main() -> ! { let x = b"He\x7Fllo"; defmt::info!("no hint {=[u8]}", *x); defmt::info!("hex {=[u8]:x}", *x); + defmt::info!("hex alt {=[u8]:#x}", *x); defmt::info!("HEX {=[u8]:X}", *x); + defmt::info!("HEX alt {=[u8]:#X}", *x); defmt::info!("binary {=[u8]:b}", *x); + defmt::info!("binary alt {=[u8]:#b}", *x); defmt::info!("ASCII {=[u8]:a}", *x); defmt::info!("Debug {=[u8]:?}", *x); diff --git a/firmware/qemu/src/bin/log.out b/firmware/qemu/src/bin/log.out index acc41582..8fac0785 100644 --- a/firmware/qemu/src/bin/log.out +++ b/firmware/qemu/src/bin/log.out @@ -106,15 +106,15 @@ 0.000105 INFO EnumLarge::A269 0.000106 INFO S { x: "hi" } 0.000107 INFO S { x: PhantomData, y: 42 } -0.000108 INFO bitfields 0x97 0b10000100 12 b"42" b"hello" +0.000108 INFO bitfields 97 10000100 12 b"42" b"hello" 0.000109 INFO b"Hi" 0.000110 INFO b"Hi" 0.000111 INFO b"Hi" 0.000112 INFO [45054, 49406] 0.000113 INFO [Data { name: b"Hi", value: true }] 0.000114 INFO true true -0.000115 INFO 0xaabbccdd -0.000116 INFO 0xddccbbaa +0.000115 INFO aabbccdd +0.000116 INFO ddccbbaa 0.000117 INFO 1..2 0.000118 INFO 1.. 0.000119 INFO ..2 diff --git a/firmware/qemu/src/bin/log.release.out b/firmware/qemu/src/bin/log.release.out index 14aba36d..5d7357c1 100644 --- a/firmware/qemu/src/bin/log.release.out +++ b/firmware/qemu/src/bin/log.release.out @@ -104,15 +104,15 @@ 0.000103 INFO EnumLarge::A269 0.000104 INFO S { x: "hi" } 0.000105 INFO S { x: PhantomData, y: 42 } -0.000106 INFO bitfields 0x97 0b10000100 12 b"42" b"hello" +0.000106 INFO bitfields 97 10000100 12 b"42" b"hello" 0.000107 INFO b"Hi" 0.000108 INFO b"Hi" 0.000109 INFO b"Hi" 0.000110 INFO [45054, 49406] 0.000111 INFO [Data { name: b"Hi", value: true }] 0.000112 INFO true true -0.000113 INFO 0xaabbccdd -0.000114 INFO 0xddccbbaa +0.000113 INFO aabbccdd +0.000114 INFO ddccbbaa 0.000115 INFO 1..2 0.000116 INFO 1.. 0.000117 INFO ..2 diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 41b1a9c3..b4fa35ef 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -35,11 +35,13 @@ pub enum DisplayHint { }, /// `:x` OR `:X` Hexadecimal { + alternate: bool, uppercase: bool, zero_pad: usize, }, /// `:b` Binary { + alternate: bool, zero_pad: usize, }, /// `:a` @@ -52,24 +54,40 @@ pub enum DisplayHint { Unknown(String), } +/// Parses the display hint (e.g. the `#x` in `{=u8:#x}`) fn parse_display_hint(mut s: &str) -> Option { + // The `#` comes before any padding hints (I think this matches core::fmt). + // It is ignored for types that don't have an alternate representation. + let alternate = if matches!(s.chars().next(), Some('#')) { + s = &s[1..]; // '#' is always 1 byte + true + } else { + false + }; + let zero_pad = if let Some(rest) = s.strip_prefix("0") { let (rest, columns) = parse_integer::(rest)?; s = rest; columns } else { - 0 // default behavior is the same as zero padding. + 0 // default behavior is the same as no zero-padding. }; + Some(match s { "" => DisplayHint::NoHint { zero_pad }, "µs" => DisplayHint::Microseconds, "a" => DisplayHint::Ascii, - "b" => DisplayHint::Binary { zero_pad }, + "b" => DisplayHint::Binary { + alternate, + zero_pad, + }, "x" => DisplayHint::Hexadecimal { + alternate, uppercase: false, zero_pad, }, "X" => DisplayHint::Hexadecimal { + alternate, uppercase: true, zero_pad, }, @@ -517,6 +535,7 @@ mod tests { index: None, ty: Type::U8, hint: Some(DisplayHint::Hexadecimal { + alternate: false, uppercase: false, zero_pad: 0 }), @@ -547,7 +566,10 @@ mod tests { Ok(Param { index: Some(1), ty: Type::U8, - hint: Some(DisplayHint::Binary { zero_pad: 0 }), + hint: Some(DisplayHint::Binary { + alternate: false, + zero_pad: 0, + }), }) ); } @@ -568,7 +590,22 @@ mod tests { Ok(Param { index: None, ty: Type::Format, - hint: Some(DisplayHint::Binary { zero_pad: 0 }), + hint: Some(DisplayHint::Binary { + alternate: false, + zero_pad: 0, + }), + }) + ); + + assert_eq!( + parse_param(":#b", ParserMode::Strict), + Ok(Param { + index: None, + ty: Type::Format, + hint: Some(DisplayHint::Binary { + alternate: true, + zero_pad: 0, + }), }) ); @@ -578,6 +615,20 @@ mod tests { index: None, ty: Type::Format, hint: Some(DisplayHint::Hexadecimal { + alternate: false, + uppercase: false, + zero_pad: 0 + }), + }) + ); + + assert_eq!( + parse_param(":#x", ParserMode::Strict), + Ok(Param { + index: None, + ty: Type::Format, + hint: Some(DisplayHint::Hexadecimal { + alternate: true, uppercase: false, zero_pad: 0 }), @@ -590,6 +641,20 @@ mod tests { index: None, ty: Type::Format, hint: Some(DisplayHint::Hexadecimal { + alternate: false, + uppercase: true, + zero_pad: 0 + }), + }) + ); + + assert_eq!( + parse_param(":#X", ParserMode::Strict), + Ok(Param { + index: None, + ty: Type::Format, + hint: Some(DisplayHint::Hexadecimal { + alternate: true, uppercase: true, zero_pad: 0 }),