From 10fb39ab48321ebfd48696eb47ca32ba87105512 Mon Sep 17 00:00:00 2001 From: chrysn Date: Sat, 21 Dec 2024 21:51:27 +0100 Subject: [PATCH 1/4] Add ':cbor' hint for CBOR Diagnostic Notation (EDN) --- decoder/Cargo.toml | 1 + decoder/src/frame.rs | 10 ++++++++++ parser/src/display_hint.rs | 12 ++++++++++++ 3 files changed, 23 insertions(+) diff --git a/decoder/Cargo.toml b/decoder/Cargo.toml index 7368d836..9f8b795f 100644 --- a/decoder/Cargo.toml +++ b/decoder/Cargo.toml @@ -44,6 +44,7 @@ serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["arbitrary_precision"] } regex = "1" alterable_logger = "1" +cbor-edn = { version = "0.0.6", default-features = false } [features] # DEPRECATED: noop, will be removed in 1.0 diff --git a/decoder/src/frame.rs b/decoder/src/frame.rs index 00e43489..b1aba9e2 100644 --- a/decoder/src/frame.rs +++ b/decoder/src/frame.rs @@ -399,6 +399,16 @@ impl<'t> Frame<'t> { } buf.push(']'); } + Some(DisplayHint::Cbor) => { + use core::fmt::Write; + let parsed = cbor_edn::Sequence::from_cbor(bytes); + match parsed { + Ok(parsed) => buf.write_str(&parsed.serialize())?, + Err(err) => { + write!(buf, "invalid CBOR (error: {}, bytes: {:02x?})", err, bytes)? + } + } + } _ => write!(buf, "{bytes:?}")?, } Ok(()) diff --git a/parser/src/display_hint.rs b/parser/src/display_hint.rs index 1878db66..7d90f215 100644 --- a/parser/src/display_hint.rs +++ b/parser/src/display_hint.rs @@ -40,6 +40,17 @@ pub enum DisplayHint { disambiguator: String, crate_name: Option, }, + /// `:cbor`: There is CBOR data encoded in those bytes, to be shown in diagnostic notation. + /// + /// Technically, the byte string interpreted as a CBOR sequence, and shown in the diagnostic + /// notation of a sequence. That is identical to processing a single CBOR item if there is just + /// one present, but also allows reporting multiple items from consecutive memory; diagnostic + /// notation turns those into comma separated items. + // Should we have a flag to say "do a more display style stringification" (like, if you + // recognize `54([64,h'20010db8'])`, don't show "IP'2001:db8::/64'" but just "2001:db8::64")? + // Should we allow additional params that give a CDDL that further guides processing (like, + // when data is not tagged but the shape is known for processing anyway)? + Cbor, /// Display hints currently not supported / understood Unknown(String), } @@ -108,6 +119,7 @@ impl DisplayHint { }, "iso8601ms" => DisplayHint::ISO8601(TimePrecision::Millis), "iso8601s" => DisplayHint::ISO8601(TimePrecision::Seconds), + "cbor" => DisplayHint::Cbor, "?" => DisplayHint::Debug, _ => return None, }) From 01634ec6d51aa545d1fd5f4dadfbfa6746165f8b Mon Sep 17 00:00:00 2001 From: chrysn Date: Wed, 8 Jan 2025 09:26:56 +0100 Subject: [PATCH 2/4] Mark DisplayHint as non_exhaustive --- parser/src/display_hint.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/parser/src/display_hint.rs b/parser/src/display_hint.rs index 7d90f215..3bb281e8 100644 --- a/parser/src/display_hint.rs +++ b/parser/src/display_hint.rs @@ -2,6 +2,7 @@ use std::str::FromStr; /// All display hints #[derive(Clone, Debug, Eq, PartialEq)] +#[non_exhaustive] pub enum DisplayHint { NoHint { zero_pad: usize, From 6cc7b9cfacf543cf15ee7170509952f5d120df96 Mon Sep 17 00:00:00 2001 From: chrysn Date: Wed, 8 Jan 2025 09:47:57 +0100 Subject: [PATCH 3/4] Update change log --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8ccaa58..4a16b12c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -544,6 +544,7 @@ Initial release ### [defmt-decoder-next] * [#902] Minor change to `impl StreamDecoder` for `Raw` and `Rzcobs`, eliding a lifetime specifier to satisfy Clippy 1.83. No observable change. +* [#916] Support the ":cbor" display hint, adding new dependency `cbor-edn`. ### [defmt-decoder-v0.4.0] (2024-11-27) @@ -609,6 +610,9 @@ Initial release ### [defmt-parser-next] +* [#916] Mark `DisplayHint` as `non_exhaustive`. This is a breaking change. +* [#916] Add display hint ":cbor", indicating RFC8949 encoded data to be displayed in diagnostic notation. + ### [defmt-parser-v0.4.1] (2024-11-27) * [#897] Added its own README From 252bd35bf5c2f4fdd3a92d83b9e643a1567b523c Mon Sep 17 00:00:00 2001 From: chrysn Date: Mon, 13 Jan 2025 16:02:04 +0100 Subject: [PATCH 4/4] book: Dokument :cbor hint --- book/src/hints.md | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/book/src/hints.md b/book/src/hints.md index 61dd8825..e57ec666 100644 --- a/book/src/hints.md +++ b/book/src/hints.md @@ -8,19 +8,20 @@ The hint follows the syntax `:Display` and must come after the type within the b The following display hints are currently supported: -| hint | name | -| :----- | :------------------------------------------------------- | -| `:x` | lowercase hexadecimal | -| `:X` | uppercase hexadecimal | -| `:?` | `core::fmt::Debug`-like | -| `:b` | binary | -| `:o` | octal | -| `:a` | ASCII | -| `:ms` | timestamp in seconds (input in milliseconds) | -| `:us` | timestamp in seconds (input in microseconds) | -| `:ts` | timestamp in human-readable time (input in seconds) | -| `:tms` | timestamp in human-readable time (input in milliseconds) | -| `:tus` | timestamp in human-readable time (input in microseconds) | +| hint | name | +| :------ | :------------------------------------------------------- | +| `:x` | lowercase hexadecimal | +| `:X` | uppercase hexadecimal | +| `:?` | `core::fmt::Debug`-like | +| `:b` | binary | +| `:o` | octal | +| `:a` | ASCII | +| `:ms` | timestamp in seconds (input in milliseconds) | +| `:us` | timestamp in seconds (input in microseconds) | +| `:ts` | timestamp in human-readable time (input in seconds) | +| `:tms` | timestamp in human-readable time (input in milliseconds) | +| `:tus` | timestamp in human-readable time (input in microseconds) | +| `:cbor` | CBOR encoded items rendered in Diagnostic Notation (EDN) | The first 4 display hints resemble what's supported in `core::fmt`, for example: @@ -44,6 +45,22 @@ let bytes = [104, 101, 255, 108, 108, 111]; defmt::info!("{=[u8]:a}", bytes); // -> INFO b"he\xffllo" ``` +The CBOR display hint is useful when CBOR data is in memory, especially before further processing: + +``` rust +# extern crate defmt; +# fn parse(slice: &[u8]) -> Result<(), ()> { +# Ok(()) +# } +# fn main() -> Result<(), ()> { +let id_cred = &[0xa1, 0x04, 0x44, 0x6b, 0x69, 0x64, 0x31]; + +defmt::info!("Peer ID: {=[u8]:cbor}", id_cred); // -> INFO Peer ID: {4: 'kid1'} +let parsed = parse(id_cred)?; +# Ok(()) +# } +``` + ## Alternate printing Adding `#` in front of a binary, octal, and hexadecimal display hints, precedes these numbers with a base indicator.