diff --git a/Cargo.toml b/Cargo.toml index 0d68131..5772773 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,13 @@ categories = ["embedded", "no-std", "encoding", "parsing"] edition = "2021" rust-version = "1.74" +[[example]] +name = "file_parser" +path = "examples/file_parser.rs" +required-features = ["encodings"] + [features] -default = ["with-serde", "encodings"] +default = ["serde", "encodings"] # Support decoding from all standard encodings, e.g. cp1251 commonly used for dbc encodings = ["dep:encoding_rs"] serde = ["dep:serde"] diff --git a/justfile b/justfile index 1344137..5a06745 100755 --- a/justfile +++ b/justfile @@ -35,6 +35,7 @@ build-diagram: # Quick compile without building a binary check: cargo check {{packages}} {{features}} {{targets}} + cargo check {{packages}} --no-default-features {{targets}} # Generate code coverage report to upload to codecov.io ci-coverage: env-info && \ @@ -43,7 +44,7 @@ ci-coverage: env-info && \ mkdir -p target/llvm-cov # Run all tests as expected by CI -ci-test: env-info test-fmt clippy test test-doc deny && assert-git-is-clean +ci-test: env-info test-fmt check clippy test test-doc deny && assert-git-is-clean # Run minimal subset of tests to ensure compatibility with MSRV ci-test-msrv: env-info check test diff --git a/src/lib.rs b/src/lib.rs index 9d68479..6741780 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,8 @@ #![doc = include_str!("../README.md")] -use std::borrow::Cow; use std::convert::TryFrom; use derive_getters::Getters; -use serde::{Deserialize, Serialize}; pub mod parser; @@ -17,7 +15,7 @@ pub use encoding_rs as encodings; /// A helper function to decode cp1252 bytes, as DBC files are often encoded in cp1252. #[cfg(feature = "encodings")] -pub fn decode_cp1252(bytes: &[u8]) -> Option> { +pub fn decode_cp1252(bytes: &[u8]) -> Option> { let (cow, _, had_errors) = encodings::WINDOWS_1252.decode(bytes); if had_errors { None @@ -40,13 +38,15 @@ pub enum Error<'a> { } /// Baudrate of network in kbit/s -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Baudrate(u64); /// One or multiple signals are the payload of a CAN frame. /// To determine the actual value of a signal the following fn applies: /// `let fnvalue = |can_signal_value| -> can_signal_value * factor + offset;` -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Signal { name: String, multiplexer_indicator: MultiplexIndicator, @@ -59,13 +59,14 @@ pub struct Signal { pub min: f64, pub max: f64, unit: String, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] receivers: Vec, } /// CAN id in header of CAN frame. /// Must be unique in DBC file. -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum MessageId { Standard(u16), /// 29 bit extended identifier without the extended bit. @@ -83,7 +84,8 @@ impl MessageId { } } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Transmitter { /// node transmitting the message NodeName(String), @@ -91,21 +93,25 @@ pub enum Transmitter { VectorXXX, } -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct MessageTransmitter { message_id: MessageId, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] transmitter: Vec, } /// Version generated by DB editor -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Version(pub String); -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Symbol(pub String); -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum MultiplexIndicator { /// Multiplexor switch Multiplexor, @@ -117,26 +123,30 @@ pub enum MultiplexIndicator { Plain, } -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ByteOrder { LittleEndian, BigEndian, } -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ValueType { Signed, Unsigned, } -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum EnvType { Float, U64, Data, } -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SignalType { name: String, signal_size: u64, @@ -151,7 +161,8 @@ pub struct SignalType { value_table: String, } -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum AccessType { DummyNodeVector0, DummyNodeVector1, @@ -159,20 +170,23 @@ pub enum AccessType { DummyNodeVector3, } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum AccessNode { VectorXXX, Name(String), } // FIXME: not used! -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum SignalAttributeValue { Text(String), Int(i64), } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum AttributeValuedForObjectType { Raw(AttributeValue), NetworkNode(String, AttributeValue), @@ -182,7 +196,8 @@ pub enum AttributeValuedForObjectType { } // FIXME: not used! -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum AttributeValueType { Int(i64, i64), Hex(i64, i64), @@ -191,20 +206,23 @@ pub enum AttributeValueType { Enum(Vec), } -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ValDescription { pub id: f64, pub description: String, } // FIXME: not used! -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AttrDefault { name: String, value: AttributeValue, } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum AttributeValue { U64(u64), I64(i64), @@ -213,31 +231,35 @@ pub enum AttributeValue { } /// Global value table -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ValueTable { name: String, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] descriptions: Vec, } -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ExtendedMultiplexMapping { min_value: u64, max_value: u64, } /// Mapping between multiplexors and multiplexed signals -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ExtendedMultiplex { message_id: MessageId, signal_name: String, multiplexor_signal_name: String, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] mappings: Vec, } /// Object comments -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Comment { Node { name: String, @@ -262,7 +284,8 @@ pub enum Comment { } /// CAN message (frame) details including signal details -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Message { /// CAN id in header of CAN frame. /// Must be unique in DBC file. @@ -270,11 +293,12 @@ pub struct Message { name: String, size: u64, transmitter: Transmitter, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] signals: Vec, } -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct EnvironmentVariable { name: String, typ: EnvType, @@ -284,33 +308,38 @@ pub struct EnvironmentVariable { initial_value: f64, ev_id: i64, access_type: AccessType, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] access_nodes: Vec, } -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct EnvironmentVariableData { env_var_name: String, data_size: u64, } /// CAN network nodes, names must be unique -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Node(pub String); -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AttributeDefault { name: String, value: AttributeValue, } -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AttributeValueForObject { name: String, value: AttributeValuedForObjectType, } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum AttributeDefinition { // TODO add properties Message(String), @@ -324,22 +353,24 @@ pub enum AttributeDefinition { } /// Encoding for signal raw values. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ValueDescription { Signal { message_id: MessageId, name: String, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] value_descriptions: Vec, }, EnvironmentVariable { name: String, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] value_descriptions: Vec, }, } -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SignalTypeRef { message_id: MessageId, signal_name: String, @@ -347,67 +378,71 @@ pub struct SignalTypeRef { } /// Signal groups define a group of signals within a message -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SignalGroups { message_id: MessageId, name: String, repetitions: u64, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] signal_names: Vec, } -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum SignalExtendedValueType { SignedOrUnsignedInteger, IEEEfloat32Bit, IEEEdouble64bit, } -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SignalExtendedValueTypeList { message_id: MessageId, signal_name: String, signal_extended_value_type: SignalExtendedValueType, } -#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Dbc { /// Version generated by DB editor version: Version, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] new_symbols: Vec, /// Baud rate of network bit_timing: Option>, /// CAN network nodes - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] nodes: Vec, /// Global value table - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] value_tables: Vec, /// CAN message (frame) details including signal details - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] messages: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] message_transmitters: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] environment_variables: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] environment_variable_data: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] signal_types: Vec, /// Object comments - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] comments: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] attribute_definitions: Vec, // undefined // sigtype_attr_list: SigtypeAttrList, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] attribute_defaults: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] attribute_values: Vec, /// Encoding for signal raw values - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] value_descriptions: Vec, // obsolete + undefined // category_definitions: Vec, @@ -415,15 +450,15 @@ pub struct Dbc { //categories: Vec, // obsolete + undefined //filter: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] signal_type_refs: Vec, /// Signal groups define a group of signals within a message - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] signal_groups: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] signal_extended_value_type_list: Vec, /// Extended multiplex attributes - #[serde(skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))] extended_multiplex: Vec, } diff --git a/tests/test-snapshots.rs b/tests/test-snapshots.rs index d7bf1b8..920d2b3 100644 --- a/tests/test-snapshots.rs +++ b/tests/test-snapshots.rs @@ -1,4 +1,4 @@ -#![cfg(feature = "with-serde")] +#![cfg(feature = "serde")] use std::fs; use std::path::Path;