diff --git a/Cargo.lock b/Cargo.lock index a87ae59..2cb9685 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,7 +93,7 @@ version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags", + "bitflags 2.5.0", "cexpr", "clang-sys", "itertools", @@ -110,6 +110,12 @@ dependencies = [ "which", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.5.0" @@ -144,6 +150,7 @@ version = "0.1.0" dependencies = [ "bitvec", "can-messages", + "defmt", "embedded-can", ] @@ -155,6 +162,7 @@ dependencies = [ "arbitrary", "bitvec", "dbc-codegen", + "defmt", "embedded-can", ] @@ -251,6 +259,7 @@ version = "0.3.0" dependencies = [ "anyhow", "can-dbc", + "defmt", "embedded-can", "heck 0.4.1", "typed-builder", @@ -266,6 +275,38 @@ dependencies = [ "heck 0.4.1", ] +[[package]] +name = "defmt" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99dd22262668b887121d4672af5a64b238f026099f1a2a1b322066c9ecfe9e0" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9f309eff1f79b3ebdf252954d90ae440599c26c2c553fe87a2d17195f2dcb" +dependencies = [ + "defmt-parser", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.61", +] + +[[package]] +name = "defmt-parser" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4a5fefe330e8d7f31b16a318f9ce81000d8e35e69b93eae154d16d2278f70f" +dependencies = [ + "thiserror", +] + [[package]] name = "derive-getters" version = "0.3.0" @@ -449,6 +490,30 @@ dependencies = [ "syn 2.0.61", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.82" @@ -523,7 +588,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -570,6 +635,26 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "thiserror" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.61", +] + [[package]] name = "typed-builder" version = "0.18.2" @@ -602,6 +687,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "which" version = "4.4.2" diff --git a/Cargo.toml b/Cargo.toml index 6fbfd55..c651a90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,9 @@ heck = "0.4.0" typed-builder = "0.18.0" embedded-can = "0.4.1" +[dev-dependencies] +defmt = "0.3.8" + [workspace] members = [ ".", diff --git a/src/lib.rs b/src/lib.rs index c6fbee1..cb2c37f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,6 +60,10 @@ pub struct Config<'a> { #[builder(default)] pub impl_debug: FeatureConfig<'a>, + /// Optional: `impl defmt::Format` for generated types. Default: `Never`. + #[builder(default)] + pub impl_defmt: FeatureConfig<'a>, + /// Optional: `impl Arbitrary` for generated types. Default: `Never`. #[builder(default)] pub impl_arbitrary: FeatureConfig<'a>, @@ -189,6 +193,9 @@ fn render_root_enum(mut w: impl Write, dbc: &DBC, config: &Config<'_>) -> Result writeln!(w, "/// All messages")?; writeln!(w, "#[derive(Clone)]")?; config.impl_debug.fmt_attr(&mut w, "derive(Debug)")?; + config + .impl_defmt + .fmt_attr(&mut w, "derive(defmt::Format)")?; config.impl_serde.fmt_attr(&mut w, "derive(Serialize)")?; config.impl_serde.fmt_attr(&mut w, "derive(Deserialize)")?; writeln!(w, "pub enum Messages {{")?; @@ -430,6 +437,8 @@ fn render_message(mut w: impl Write, config: &Config<'_>, msg: &Message, dbc: &D render_debug_impl(&mut w, config, msg)?; + render_defmt_impl(&mut w, config, msg)?; + render_arbitrary(&mut w, config, msg)?; let enums_for_this_message = dbc.value_descriptions().iter().filter_map(|x| { @@ -984,6 +993,9 @@ fn write_enum( writeln!(w, "/// Defined values for {}", signal.name())?; writeln!(w, "#[derive(Clone, Copy, PartialEq)]")?; config.impl_debug.fmt_attr(&mut w, "derive(Debug)")?; + config + .impl_defmt + .fmt_attr(&mut w, "derive(defmt::Format)")?; config.impl_serde.fmt_attr(&mut w, "derive(Serialize)")?; config.impl_serde.fmt_attr(&mut w, "derive(Deserialize)")?; writeln!(w, "pub enum {} {{", type_name)?; @@ -1385,6 +1397,48 @@ fn render_debug_impl(mut w: impl Write, config: &Config<'_>, msg: &Message) -> R Ok(()) } +fn render_defmt_impl(mut w: impl Write, config: &Config<'_>, msg: &Message) -> Result<()> { + match &config.impl_defmt { + FeatureConfig::Always => {} + FeatureConfig::Gated(gate) => writeln!(w, r##"#[cfg(feature = {gate:?})]"##)?, + FeatureConfig::Never => return Ok(()), + } + + let typ = type_name(msg.message_name()); + writeln!(w, r##"impl defmt::Format for {} {{"##, typ)?; + { + let mut w = PadAdapter::wrap(&mut w); + writeln!(w, "fn format(&self, f: defmt::Formatter) {{")?; + { + let mut w = PadAdapter::wrap(&mut w); + writeln!(w, r#"defmt::write!(f,"#)?; + { + let mut w = PadAdapter::wrap(&mut w); + write!(w, r#""{} {{{{"#, typ)?; + { + for signal in msg.signals() { + if *signal.multiplexer_indicator() == MultiplexIndicator::Plain { + write!(w, r#" {}={{:?}}"#, signal.name(),)?; + } + } + } + writeln!(w, r#" }}}}","#)?; + + for signal in msg.signals() { + if *signal.multiplexer_indicator() == MultiplexIndicator::Plain { + writeln!(w, "self.{}(),", field_name(signal.name()))?; + } + } + writeln!(w, r#");"#)?; + } + writeln!(w, "}}")?; + } + } + writeln!(w, "}}")?; + writeln!(w)?; + Ok(()) +} + fn render_multiplexor_enums( mut w: impl Write, config: &Config<'_>, @@ -1416,6 +1470,9 @@ fn render_multiplexor_enums( )?; config.impl_debug.fmt_attr(&mut w, "derive(Debug)")?; + config + .impl_defmt + .fmt_attr(&mut w, "derive(defmt::Format)")?; config.impl_serde.fmt_attr(&mut w, "derive(Serialize)")?; config.impl_serde.fmt_attr(&mut w, "derive(Deserialize)")?; writeln!( @@ -1443,6 +1500,9 @@ fn render_multiplexor_enums( let struct_name = multiplexed_enum_variant_name(msg, multiplexor_signal, **switch_index)?; config.impl_debug.fmt_attr(&mut w, "derive(Debug)")?; + config + .impl_defmt + .fmt_attr(&mut w, "derive(defmt::Format)")?; config.impl_serde.fmt_attr(&mut w, "derive(Serialize)")?; config.impl_serde.fmt_attr(&mut w, "derive(Deserialize)")?; writeln!(w, r##"#[derive(Default)]"##)?; diff --git a/testing/can-embedded/Cargo.toml b/testing/can-embedded/Cargo.toml index 9dbdbe3..e453fa9 100644 --- a/testing/can-embedded/Cargo.toml +++ b/testing/can-embedded/Cargo.toml @@ -11,7 +11,7 @@ build-messages = ["dep:can-messages"] [dependencies] bitvec = { version = "1.0", default-features = false } embedded-can = "0.4.1" - +defmt = "0.3.8" # This is optional and default so we can turn it off for the embedded target. # Then it doesn't pull in std. diff --git a/testing/can-messages/Cargo.toml b/testing/can-messages/Cargo.toml index 1a3b217..b4e357a 100644 --- a/testing/can-messages/Cargo.toml +++ b/testing/can-messages/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" bitvec = { version = "1.0", default-features = false } arbitrary = { version = "1.0", optional = true } embedded-can = "0.4.1" +defmt = "0.3.8" [build-dependencies] anyhow = "1.0" diff --git a/testing/can-messages/build.rs b/testing/can-messages/build.rs index 2f29922..5d7a7d0 100644 --- a/testing/can-messages/build.rs +++ b/testing/can-messages/build.rs @@ -19,6 +19,7 @@ fn main() -> Result<()> { .dbc_content(&dbc_file) .debug_prints(true) .impl_debug(FeatureConfig::Always) + .impl_defmt(FeatureConfig::Always) .impl_error(FeatureConfig::Gated("std")) .impl_arbitrary(FeatureConfig::Gated("arb")) .check_ranges(FeatureConfig::Always) diff --git a/testing/can-messages/src/messages.rs b/testing/can-messages/src/messages.rs index 5837f02..a78d2bd 100644 --- a/testing/can-messages/src/messages.rs +++ b/testing/can-messages/src/messages.rs @@ -21,7 +21,7 @@ use core::ops::BitOr; use embedded_can::{ExtendedId, Id, StandardId}; /// All messages -#[derive(Clone, Debug)] +#[derive(Clone, Debug, defmt::Format)] pub enum Messages { /// Foo Foo(Foo), @@ -272,6 +272,17 @@ impl core::fmt::Debug for Foo { } } +impl defmt::Format for Foo { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "Foo {{ Voltage={:?} Current={:?} }}", + self.voltage(), + self.current(), + ); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for Foo { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -622,6 +633,20 @@ impl core::fmt::Debug for Bar { } } +impl defmt::Format for Bar { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "Bar {{ One={:?} Two={:?} Three={:?} Four={:?} Type={:?} }}", + self.one(), + self.two(), + self.three(), + self.four(), + self.xtype(), + ); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for Bar { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -634,7 +659,7 @@ impl<'a> Arbitrary<'a> for Bar { } } /// Defined values for Three -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Debug, defmt::Format)] pub enum BarThree { Off, On, @@ -656,7 +681,7 @@ impl From for u8 { } /// Defined values for Four -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Debug, defmt::Format)] pub enum BarFour { Off, On, @@ -678,7 +703,7 @@ impl From for u8 { } /// Defined values for Type -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Debug, defmt::Format)] pub enum BarType { X0off, X1on, @@ -840,6 +865,12 @@ impl core::fmt::Debug for X4wd { } } +impl defmt::Format for X4wd { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "X4wd {{ _4DRIVE={:?} }}", self.x4drive(),); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for X4wd { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -848,7 +879,7 @@ impl<'a> Arbitrary<'a> for X4wd { } } /// Defined values for _4DRIVE -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Debug, defmt::Format)] pub enum X4wd4drive { Off, X2wd, @@ -1188,6 +1219,20 @@ impl core::fmt::Debug for Amet { } } +impl defmt::Format for Amet { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "Amet {{ One={:?} Two={:?} Three={:?} Four={:?} Five={:?} }}", + self.one(), + self.two(), + self.three(), + self.four(), + self.five(), + ); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for Amet { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -1342,6 +1387,12 @@ impl core::fmt::Debug for Dolor { } } +impl defmt::Format for Dolor { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "Dolor {{ OneFloat={:?} }}", self.one_float(),); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for Dolor { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -1350,7 +1401,7 @@ impl<'a> Arbitrary<'a> for Dolor { } } /// Defined values for OneFloat -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Debug, defmt::Format)] pub enum DolorOneFloat { Dolor, Other, @@ -1583,6 +1634,16 @@ impl core::fmt::Debug for MultiplexTest { } } +impl defmt::Format for MultiplexTest { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "MultiplexTest {{ UnmultiplexedSignal={:?} }}", + self.unmultiplexed_signal(), + ); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for MultiplexTest { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -1593,13 +1654,13 @@ impl<'a> Arbitrary<'a> for MultiplexTest { } } /// Defined values for multiplexed signal MultiplexTest -#[derive(Debug)] +#[derive(Debug, defmt::Format)] pub enum MultiplexTestMultiplexorIndex { M0(MultiplexTestMultiplexorM0), M1(MultiplexTestMultiplexorM1), } -#[derive(Debug, Default)] +#[derive(Debug, defmt::Format, Default)] pub struct MultiplexTestMultiplexorM0 { raw: [u8; 8], } @@ -1697,7 +1758,7 @@ impl MultiplexTestMultiplexorM0 { } } -#[derive(Debug, Default)] +#[derive(Debug, defmt::Format, Default)] pub struct MultiplexTestMultiplexorM1 { raw: [u8; 8], } @@ -2139,6 +2200,19 @@ impl core::fmt::Debug for IntegerFactorOffset { } } +impl defmt::Format for IntegerFactorOffset { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, + "IntegerFactorOffset {{ ByteWithOffset={:?} ByteWithFactor={:?} ByteWithBoth={:?} ByteWithNegativeOffset={:?} ByteWithNegativeMin={:?} }}", + self.byte_with_offset(), + self.byte_with_factor(), + self.byte_with_both(), + self.byte_with_negative_offset(), + self.byte_with_negative_min(), + ); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for IntegerFactorOffset { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -2354,6 +2428,17 @@ impl core::fmt::Debug for NegativeFactorTest { } } +impl defmt::Format for NegativeFactorTest { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "NegativeFactorTest {{ UnsignedNegativeFactorSignal={:?} WidthMoreThanMinMax={:?} }}", + self.unsigned_negative_factor_signal(), + self.width_more_than_min_max(), + ); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for NegativeFactorTest { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -2561,6 +2646,17 @@ impl core::fmt::Debug for LargerIntsWithOffsets { } } +impl defmt::Format for LargerIntsWithOffsets { + fn format(&self, f: defmt::Formatter) { + defmt::write!( + f, + "LargerIntsWithOffsets {{ Twelve={:?} Sixteen={:?} }}", + self.twelve(), + self.sixteen(), + ); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for LargerIntsWithOffsets { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -2656,6 +2752,12 @@ impl core::fmt::Debug for MsgWithoutSignals { } } +impl defmt::Format for MsgWithoutSignals { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "MsgWithoutSignals {{ }}",); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for MsgWithoutSignals { fn arbitrary(_u: &mut Unstructured<'a>) -> Result { @@ -2802,6 +2904,12 @@ impl core::fmt::Debug for TruncatedBeSignal { } } +impl defmt::Format for TruncatedBeSignal { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "TruncatedBeSignal {{ Foo={:?} }}", self.foo(),); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for TruncatedBeSignal { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -2949,6 +3057,12 @@ impl core::fmt::Debug for TruncatedLeSignal { } } +impl defmt::Format for TruncatedLeSignal { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "TruncatedLeSignal {{ Foo={:?} }}", self.foo(),); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for TruncatedLeSignal { fn arbitrary(u: &mut Unstructured<'a>) -> Result { @@ -3094,6 +3208,12 @@ impl core::fmt::Debug for MsgExtendedId { } } +impl defmt::Format for MsgExtendedId { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "MsgExtendedId {{ Dummy={:?} }}", self.dummy(),); + } +} + #[cfg(feature = "arb")] impl<'a> Arbitrary<'a> for MsgExtendedId { fn arbitrary(u: &mut Unstructured<'a>) -> Result {