diff --git a/codegen-tests/snapshot-tests/snapshots.rs b/codegen-tests/snapshot-tests/snapshots.rs index 9436f4b..7d16d34 100644 --- a/codegen-tests/snapshot-tests/snapshots.rs +++ b/codegen-tests/snapshot-tests/snapshots.rs @@ -15,7 +15,7 @@ fn generated_path(output_base: &Path, lang: Language) -> PathBuf { fn generate_snapshot_fixture(lang: Language) -> String { let tempdir = tempfile::tempdir().expect("failed to create temp output directory"); let output_base = tempdir.path().join("generated"); - let generated_path = generated_path(&output_base, lang.clone()); + let generated_path = generated_path(&output_base, lang); let output = output_base .to_str() .expect("temp output path should be valid UTF-8") @@ -34,7 +34,7 @@ fn generate_snapshot_fixture(lang: Language) -> String { separate: false, }; - CodegenPipeline::run(config).expect("codegen should succeed for snapshot fixture"); + CodegenPipeline::run(&config).expect("codegen should succeed for snapshot fixture"); fs::read_to_string(generated_path).expect("generated file should be readable") } diff --git a/codegen-tests/src/lib.rs b/codegen-tests/src/lib.rs index 23c263f..3fc2347 100644 --- a/codegen-tests/src/lib.rs +++ b/codegen-tests/src/lib.rs @@ -97,7 +97,7 @@ mod tests { "#[inline(always)]", ); - CodegenPipeline::run(config).context("codegen failed") + CodegenPipeline::run(&config).context("codegen failed") } fn run_quiet(command: &mut Command, label: &str) -> Result<()> { diff --git a/src/app.rs b/src/app.rs index 9f2c3ec..bbd8082 100644 --- a/src/app.rs +++ b/src/app.rs @@ -26,7 +26,7 @@ use std::path::Path; pub struct CodegenPipeline; impl CodegenPipeline { - pub fn run(config: CodegenConfig) -> anyhow::Result<()> { + pub fn run(config: &CodegenConfig) -> anyhow::Result<()> { let mut parsed_dbcs = config.inputs.iter().map(|input| { let data = fs::read_to_string(input) .with_context(|| format!("Unable to read input file `{input}`"))?; @@ -47,26 +47,26 @@ impl CodegenPipeline { let mut dbc = IRBuilder::to_ir(merged_parsed_dbc); - TransformationPipeline::new() - .add(ComputeBitvecPositions) - .add(AttachMessageSignalUsage) - .add(InferSignalTypes) + TransformationPipeline::default() + .add_node(ComputeBitvecPositions) + .add_node(AttachMessageSignalUsage) + .add_node(InferSignalTypes) .run(&mut dbc); let mut diagnostics = Diagnostics::default(); CheckPipeline::new() - .add(CheckZeroZeroRanges { + .add_node(CheckZeroZeroRanges { zero_zero_range_allows_all: config.zero_zero_range_allows_all, }) - .add(CheckUniqueMessageIds) - .add(CheckSignalLayoutValidity) - .add(CheckMessageSignalUsage) - .add(CheckUnsupportedMultiplexing) - .add(CheckEnumVariants) - .add(CheckSignalPhysicalRangeRepresentable { + .add_node(CheckUniqueMessageIds) + .add_node(CheckSignalLayoutValidity) + .add_node(CheckMessageSignalUsage) + .add_node(CheckUnsupportedMultiplexing) + .add_node(CheckEnumVariants) + .add_node(CheckSignalPhysicalRangeRepresentable { zero_zero_range_allows_all: config.zero_zero_range_allows_all, }) - .add(CheckSignalScalingArithmeticSafety) + .add_node(CheckSignalScalingArithmeticSafety) .run(&dbc, &mut diagnostics); diagnostics.emit(); @@ -75,23 +75,23 @@ impl CodegenPipeline { anyhow::bail!("En error was found during validation phase!"); } - TransformationPipeline::new() - .add(SanitizeSignalEnumVariantNames) - .add(DeduplicateSignalValueEnums { + TransformationPipeline::default() + .add_node(SanitizeSignalEnumVariantNames) + .add_node(DeduplicateSignalValueEnums { dedup_enabled: !config.no_enum_dedup, }) - .add(PrefixSignalValueEnumName { + .add_node(PrefixSignalValueEnumName { dedup_enabled: !config.no_enum_dedup, }) - .add(AttachSignalValueEnumType) - .add(SanitizeMessageNames) - .add(SanitizeSVENames) - .add(SanitizeSignalNames) + .add_node(AttachSignalValueEnumType) + .add_node(SanitizeMessageNames) + .add_node(SanitizeSVENames) + .add_node(SanitizeSignalNames) .run(&mut dbc); match &config.lang { Language::Rust => { - let code = codegen::rust::RustGen::generate(&dbc, &config); + let code = codegen::rust::RustGen::generate(&dbc, config); let out = PathBuf::from(&config.output).with_extension(config.lang.file_extension()); std::fs::write(out, code)?; @@ -105,12 +105,12 @@ impl CodegenPipeline { .and_then(|stem| stem.to_str()) .context("C++ output path must have a valid UTF-8 file stem")?; - for generated in codegen::cpp::CppGen::generate_separate(&dbc, &config, stem) { + for generated in codegen::cpp::CppGen::generate_separate(&dbc, config, stem) { std::fs::write(parent.join(generated.file_name), generated.contents)?; } } Language::Cpp => { - let code = codegen::cpp::CppGen::generate(&dbc, &config); + let code = codegen::cpp::CppGen::generate(&dbc, config); let out = PathBuf::from(&config.output).with_extension(config.lang.file_extension()); std::fs::write(out, code)?; diff --git a/src/codegen/cpp.rs b/src/codegen/cpp.rs index ca38240..da3ab7d 100644 --- a/src/codegen/cpp.rs +++ b/src/codegen/cpp.rs @@ -1,4 +1,7 @@ -use std::collections::{BTreeMap, BTreeSet}; +use std::{ + collections::{BTreeMap, BTreeSet}, + string::ToString, +}; use heck::ToSnakeCase; @@ -36,6 +39,7 @@ fn cpp_code_injections(out: &mut Generator, config: &CodegenConfig, point: CppCo } impl CppGen { + #[must_use] pub fn generate(file: &DbcFile, config: &CodegenConfig) -> String { let mut out = Generator::new(); @@ -57,6 +61,7 @@ impl CppGen { out.into_string() } + #[must_use] pub fn generate_separate( file: &DbcFile, config: &CodegenConfig, @@ -172,10 +177,10 @@ impl CppGen { let mut emitted_enum_idxs = BTreeSet::new(); for signal in &file.signals { - if let Some(idx) = signal.signal_value_enum_idx { - if emitted_enum_idxs.insert(idx.0) { - Self::signal_value_enum(out, signal, &file.signal_value_enums[idx.0], config); - } + if let Some(idx) = signal.signal_value_enum_idx + && emitted_enum_idxs.insert(idx.0) + { + Self::signal_value_enum(out, signal, &file.signal_value_enums[idx.0], config); } } } @@ -340,10 +345,10 @@ impl CppGen { fn emit_message_id(out: &mut Generator, msg: &Message) { match msg.id { MessageId::Standard(id) => { - line!(out, "static constexpr CanId ID = CanId::standard({});", id) + line!(out, "static constexpr CanId ID = CanId::standard({});", id); } MessageId::Extended(id) => { - line!(out, "static constexpr CanId ID = CanId::extended({});", id) + line!(out, "static constexpr CanId ID = CanId::extended({});", id); } } } @@ -836,8 +841,8 @@ impl CppGen { ]; if let Some(comment) = &msg.comment { - lines.push("".into()); - lines.extend(comment.lines().map(|l| l.to_string())); + lines.push(String::new()); + lines.extend(comment.lines().map(ToString::to_string)); } line!(out, "/**"); @@ -855,7 +860,7 @@ impl CppGen { let max = layout.max; let unit = &signal.unit; let receivers = if signal.receivers.is_empty() { - "".into() + String::new() } else { signal .receivers @@ -898,8 +903,8 @@ impl CppGen { ]; if let Some(comment) = &signal.comment { - lines.push("".into()); - lines.extend(comment.lines().map(|l| l.to_string())); + lines.push(String::new()); + lines.extend(comment.lines().map(ToString::to_string)); } line!(out, "/**"); @@ -1402,7 +1407,7 @@ impl CppGen { start_block!(out, "std::visit([&msg](const auto& v)"); line!(out, "using T = std::decay_t;"); - for (mux_value, _) in &muxed_sigs { + for mux_value in muxed_sigs.keys() { let variant_class = format!("{}Mux{}", msg_name, mux_value); start_block!(out, "if constexpr (std::is_same_v)", variant_class); line!(out, "msg.set_mux_{}(v);", mux_value); @@ -1438,7 +1443,7 @@ impl CppGen { mux_layout, ); start_block!(out, "switch (mux_raw)"); - for (mux_value, _) in &muxed_sigs { + for mux_value in muxed_sigs.keys() { let variant_class = format!("{}Mux{}", msg_name, mux_value); start_block!(out, "case {}:", mux_value); line!(out, "{} inner{{}};", variant_class); @@ -1955,7 +1960,7 @@ impl CppGen { let field_name = signal.name.raw.to_snake_case(); let invalid_var = format!("{}_out_of_range", field_name); let mut constructor_args = Self::test_vars(signals, valid_suffix); - constructor_args[bad_idx] = invalid_var.clone(); + constructor_args[bad_idx].clone_from(&invalid_var); constructor_args.extend(trailing_args.iter().cloned()); start_block!(out, ""); @@ -2358,7 +2363,12 @@ impl CppGen { } if Self::is_bool_signal(signal, file) { - return if ordinal % 2 == 0 { "false" } else { "true" }.to_string(); + return if ordinal.is_multiple_of(2) { + "false" + } else { + "true" + } + .to_string(); } let layout = &file.signal_layouts[signal.layout.0]; @@ -2426,7 +2436,7 @@ impl CppGen { let candidates = [ layout.min + 1.0, layout.max - 1.0, - (layout.min + layout.max) / 2.0, + f64::midpoint(layout.min, layout.max), layout.min, layout.max, ]; @@ -2463,12 +2473,12 @@ impl CppGen { let min = layout.min; let max = layout.max; let type_min = if phys_type == "float" { - f32::MIN as f64 + f64::from(f32::MIN) } else { f64::MIN }; let type_max = if phys_type == "float" { - f32::MAX as f64 + f64::from(f32::MAX) } else { f64::MAX }; @@ -2531,7 +2541,7 @@ impl CppGen { match ordinal % 3 { 0 => layout.min, 1 => layout.max, - _ => (layout.min + layout.max) / 2.0, + _ => f64::midpoint(layout.min, layout.max), } } else { match ordinal % 5 { @@ -2583,7 +2593,7 @@ impl CppGen { let midpoint = low .checked_add(high) .map(|v| v / 2) - .or_else(|| if low <= 0 && high >= 0 { Some(0) } else { None }); + .or(if low <= 0 && 0 <= high { Some(0) } else { None }); let mut candidates = Vec::new(); let ordered = if prefer_bounds { @@ -2708,7 +2718,7 @@ impl CppGen { let used = enum_def .variants .iter() - .map(|variant| variant.value as i128) + .map(|variant| i128::from(variant.value)) .collect::>(); let layout = &file.signal_layouts[signal.layout.0]; let (low, high) = Self::integer_raw_range(layout); @@ -2721,7 +2731,7 @@ impl CppGen { muxed: &BTreeMap>, file: &DbcFile, ) -> Option { - let used = muxed.keys().map(|value| *value as i128).collect(); + let used = muxed.keys().map(|value| i128::from(*value)).collect(); let layout = &file.signal_layouts[mux_signal.layout.0]; let (low, high) = Self::integer_raw_range(layout); diff --git a/src/codegen/generator.rs b/src/codegen/generator.rs index b232b3b..4da92e3 100644 --- a/src/codegen/generator.rs +++ b/src/codegen/generator.rs @@ -5,10 +5,12 @@ pub struct Generator { } impl Generator { + #[must_use] pub fn new() -> Self { Self::with_indent(" ") } + #[must_use] pub fn with_indent(indent: &str) -> Self { Self { buffer: String::new(), @@ -45,14 +47,16 @@ impl Generator { if !text.is_empty() { self.push_indent(); self.buffer.push_str(text); - self.buffer.push_str("\n"); + self.buffer.push('\n'); } } + #[must_use] pub fn get(&self) -> &str { &self.buffer } + #[must_use] pub fn into_string(self) -> String { self.buffer } diff --git a/src/codegen/rust.rs b/src/codegen/rust.rs index 075d0ef..b970601 100644 --- a/src/codegen/rust.rs +++ b/src/codegen/rust.rs @@ -39,6 +39,7 @@ fn rust_code_injection_tokens( } impl RustGen { + #[must_use] pub fn generate(file: &DbcFile, config: &CodegenConfig) -> String { let imports = quote! { use embedded_can::{Frame, Id, StandardId, ExtendedId}; @@ -59,7 +60,7 @@ impl RustGen { .map(|m| MessageDef { msg: m, file, - config: config, + config, }) .collect(); @@ -213,7 +214,7 @@ impl ToTokens for MessageDef<'_> { if muxed.is_empty() { self.generate_plain(tokens, &signals); } else { - self.generate_mux(tokens, plain, muxed, mux_signal.unwrap()); + self.generate_mux(tokens, &plain, &muxed, mux_signal.unwrap()); } } } @@ -237,14 +238,14 @@ impl MessageDef<'_> { } }; - let len = msg.size as usize; + let len = usize::try_from(msg.size).unwrap(); let constructor_params = Self::gen_constructor_params(&signals); let constructor_body = Self::gen_constructor_body(&signals); let getters = Self::gen_getters(&signals, self.config); let setters = Self::gen_setters(&signals, self.config); - let doc = message_doc(&msg); + let doc = message_doc(msg); let injected = rust_code_injection_tokens(self.config, RustCodeInjectionPoint::MessageStruct); let can_msg_impl = Self::gen_can_message_impl(&name); @@ -326,8 +327,8 @@ impl MessageDef<'_> { fn generate_mux( &self, tokens: &mut TokenStream, - plain: Vec<&SignalCtx>, - muxed: BTreeMap>, + plain: &[&SignalCtx], + muxed: &BTreeMap>, mux_signal: &SignalCtx, ) { let msg = self.msg; @@ -343,9 +344,9 @@ impl MessageDef<'_> { } }; - let len = msg.size as usize; + let len = usize::try_from(msg.size).unwrap(); - let doc = message_doc(&msg); + let doc = message_doc(msg); let variant_structs = muxed.iter().map(|(idx, sigs)| { let struct_name = format_ident!("{}Mux{}", name, idx); @@ -451,8 +452,8 @@ impl MessageDef<'_> { } }); - let plain_params = Self::gen_constructor_params(&plain); - let constructor_body = Self::gen_constructor_body(&plain); + let plain_params = Self::gen_constructor_params(plain); + let constructor_body = Self::gen_constructor_body(plain); let mux_apply_arms = muxed.keys().map(|idx| { let variant = format_ident!("V{}", idx); let setter = format_ident!("set_mux{}", idx); @@ -463,8 +464,8 @@ impl MessageDef<'_> { } } }); - let plain_getters = Self::gen_getters(&plain, self.config); - let plain_setters = Self::gen_setters(&plain, self.config); + let plain_getters = Self::gen_getters(plain, self.config); + let plain_setters = Self::gen_setters(plain, self.config); let mux_enum_injected = rust_code_injection_tokens(self.config, RustCodeInjectionPoint::MuxEnum); @@ -539,7 +540,7 @@ impl MessageDef<'_> { signals.iter().map(|s| { let field = s.field_ident(); let ty = s.rust_type(); - let doc = getter_doc(&s); + let doc = getter_doc(s); let read = s.decode_read(); let expr = s.decode_expr(); @@ -622,7 +623,7 @@ impl ToTokens for SignalValueEnumCtx<'_> { } } -impl<'a> SignalValueEnumCtx<'a> { +impl SignalValueEnumCtx<'_> { fn gen_with_other( &self, enum_name: &Ident, @@ -1224,12 +1225,12 @@ impl ToTokens for PlainMessageTest<'_> { let first_values = self.signals.iter().map(|s| { let var = format_ident!("{}_value", s.signal.name.snake_case()); - s.test_value_statement(&var, format_ident!("u")) + s.test_value_statement(&var, &format_ident!("u")) }); let second_values = self.signals.iter().map(|s| { let var = format_ident!("{}_next_value", s.signal.name.snake_case()); - s.test_value_statement(&var, format_ident!("u")) + s.test_value_statement(&var, &format_ident!("u")) }); let constructor_args = self @@ -1299,7 +1300,7 @@ impl ToTokens for MultiplexedMessageTest<'_> { .iter() .map(|s| { let var = format_ident!("{}_value", s.signal.name.snake_case()); - s.test_value_statement(&var, format_ident!("u")) + s.test_value_statement(&var, &format_ident!("u")) }) .collect(); @@ -1308,7 +1309,7 @@ impl ToTokens for MultiplexedMessageTest<'_> { .iter() .map(|s| { let var = format_ident!("{}_next_value", s.signal.name.snake_case()); - s.test_value_statement(&var, format_ident!("u")) + s.test_value_statement(&var, &format_ident!("u")) }) .collect(); @@ -1369,12 +1370,12 @@ impl ToTokens for MultiplexedMessageTest<'_> { let first_values = sigs.iter().map(|s| { let var = format_ident!("{}_value", s.signal.name.snake_case()); - s.test_value_statement(&var, format_ident!("u")) + s.test_value_statement(&var, &format_ident!("u")) }); let second_values = sigs.iter().map(|s| { let var = format_ident!("{}_next_value", s.signal.name.snake_case()); - s.test_value_statement(&var, format_ident!("u")) + s.test_value_statement(&var, &format_ident!("u")) }); let constructor_args = sigs.iter().map(|s| { @@ -1403,12 +1404,12 @@ impl ToTokens for MultiplexedMessageTest<'_> { let next_first_values = next_sigs.iter().map(|s| { let var = format_ident!("{}_switch_value", s.signal.name.snake_case()); - s.test_value_statement(&var, format_ident!("u")) + s.test_value_statement(&var, &format_ident!("u")) }); let next_second_values = next_sigs.iter().map(|s| { let var = format_ident!("{}_switch_next_value", s.signal.name.snake_case()); - s.test_value_statement(&var, format_ident!("u")) + s.test_value_statement(&var, &format_ident!("u")) }); let next_constructor_args = next_sigs.iter().map(|s| { @@ -1520,8 +1521,8 @@ impl ToTokens for MultiplexedMessageTest<'_> { } } -impl<'a> SignalCtx<'a> { - fn test_value_statement(&self, var: &Ident, arbitrary: Ident) -> TokenStream { +impl SignalCtx<'_> { + fn test_value_statement(&self, var: &Ident, arbitrary: &Ident) -> TokenStream { if self.is_enum() { let enum_name = self.enum_ident(); @@ -1583,7 +1584,7 @@ impl<'a> SignalCtx<'a> { let #var: #ty = { let raw = #arbitrary .int_in_range(#min..=#max) - .expect("failed to generate physical interger value"); + .expect("failed to generate physical integer value"); raw }; } diff --git a/src/ir/identifier.rs b/src/ir/identifier.rs index accee92..b2ad1e9 100644 --- a/src/ir/identifier.rs +++ b/src/ir/identifier.rs @@ -9,6 +9,7 @@ pub struct Identifier { } impl Identifier { + #[must_use] pub fn from_raw(raw: String) -> Self { Self { prefix: String::new(), @@ -17,22 +18,27 @@ impl Identifier { } } + #[must_use] pub fn raw(&self) -> &str { &self.raw } + #[must_use] pub fn rendered(&self) -> String { format!("{}{}{}", self.prefix, self.raw, self.postfix) } + #[must_use] pub fn lower(&self) -> String { self.rendered().to_lowercase() } + #[must_use] pub fn upper_camel(&self) -> String { self.rendered().to_upper_camel_case() } + #[must_use] pub fn snake_case(&self) -> String { self.rendered().to_snake_case() } @@ -43,17 +49,15 @@ impl Identifier { } } + #[must_use] pub fn upper_camel_with_numeric_postfix(&self) -> String { - let numeric_postfix: String = self - .postfix - .chars() - .filter(|ch| ch.is_ascii_digit()) - .collect(); + let numeric_postfix: String = self.postfix.chars().filter(char::is_ascii_digit).collect(); format!("{}{}{}", self.prefix, self.raw, numeric_postfix).to_upper_camel_case() } } +#[must_use] pub fn is_valid_identifier(candidate: &str) -> bool { let mut chars = candidate.chars(); diff --git a/src/ir/ir_builder.rs b/src/ir/ir_builder.rs index c3db8b0..ba612bc 100644 --- a/src/ir/ir_builder.rs +++ b/src/ir/ir_builder.rs @@ -31,6 +31,7 @@ pub struct IRBuilder { } impl IRBuilder { + #[must_use] pub fn to_ir(value: ParsedDbc) -> DbcFile { let mut builder = Self::new(value); builder.build(); @@ -42,9 +43,11 @@ impl IRBuilder { let extended_type_map = Self::extended_type_map(value.signal_extended_value_type_list); let (message_comment_map, signal_comment_map) = Self::comment_maps(value.comments); - let mut file = DbcFile::default(); - file.nodes = map_into(value.nodes); - file.has_extended_mux_symbols = !value.extended_multiplex.is_empty(); + let file = DbcFile { + nodes: map_into(value.nodes), + has_extended_mux_symbols: !value.extended_multiplex.is_empty(), + ..Default::default() + }; Self { file, diff --git a/src/ir/message.rs b/src/ir/message.rs index 36b04dd..bfb075e 100644 --- a/src/ir/message.rs +++ b/src/ir/message.rs @@ -17,6 +17,7 @@ pub struct Message { } impl Message { + #[must_use] pub fn from_parsed( id: ParsedMessageId, name: String, @@ -29,15 +30,16 @@ impl Message { Message { id: id.into(), name: Identifier::from_raw(name), - size: size, + size, transmitter: Transmitter::from(transmitter), signal_idxs: signals, - layout: layout, + layout, comment, signal_usage: None, } } + #[must_use] pub fn classify_signals(&self, signals: &[Signal]) -> MessageSignalClassification { let mut plain = Vec::new(); let mut mux_signal = None; diff --git a/src/ir/signal_extended_value_type.rs b/src/ir/signal_extended_value_type.rs index 2402a8f..4fa4fa5 100644 --- a/src/ir/signal_extended_value_type.rs +++ b/src/ir/signal_extended_value_type.rs @@ -1,6 +1,6 @@ use can_dbc::SignalExtendedValueType as ParsedExtendedValueType; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub enum ExtendedValueType { Integer, Float32, diff --git a/src/ir/signal_value_enum.rs b/src/ir/signal_value_enum.rs index c041c85..44fbef8 100644 --- a/src/ir/signal_value_enum.rs +++ b/src/ir/signal_value_enum.rs @@ -14,6 +14,7 @@ pub struct SignalValueEnum { } impl SignalValueEnum { + #[must_use] pub fn from_parsed(name: String, variants: Vec) -> Self { Self { name: Identifier::from_raw(name), diff --git a/src/ir/signal_value_type.rs b/src/ir/signal_value_type.rs index ee3caa6..5034cba 100644 --- a/src/ir/signal_value_type.rs +++ b/src/ir/signal_value_type.rs @@ -62,33 +62,32 @@ pub enum PhysicalType { } impl PhysicalType { + #[must_use] pub fn is_float(&self) -> bool { - match self { - PhysicalType::Float32 | PhysicalType::Float64 => true, - _ => false, - } + matches!(self, PhysicalType::Float32 | PhysicalType::Float64) } + #[must_use] pub fn min_value_f64(&self) -> f64 { match self { PhysicalType::Bool => 0.0, - PhysicalType::Float32 => f32::MIN as f64, + PhysicalType::Float32 => f64::from(f32::MIN), PhysicalType::Float64 => f64::MIN, - PhysicalType::Integer(repr) => repr.min_value_f64(), - PhysicalType::Enum { repr, .. } => repr.min_value_f64(), + PhysicalType::Integer(repr) | PhysicalType::Enum { repr, .. } => repr.min_value_f64(), } } + #[must_use] pub fn max_value_f64(&self) -> f64 { match self { PhysicalType::Bool => 1.0, - PhysicalType::Float32 => f32::MAX as f64, + PhysicalType::Float32 => f64::from(f32::MAX), PhysicalType::Float64 => f64::MAX, - PhysicalType::Integer(repr) => repr.max_value_f64(), - PhysicalType::Enum { repr, .. } => repr.max_value_f64(), + PhysicalType::Integer(repr) | PhysicalType::Enum { repr, .. } => repr.max_value_f64(), } } + #[must_use] pub fn integer_range_f64(&self) -> Option<(f64, f64)> { match self { PhysicalType::Integer(repr) | PhysicalType::Enum { repr, .. } => { @@ -126,8 +125,7 @@ impl CppType for PhysicalType { impl RustIntegerLiteral for PhysicalType { fn literal(&self, value: i64) -> Literal { match self { - PhysicalType::Integer(repr) => repr.literal(value), - PhysicalType::Enum { repr, .. } => repr.literal(value), + PhysicalType::Integer(repr) | PhysicalType::Enum { repr, .. } => repr.literal(value), _ => panic!("Use only with integer types"), } } @@ -159,6 +157,7 @@ pub enum IntReprType { } impl IntReprType { + #[must_use] pub fn from_size_sign(size: u64, signed: bool) -> IntReprType { match (signed, size) { (false, 0..=8) => IntReprType::U8, @@ -175,55 +174,60 @@ impl IntReprType { } } + #[must_use] pub fn min_value_i64(&self) -> i64 { match self { Self::U8 | Self::U16 | Self::U32 | Self::U64 | Self::U128 => 0, - Self::I8 => i8::MIN as i64, - Self::I16 => i16::MIN as i64, - Self::I32 => i32::MIN as i64, + Self::I8 => i64::from(i8::MIN), + Self::I16 => i64::from(i16::MIN), + Self::I32 => i64::from(i32::MIN), Self::I64 | Self::I128 => i64::MIN, } } + #[must_use] pub fn max_value_i64(&self) -> i64 { match self { - Self::U8 => u8::MAX as i64, - Self::U16 => u16::MAX as i64, - Self::U32 => u32::MAX as i64, + Self::U8 => i64::from(u8::MAX), + Self::U16 => i64::from(u16::MAX), + Self::U32 => i64::from(u32::MAX), Self::U64 | Self::U128 => i64::MAX, - Self::I8 => i8::MAX as i64, - Self::I16 => i16::MAX as i64, - Self::I32 => i32::MAX as i64, + Self::I8 => i64::from(i8::MAX), + Self::I16 => i64::from(i16::MAX), + Self::I32 => i64::from(i32::MAX), Self::I64 | Self::I128 => i64::MAX, } } + #[must_use] pub fn min_value_f64(self) -> f64 { match self { Self::U8 | Self::U16 | Self::U32 | Self::U64 | Self::U128 => 0.0, - Self::I8 => i8::MIN as f64, - Self::I16 => i16::MIN as f64, - Self::I32 => i32::MIN as f64, + Self::I8 => f64::from(i8::MIN), + Self::I16 => f64::from(i16::MIN), + Self::I32 => f64::from(i32::MIN), Self::I64 => i64::MIN as f64, Self::I128 => i128::MIN as f64, } } + #[must_use] pub fn max_value_f64(self) -> f64 { match self { - Self::U8 => u8::MAX as f64, - Self::U16 => u16::MAX as f64, - Self::U32 => u32::MAX as f64, + Self::U8 => f64::from(u8::MAX), + Self::U16 => f64::from(u16::MAX), + Self::U32 => f64::from(u32::MAX), Self::U64 => u64::MAX as f64, Self::U128 => u128::MAX as f64, - Self::I8 => i8::MAX as f64, - Self::I16 => i16::MAX as f64, - Self::I32 => i32::MAX as f64, + Self::I8 => f64::from(i8::MAX), + Self::I16 => f64::from(i16::MAX), + Self::I32 => f64::from(i32::MAX), Self::I64 => i64::MAX as f64, Self::I128 => i128::MAX as f64, } } + #[must_use] pub fn is_unsigned(&self) -> bool { matches!( self, @@ -231,32 +235,34 @@ impl IntReprType { ) } + #[must_use] pub fn from_min_max(min: i128, max: i128) -> Self { if min < 0 { - if min >= i8::MIN as i128 && max <= i8::MAX as i128 { + if min >= i128::from(i8::MIN) && max <= i128::from(i8::MAX) { IntReprType::I8 - } else if min >= i16::MIN as i128 && max <= i16::MAX as i128 { + } else if min >= i128::from(i16::MIN) && max <= i128::from(i16::MAX) { IntReprType::I16 - } else if min >= i32::MIN as i128 && max <= i32::MAX as i128 { + } else if min >= i128::from(i32::MIN) && max <= i128::from(i32::MAX) { IntReprType::I32 - } else if min >= i64::MIN as i128 && max <= i64::MAX as i128 { + } else if min >= i128::from(i64::MIN) && max <= i128::from(i64::MAX) { IntReprType::I64 } else { IntReprType::I128 } - } else if max <= u8::MAX as i128 { + } else if max <= i128::from(u8::MAX) { IntReprType::U8 - } else if max <= u16::MAX as i128 { + } else if max <= i128::from(u16::MAX) { IntReprType::U16 - } else if max <= u32::MAX as i128 { + } else if max <= i128::from(u32::MAX) { IntReprType::U32 - } else if max <= u64::MAX as i128 { + } else if max <= i128::from(u64::MAX) { IntReprType::U64 } else { IntReprType::U128 } } + #[must_use] pub fn unsigned(self) -> Self { match self { Self::U8 | Self::I8 => Self::U8, @@ -267,6 +273,7 @@ impl IntReprType { } } + #[must_use] pub fn signed(self) -> Self { match self { Self::U8 | Self::I8 => Self::I8, @@ -277,6 +284,7 @@ impl IntReprType { } } + #[must_use] pub fn bits(self) -> u32 { match self { Self::U8 | Self::I8 => 8, @@ -325,16 +333,16 @@ impl CppType for IntReprType { impl RustIntegerLiteral for IntReprType { fn literal(&self, value: i64) -> Literal { match self { - Self::U8 => Literal::u8_suffixed(value as u8), - Self::U16 => Literal::u16_suffixed(value as u16), - Self::U32 => Literal::u32_suffixed(value as u32), - Self::U64 => Literal::u64_suffixed(value as u64), - Self::U128 => Literal::u128_suffixed(value as u128), - Self::I8 => Literal::i8_suffixed(value as i8), - Self::I16 => Literal::i16_suffixed(value as i16), - Self::I32 => Literal::i32_suffixed(value as i32), + Self::U8 => Literal::u8_suffixed(u8::try_from(value).unwrap()), + Self::U16 => Literal::u16_suffixed(u16::try_from(value).unwrap()), + Self::U32 => Literal::u32_suffixed(u32::try_from(value).unwrap()), + Self::U64 => Literal::u64_suffixed(u64::try_from(value).unwrap()), + Self::U128 => Literal::u128_suffixed(u128::try_from(value).unwrap()), + Self::I8 => Literal::i8_suffixed(i8::try_from(value).unwrap()), + Self::I16 => Literal::i16_suffixed(i16::try_from(value).unwrap()), + Self::I32 => Literal::i32_suffixed(i32::try_from(value).unwrap()), Self::I64 => Literal::i64_suffixed(value), - Self::I128 => Literal::i128_suffixed(value as i128), + Self::I128 => Literal::i128_suffixed(i128::from(value)), } } } diff --git a/src/main.rs b/src/main.rs index 8e3304a..82a47a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,7 +76,7 @@ fn main() { match cli.command { Command::Parse { input, output } => { let dbc = parse_dbc_file(&input); - if let Err(e) = write_parsed_dbc(dbc, &output) { + if let Err(e) = write_parsed_dbc(&dbc, &output) { eprintln!("Error parsing dbc: {e}"); } } @@ -84,7 +84,7 @@ fn main() { Command::Ir { input, output } => { let dbc = parse_dbc_file(&input); let ir = IRBuilder::to_ir(dbc); - if let Err(e) = write_ir(ir, &output) { + if let Err(e) = write_ir(&ir, &output) { eprintln!("Error writing IR: {e}"); } } @@ -121,7 +121,7 @@ fn main() { "#[inline(always)]", ); - if let Err(err) = CodegenPipeline::run(config) { + if let Err(err) = CodegenPipeline::run(&config) { eprintln!("{:#}", err); std::process::exit(1); } @@ -129,7 +129,7 @@ fn main() { } } -fn write_parsed_dbc(dbc: ParsedDbc, output: &str) -> std::io::Result<()> { +fn write_parsed_dbc(dbc: &ParsedDbc, output: &str) -> std::io::Result<()> { let output_file = File::create(output)?; let mut writer = BufWriter::new(output_file); @@ -139,7 +139,7 @@ fn write_parsed_dbc(dbc: ParsedDbc, output: &str) -> std::io::Result<()> { Ok(()) } -fn write_ir(ir: DbcFile, output: &str) -> std::io::Result<()> { +fn write_ir(ir: &DbcFile, output: &str) -> std::io::Result<()> { let output_file = File::create(output)?; let mut writer = BufWriter::new(output_file); @@ -149,6 +149,7 @@ fn write_ir(ir: DbcFile, output: &str) -> std::io::Result<()> { Ok(()) } +#[must_use] pub fn parse_dbc_file(file_path: &str) -> ParsedDbc { let data = fs::read_to_string(file_path).expect("Unable to read input file"); ParsedDbc::try_from(data.as_str()).unwrap() diff --git a/src/middle_end/nodes/bitvec_postition_computer.rs b/src/middle_end/nodes/bitvec_postition_computer.rs index 5e3c7b3..566b771 100644 --- a/src/middle_end/nodes/bitvec_postition_computer.rs +++ b/src/middle_end/nodes/bitvec_postition_computer.rs @@ -2,7 +2,7 @@ use super::transformation::TransformationNode; use crate::ir::signal_layout::ByteOrder; /// Pre-compute bitvec slice positions for each signal layout. -/// Translates DBC start_bit (which varies by byte order) into +/// Translates DBC `start_bit` (which varies by byte order) into /// a unified [start..end] range suitable for bitvec indexing. pub struct ComputeBitvecPositions; @@ -11,16 +11,16 @@ impl TransformationNode for ComputeBitvecPositions { for layout in &mut file.signal_layouts { let (start, end) = match layout.byte_order { ByteOrder::LittleEndian => { - let start = layout.start_bit as usize; - let end = start + layout.size as usize; + let start = usize::try_from(layout.start_bit).unwrap(); + let end = start + usize::try_from(layout.size).unwrap(); (start, end) } ByteOrder::BigEndian => { let start_bit = layout.start_bit; let x = (start_bit / 8) * 8; let y = 7 - (start_bit % 8); - let start = (x + y) as usize; - let end = start + layout.size as usize; + let start = usize::try_from(x + y).unwrap(); + let end = start + usize::try_from(layout.size).unwrap(); (start, end) } }; diff --git a/src/middle_end/nodes/check.rs b/src/middle_end/nodes/check.rs index 59aa072..6278ab9 100644 --- a/src/middle_end/nodes/check.rs +++ b/src/middle_end/nodes/check.rs @@ -42,6 +42,7 @@ impl Diagnostics { }); } + #[must_use] pub fn has_errors(&self) -> bool { self.diagnostics .iter() diff --git a/src/middle_end/nodes/message_signal_usage_attacher.rs b/src/middle_end/nodes/message_signal_usage_attacher.rs index 1b8171c..fee3ab9 100644 --- a/src/middle_end/nodes/message_signal_usage_attacher.rs +++ b/src/middle_end/nodes/message_signal_usage_attacher.rs @@ -114,7 +114,7 @@ fn collect_unused_bits( msg_size_bytes: u64, spans: &[MessageSignalBitSpan], ) -> Vec { - let msg_bits = msg_size_bytes as usize * 8; + let msg_bits = usize::try_from(msg_size_bytes).unwrap() * 8; if msg_bits == 0 { return Vec::new(); @@ -124,9 +124,8 @@ fn collect_unused_bits( for span in spans { let end = span.end.min(msg_bits); - for bit in span.start.min(msg_bits)..end { - used[bit] = true; - } + let start = span.start.min(msg_bits); + used[start..end].fill(true); } collect_gaps(&used) diff --git a/src/middle_end/nodes/signal_name_sanitizer.rs b/src/middle_end/nodes/signal_name_sanitizer.rs index 2869b88..4e22bb9 100644 --- a/src/middle_end/nodes/signal_name_sanitizer.rs +++ b/src/middle_end/nodes/signal_name_sanitizer.rs @@ -17,7 +17,7 @@ impl TransformationNode for SanitizeSignalNames { let count = counts.entry(base.to_lowercase()).or_insert(0); let new_postfix = if *count == 0 { - "".into() + String::new() } else { format!("{}", count) }; diff --git a/src/middle_end/nodes/signal_range_checker.rs b/src/middle_end/nodes/signal_range_checker.rs index e5c488c..6324b8c 100644 --- a/src/middle_end/nodes/signal_range_checker.rs +++ b/src/middle_end/nodes/signal_range_checker.rs @@ -24,8 +24,7 @@ impl CheckNode for CheckSignalPhysicalRangeRepresentable { } //ignore floats and doubles - let Some((scaled_min, scaled_max)) = - scaled_raw_range(layout, sig.extended_type.clone()) + let Some((scaled_min, scaled_max)) = scaled_raw_range(layout, sig.extended_type) else { continue; }; @@ -88,7 +87,7 @@ fn pow2(bits: u64) -> Option { if bits > 1023 { None } else { - Some(2f64.powi(bits as i32)) + Some(2f64.powi(i32::try_from(bits).unwrap())) } } diff --git a/src/middle_end/nodes/signal_scaling_safety_checker.rs b/src/middle_end/nodes/signal_scaling_safety_checker.rs index 92e09f8..71541be 100644 --- a/src/middle_end/nodes/signal_scaling_safety_checker.rs +++ b/src/middle_end/nodes/signal_scaling_safety_checker.rs @@ -232,8 +232,7 @@ fn check_setter_path( fn integer_physical_repr(ty: PhysicalType) -> Option { match ty { - PhysicalType::Integer(repr) => Some(repr), - PhysicalType::Enum { repr, .. } => Some(repr), + PhysicalType::Integer(repr) | PhysicalType::Enum { repr, .. } => Some(repr), PhysicalType::Bool | PhysicalType::Float32 | PhysicalType::Float64 => None, } } @@ -263,16 +262,17 @@ fn actual_raw_domain(layout: &SignalLayout) -> (i128, i128) { fn int_repr_domain(repr: IntReprType) -> (i128, i128) { match repr { - IntReprType::U8 => (u8::MIN as i128, u8::MAX as i128), - IntReprType::U16 => (u16::MIN as i128, u16::MAX as i128), - IntReprType::U32 => (u32::MIN as i128, u32::MAX as i128), - IntReprType::U64 => (u64::MIN as i128, u64::MAX as i128), - IntReprType::I8 => (i8::MIN as i128, i8::MAX as i128), - IntReprType::I16 => (i16::MIN as i128, i16::MAX as i128), - IntReprType::I32 => (i32::MIN as i128, i32::MAX as i128), - IntReprType::I64 => (i64::MIN as i128, i64::MAX as i128), + IntReprType::U8 => (i128::from(u8::MIN), i128::from(u8::MAX)), + IntReprType::U16 => (i128::from(u16::MIN), i128::from(u16::MAX)), + IntReprType::U32 => (i128::from(u32::MIN), i128::from(u32::MAX)), + IntReprType::U64 => (i128::from(u64::MIN), i128::from(u64::MAX)), + IntReprType::I8 => (i128::from(i8::MIN), i128::from(i8::MAX)), + IntReprType::I16 => (i128::from(i16::MIN), i128::from(i16::MAX)), + IntReprType::I32 => (i128::from(i32::MIN), i128::from(i32::MAX)), + IntReprType::I64 => (i128::from(i64::MIN), i128::from(i64::MAX)), IntReprType::I128 => (i128::MIN, i128::MAX), - IntReprType::U128 => (u128::MIN as i128, u128::MAX as i128), + // TODO: This will always panic... U128::MAX is not representable right now + IntReprType::U128 => (i128::try_from(u128::MIN).unwrap(), i128::try_from(u128::MAX).unwrap()), } } diff --git a/src/middle_end/nodes/signal_type_inferer.rs b/src/middle_end/nodes/signal_type_inferer.rs index 65ab6d2..cc1013d 100644 --- a/src/middle_end/nodes/signal_type_inferer.rs +++ b/src/middle_end/nodes/signal_type_inferer.rs @@ -82,7 +82,7 @@ fn infer_physical_type( } fn enum_coverage(size: u64, variant_count: usize) -> EnumCoverage { - match 1u128.checked_shl(size as u32) { + match 1u128.checked_shl(u32::try_from(size).unwrap()) { Some(possible_values) if variant_count as u128 == possible_values => { EnumCoverage::Exhaustive } @@ -118,10 +118,10 @@ fn raw_integer_range(sig_layout: &SignalLayout) -> Option<(i128, i128)> { if matches!(sig_layout.value_type, ValueType::Signed) { let high_bit = size.checked_sub(1)?; - let magnitude = 1i128.checked_shl(high_bit as u32)?; + let magnitude = 1i128.checked_shl(u32::try_from(high_bit).unwrap())?; Some((magnitude.checked_neg()?, magnitude.checked_sub(1)?)) } else { - let values = 1i128.checked_shl(size as u32)?; + let values = 1i128.checked_shl(u32::try_from(size).unwrap())?; Some((0, values.checked_sub(1)?)) } } diff --git a/src/middle_end/nodes/sve_deduplicator.rs b/src/middle_end/nodes/sve_deduplicator.rs index 399cf57..e224132 100644 --- a/src/middle_end/nodes/sve_deduplicator.rs +++ b/src/middle_end/nodes/sve_deduplicator.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use super::transformation::TransformationNode; use crate::ir::signal_value_enum::SignalValueEnum; -/// Deduplicate SignalValueEnums. +/// Deduplicate `SignalValueEnums`. /// /// If enabled, performs the deduplication. /// Enums with same names and variants are treated as one. @@ -43,14 +43,13 @@ impl TransformationNode for DeduplicateSignalValueEnums { for (old_idx, sve) in file.signal_value_enums.iter().enumerate() { let sig = EnumSignature::from_enum(sve); - let new_idx = match map.get(&sig) { - Some(&idx) => idx, - None => { - let idx = new_enums.len(); - new_enums.push(sve.clone()); - map.insert(sig, idx); - idx - } + let new_idx = if let Some(&idx) = map.get(&sig) { + idx + } else { + let idx = new_enums.len(); + new_enums.push(sve.clone()); + map.insert(sig, idx); + idx }; remap[old_idx] = new_idx; diff --git a/src/middle_end/nodes/sve_name_prefixer.rs b/src/middle_end/nodes/sve_name_prefixer.rs index 5fd8d24..3f93687 100644 --- a/src/middle_end/nodes/sve_name_prefixer.rs +++ b/src/middle_end/nodes/sve_name_prefixer.rs @@ -1,6 +1,6 @@ use super::transformation::TransformationNode; -/// Prefix SignalValueEnum with Message name. +/// Prefix `SignalValueEnum` with Message name. /// /// Performs the task when enum deduplication is disabled. pub struct PrefixSignalValueEnumName { diff --git a/src/middle_end/nodes/sve_type_attacher.rs b/src/middle_end/nodes/sve_type_attacher.rs index 252b082..ee72d86 100644 --- a/src/middle_end/nodes/sve_type_attacher.rs +++ b/src/middle_end/nodes/sve_type_attacher.rs @@ -1,6 +1,6 @@ use super::transformation::TransformationNode; -/// Attach physical type to SignalValueEnum. +/// Attach physical type to `SignalValueEnum`. pub struct AttachSignalValueEnumType; impl TransformationNode for AttachSignalValueEnumType { diff --git a/src/middle_end/nodes/sve_variant_sanitizer.rs b/src/middle_end/nodes/sve_variant_sanitizer.rs index 20b12aa..dfc9c5a 100644 --- a/src/middle_end/nodes/sve_variant_sanitizer.rs +++ b/src/middle_end/nodes/sve_variant_sanitizer.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use super::transformation::TransformationNode; use crate::ir::identifier::is_valid_identifier; -/// Sanitize the names of SignalValueEnum variants. +/// Sanitize the names of `SignalValueEnum` variants. /// Remove the name of the signal and convert to upper camel case. /// If duplicates appear after sanitization, append the numeric value. pub struct SanitizeSignalEnumVariantNames; @@ -36,11 +36,10 @@ impl TransformationNode for SanitizeSignalEnumVariantNames { } for variant in &mut sve.variants { - if let Some(count) = counts.get(&variant.description) { - if *count > 1 { - variant.description = - format!("{}{}", variant.description, variant.value); - } + if let Some(count) = counts.get(&variant.description) + && *count > 1 + { + variant.description = format!("{}{}", variant.description, variant.value); } } } diff --git a/src/middle_end/pipeline/check_pipeline.rs b/src/middle_end/pipeline/check_pipeline.rs index 0923fd5..3b12d22 100644 --- a/src/middle_end/pipeline/check_pipeline.rs +++ b/src/middle_end/pipeline/check_pipeline.rs @@ -5,11 +5,13 @@ pub struct CheckPipeline { } impl CheckPipeline { + #[must_use] pub fn new() -> Self { Self { nodes: Vec::new() } } - pub fn add(mut self, node: N) -> Self + #[must_use] + pub fn add_node(mut self, node: N) -> Self where N: CheckNode + 'static, { @@ -24,6 +26,12 @@ impl CheckPipeline { } } +impl Default for CheckPipeline { + fn default() -> Self { + Self::new() + } +} + //TODO: checker node ideas // enum values fit raw range // mux value fits raw range diff --git a/src/middle_end/pipeline/transform_pipeline.rs b/src/middle_end/pipeline/transform_pipeline.rs index 0797d69..891edfb 100644 --- a/src/middle_end/pipeline/transform_pipeline.rs +++ b/src/middle_end/pipeline/transform_pipeline.rs @@ -5,11 +5,13 @@ pub struct TransformationPipeline { } impl TransformationPipeline { + #[must_use] pub fn new() -> Self { Self { nodes: Vec::new() } } - pub fn add(mut self, node: N) -> Self + #[must_use] + pub fn add_node(mut self, node: N) -> Self where N: TransformationNode + 'static, { @@ -23,3 +25,9 @@ impl TransformationPipeline { } } } + +impl Default for TransformationPipeline { + fn default() -> Self { + Self::new() + } +} diff --git a/src/utils.rs b/src/utils.rs index 42a35c4..d1e4c3b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,9 +1,10 @@ -#[derive(clap::ValueEnum, Clone, Debug)] +#[derive(clap::ValueEnum, Clone, Copy, Debug)] pub enum Language { Rust, Cpp, } impl Language { + #[must_use] pub fn file_extension(&self) -> &'static str { match self { Language::Rust => "rs",