Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support extended IDs and generate impls for embedded_can::Frame trait #82

Merged
merged 2 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ rust-version = "1.78.0"
std = []

[dependencies]
can-dbc = "5.0.0"
can-dbc = "6.0.0"
anyhow = "1.0.68"
heck = "0.4.0"
typed-builder = "0.18.0"
embedded-can = "0.4.1"

[workspace]
members = [
Expand Down
25 changes: 21 additions & 4 deletions fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/includes/errors.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CanError {
UnknownMessageId(u32),
UnknownMessageId(embedded_can::Id),
/// Signal parameter is not within the range
/// defined in the dbc
ParameterOutOfRange {
/// dbc message id
message_id: u32,
message_id: embedded_can::Id,
},
InvalidPayloadSize,
/// Multiplexor value not defined in the dbc
InvalidMultiplexor {
/// dbc message id
message_id: u32,
message_id: embedded_can::Id,
/// Multiplexor value not defined in the dbc
multiplexor: u16,
},
Expand Down
94 changes: 81 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ pub struct Config<'a> {
#[builder(default)]
pub impl_error: FeatureConfig<'a>,

/// Optional: Generate `embedded_can::Frame` impl for each frame. Default: `Always`
#[builder(default = FeatureConfig::Always)]
pub impl_embedded_can_frame: FeatureConfig<'a>,

/// Optional: Validate min and max values in generated signal setters. Default: `Always`
#[builder(default = FeatureConfig::Always)]
pub check_ranges: FeatureConfig<'a>,
Expand Down Expand Up @@ -143,6 +147,7 @@ pub fn codegen(config: Config<'_>, out: impl Write) -> Result<()> {
writeln!(&mut w)?;
writeln!(&mut w, "use core::ops::BitOr;")?;
writeln!(&mut w, "use bitvec::prelude::*;")?;
writeln!(&mut w, "use embedded_can::{{Id, StandardId, ExtendedId}};")?;

writeln!(w, r##"#[cfg(feature = "arb")]"##)?;
writeln!(&mut w, "use arbitrary::{{Arbitrary, Unstructured}};")?;
Expand Down Expand Up @@ -210,7 +215,7 @@ fn render_root_enum(mut w: impl Write, dbc: &DBC, config: &Config<'_>) -> Result
writeln!(w, "#[inline(never)]")?;
writeln!(
&mut w,
"pub fn from_can_message(id: u32, payload: &[u8]) -> Result<Self, CanError> {{",
"pub fn from_can_message(id: Id, payload: &[u8]) -> Result<Self, CanError> {{",
)?;
{
let mut w = PadAdapter::wrap(&mut w);
Expand All @@ -221,12 +226,11 @@ fn render_root_enum(mut w: impl Write, dbc: &DBC, config: &Config<'_>) -> Result
for msg in get_relevant_messages(dbc) {
writeln!(
w,
"{} => Messages::{1}({1}::try_from(payload)?),",
msg.message_id().0,
"{0}::MESSAGE_ID => Messages::{0}({0}::try_from(payload)?),",
type_name(msg.message_name())
)?;
}
writeln!(w, r#"n => return Err(CanError::UnknownMessageId(n)),"#)?;
writeln!(w, r#"id => return Err(CanError::UnknownMessageId(id)),"#)?;
}
writeln!(&mut w, "}};")?;
writeln!(&mut w, "Ok(res)")?;
Expand All @@ -243,7 +247,10 @@ fn render_root_enum(mut w: impl Write, dbc: &DBC, config: &Config<'_>) -> Result
fn render_message(mut w: impl Write, config: &Config<'_>, msg: &Message, dbc: &DBC) -> Result<()> {
writeln!(w, "/// {}", msg.message_name())?;
writeln!(w, "///")?;
writeln!(w, "/// - ID: {0} (0x{0:x})", msg.message_id().0)?;
match msg.message_id() {
can_dbc::MessageId::Standard(id) => writeln!(w, "/// - Standard ID: {0} (0x{0:x})", id),
can_dbc::MessageId::Extended(id) => writeln!(w, "/// - Extended ID: {0} (0x{0:x})", id),
}?;
writeln!(w, "/// - Size: {} bytes", msg.message_size())?;
if let can_dbc::Transmitter::NodeName(transmitter) = msg.transmitter() {
writeln!(w, "/// - Transmitter: {}", transmitter)?;
Expand Down Expand Up @@ -274,8 +281,18 @@ fn render_message(mut w: impl Write, config: &Config<'_>, msg: &Message, dbc: &D

writeln!(
&mut w,
"pub const MESSAGE_ID: u32 = {};",
msg.message_id().0
"pub const MESSAGE_ID: embedded_can::Id = {};",
match msg.message_id() {
// use StandardId::new().unwrap() once const_option is stable
can_dbc::MessageId::Standard(id) => format!(
"Id::Standard(unsafe {{ StandardId::new_unchecked({0:#x})}})",
id
),
can_dbc::MessageId::Extended(id) => format!(
"Id::Extended(unsafe {{ ExtendedId::new_unchecked({0:#x})}})",
id
),
}
)?;
writeln!(w)?;

Expand Down Expand Up @@ -415,6 +432,8 @@ fn render_message(mut w: impl Write, config: &Config<'_>, msg: &Message, dbc: &D
writeln!(w, "}}")?;
writeln!(w)?;

render_embedded_can_frame(&mut w, config, msg)?;

render_debug_impl(&mut w, config, msg)?;

render_arbitrary(&mut w, config, msg)?;
Expand Down Expand Up @@ -623,8 +642,8 @@ fn render_set_signal(
let mut w = PadAdapter::wrap(&mut w);
writeln!(
w,
r##"return Err(CanError::ParameterOutOfRange {{ message_id: {message_id} }});"##,
message_id = msg.message_id().0,
r##"return Err(CanError::ParameterOutOfRange {{ message_id: {}::MESSAGE_ID }});"##,
type_name(msg.message_name())
)?;
}
writeln!(w, r"}}")?;
Expand Down Expand Up @@ -742,8 +761,8 @@ fn render_multiplexor_signal(
}
writeln!(
&mut w,
"multiplexor => Err(CanError::InvalidMultiplexor {{ message_id: {}, multiplexor: multiplexor.into() }}),",
msg.message_id().0
"multiplexor => Err(CanError::InvalidMultiplexor {{ message_id: {}::MESSAGE_ID, multiplexor: multiplexor.into() }}),",
type_name(msg.message_name())
)?;
}

Expand Down Expand Up @@ -914,8 +933,7 @@ fn signal_to_payload(mut w: impl Write, signal: &Signal, msg: &Message) -> Resul
}
writeln!(
&mut w,
" .ok_or(CanError::ParameterOutOfRange {{ message_id: {} }})?;",
msg.message_id().0,
" .ok_or(CanError::ParameterOutOfRange {{ message_id: Self::MESSAGE_ID }})?;",
)?;
writeln!(
&mut w,
Expand Down Expand Up @@ -1273,6 +1291,56 @@ fn multiplexed_enum_variant_name(
))
}

fn render_embedded_can_frame(
w: &mut impl Write,
config: &Config<'_>,
msg: &Message,
) -> Result<(), std::io::Error> {
config.impl_embedded_can_frame.fmt_cfg(w, |w| {
writeln!(
w,
"\
impl embedded_can::Frame for {0} {{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we gate this with a feature flag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added feature flag defaulting to Always as embedded_can crate dependency is required anyway for representing CAN frame IDs

fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {{
if id.into() != Self::MESSAGE_ID {{
None
}} else {{
data.try_into().ok()
}}
}}

fn new_remote(_id: impl Into<Id>, _dlc: usize) -> Option<Self> {{
unimplemented!()
}}

fn is_extended(&self) -> bool {{
match self.id() {{
Id::Standard(_) => false,
Id::Extended(_) => true,
}}
}}

fn is_remote_frame(&self) -> bool {{
false
}}

fn id(&self) -> Id {{
Self::MESSAGE_ID
}}

fn dlc(&self) -> usize {{
self.raw.len()
}}

fn data(&self) -> &[u8] {{
&self.raw
}}
}}",
type_name(msg.message_name())
)
})
}

fn render_debug_impl(mut w: impl Write, config: &Config<'_>, msg: &Message) -> Result<()> {
match &config.impl_debug {
FeatureConfig::Always => {}
Expand Down
1 change: 1 addition & 0 deletions testing/can-embedded/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ build-messages = ["dep:can-messages"]

[dependencies]
bitvec = { version = "1.0", default-features = false }
embedded-can = "0.4.1"


# This is optional and default so we can turn it off for the embedded target.
Expand Down
3 changes: 2 additions & 1 deletion testing/can-messages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
bitvec = { version = "1.0", default-features = false }
arbitrary = { version = "1.0", optional = true }
embedded-can = "0.4.1"

[build-dependencies]
anyhow = "1.0"
Expand All @@ -15,4 +16,4 @@ dbc-codegen = { path = "../../" }
[features]
default = ["arb", "std"]
arb = ["arbitrary"]
std = []
std = []
Loading
Loading