diff --git a/Cargo.toml b/Cargo.toml index a75627a295..f2c7e0733c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ ufmt-impl = ["ufmt-write"] x86-sync-pool = [] # only for tests __trybuild = [] +defmt-impl = ["defmt"] [target.x86_64-unknown-linux-gnu.dev-dependencies] scoped_threadpool = "0.1.8" @@ -51,3 +52,8 @@ optional = true [dev-dependencies.ufmt] version = "0.1" + +[dependencies.defmt] +git = "https://github.com/knurling-rs/defmt" +branch = "main" +optional = true diff --git a/src/defmt.rs b/src/defmt.rs new file mode 100644 index 0000000000..26a847de73 --- /dev/null +++ b/src/defmt.rs @@ -0,0 +1,86 @@ +//! Defmt implementations for heapless types +//! + +use crate::ArrayLength; +use crate::Vec; +use defmt::Formatter; + +impl defmt::Format for Vec +where + N: ArrayLength, + T: defmt::Format, +{ + fn format(&self, fmt: &mut Formatter) { + fmt.fmt_slice(self) + } +} + +impl defmt::Format for crate::String +where + N: ArrayLength, + u8: defmt::Format, +{ + fn format(&self, fmt: &mut Formatter) { + fmt.str(self.as_str()); + } +} + +#[cfg(test)] +mod tests { + use std::convert::TryInto; + + use crate::{consts::*, Vec}; + + #[test] + /// Tests encoding Vec with defmt, + /// based loosely on https://github.com/knurling-rs/defmt/blob/main/tests/encode.rs#L483 + fn test_defmt_format_vec() { + let v: Vec<_, U8> = Vec::from_slice(b"abc").unwrap(); + let index = defmt::export::fetch_string_index(); + + // borrowed from https://github.com/knurling-rs/defmt/blob/main/tests/encode.rs#L49 + let fake_interned = index.wrapping_add(1) & 0x7F; + + let timestamp = defmt::export::fetch_timestamp(); + let mut formatter = defmt::Formatter::new(); + defmt::winfo!(formatter, "{:?}", v); + assert_eq!( + formatter.bytes(), + &[ + index, + timestamp, + v.len().try_into().unwrap(), + fake_interned, // Faked + // Data bytes. + 97u8, + 98u8, + 99u8, + ] + ); + } + + /// Tests encoding String with defmt, + /// based loosely on https://github.com/knurling-rs/defmt/blob/main/tests/encode.rs#L483 + #[test] + fn test_defmt_format_str() { + let mut v: crate::String = crate::String::new(); + v.push_str("foo").unwrap(); + let index = defmt::export::fetch_string_index(); + + let timestamp = defmt::export::fetch_timestamp(); + let mut formatter = defmt::Formatter::new(); + defmt::winfo!(formatter, "{:?}", v); + assert_eq!( + formatter.bytes(), + &[ + index, + timestamp, + v.len().try_into().unwrap(), + // Data bytes. + 102u8, + 111u8, + 111u8, + ] + ); + } +} diff --git a/src/lib.rs b/src/lib.rs index 4d95fe2427..dbe492acd2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -106,6 +106,8 @@ pub mod mpmc; pub mod pool; #[cfg(has_atomics)] pub mod spsc; +#[cfg(feature = "defmt-impl")] +mod defmt; #[cfg(feature = "ufmt-impl")] mod ufmt;