Skip to content

Commit f4ae6c7

Browse files
authored
Add optional serde feature (#12)
1 parent 90bdc5c commit f4ae6c7

26 files changed

+61
-2
lines changed

Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ edition = "2021"
88
license = "MIT OR Apache-2.0"
99
keywords = ["uds", "kwp2000", "obd", "automotive", "no_std"]
1010
categories = ["embedded", "no-std", "encoding", "parsing"]
11-
rust-version = "1.61.0"
11+
rust-version = "1.63.0"
1212

1313
[features]
1414
default = ["std", "iter", "display", "with-kwp2000", "with-obd2", "with-uds"]
@@ -24,13 +24,17 @@ with-kwp2000 = []
2424
with-obd2 = []
2525
# Include support for Unified Diagnostic Services
2626
with-uds = []
27+
# Include support for serde serialization
28+
serde = ["dep:serde"]
2729

2830
[dependencies]
2931
displaydoc = { version = "0.2", optional = true }
32+
serde = { version = "1", features = ["derive"], optional = true }
3033
strum = { version = "0.26.3", features = ["derive"] }
3134

3235
[dev-dependencies]
3336
cargo-husky = { version = "1", features = ["user-hooks"], default-features = false }
37+
serde_json = { version = "1", features = ["preserve_order"] }
3438

3539
[lints.rust]
3640
unsafe_code = "forbid"

justfile

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ test:
3737
RUSTFLAGS='-D warnings' cargo test --no-default-features --features with-kwp2000
3838
RUSTFLAGS='-D warnings' cargo test --no-default-features --features with-obd2
3939
RUSTFLAGS='-D warnings' cargo test --no-default-features --features with-uds
40+
RUSTFLAGS='-D warnings' cargo test --features serde
4041

4142
# Test documentation
4243
test-doc:

src/kwp2000/commands.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ crate::utils::enum_wrapper!(kwp2000, KwpCommand, KwpCommandByte);
77
#[repr(u8)]
88
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
99
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
10+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1011
pub enum KwpCommand {
1112
/// Start or change ECU diagnostic session mode.
1213
StartDiagnosticSession = 0x10,

src/kwp2000/errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ crate::utils::enum_wrapper!(kwp2000, KwpError, KwpErrorByte);
44
#[repr(u8)]
55
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
7+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
78
pub enum KwpError {
89
/// ECU rejected the request for unknown reason
910
GeneralReject = 0x10,

src/kwp2000/reset_types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ crate::utils::enum_wrapper!(kwp2000, ResetType, ResetTypeByte);
1414
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
1515
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
1616
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
17+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1718
pub enum ResetType {
1819
/// Simulates a power off/on reset of the ECU.
1920
PowerOnReset = 0x01,

src/kwp2000/routine_exit_status.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ crate::utils::enum_wrapper!(kwp2000, RoutineExitStatus, RoutineExitStatusByte);
33
#[repr(u8)]
44
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
55
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
6+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
67
pub enum RoutineExitStatus {
78
/// Normal exit with results available
89
NormalExitWithResults = 0x61,

src/kwp2000/session_types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ crate::utils::enum_wrapper!(kwp2000, KwpSessionType, KwpSessionTypeByte);
1414
#[repr(u8)]
1515
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
1616
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
17+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1718
pub enum KwpSessionType {
1819
/// Normal session. The ECU will typically boot in this state.
1920
/// In this mode, only non-intrusive functions are supported.

src/obd2/command_2nd_air_status.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ crate::utils::enum_wrapper!(
99
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
1010
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
1111
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
12+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1213
pub enum CommandedSecondaryAirStatus {
1314
/// Upstream
1415
Upstream = 0x01,

src/obd2/commands.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ crate::utils::enum_wrapper!(obd2, Obd2Command, Obd2CommandByte);
55
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
77
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
8+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89
pub enum Obd2Command {
910
/// Service 01 - Show current data
1011
Service01 = 0x01,

src/obd2/data_pids.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ crate::utils::enum_wrapper!(obd2, DataPid, DataPidByte);
44
#[repr(u8)]
55
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
7+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
78
pub enum DataPid {
89
PidSupport0120 = 0x00,
910
StatusSinceDTCCleared = 0x01,

src/obd2/errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ crate::utils::enum_wrapper!(obd2, Obd2Error, Obd2ErrorByte);
55
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
77
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
8+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89
pub enum Obd2Error {
910
/// ECU general reject
1011
GeneralReject = 0x10,

src/obd2/fuel_system_status.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ crate::utils::enum_wrapper!(obd2, FuelSystemStatus, FuelSystemStatusByte);
55
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
77
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
8+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89
pub enum FuelSystemStatus {
910
/// The motor is off
1011
Off = 0x00,

src/obd2/fuel_types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ crate::utils::enum_wrapper!(obd2, FuelTypeCoding, FuelTypeCodingByte);
66
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
77
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
88
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
9+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
910
pub enum FuelTypeCoding {
1011
/// Fuel type unavailable
1112
NotAvailable = 0,

src/obd2/obd_standard.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ crate::utils::enum_wrapper!(obd2, ObdStandard, ObdStandardByte);
66
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
77
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
88
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
9+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
910
#[allow(clippy::doc_markdown)]
1011
pub enum ObdStandard {
1112
/// OBD-II as defined by the CARB

src/obd2/service09.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ crate::utils::enum_wrapper!(obd2, Service09Pid, Service09PidByte);
55
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
77
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
8+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89
pub enum Service09Pid {
910
/// VIN message count (Only for LIN)
1011
VinMsgCount = 0x01,

src/uds/comm_level.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ crate::utils::enum_wrapper!(uds, CommunicationLevel, CommunicationLevelByte);
44
#[repr(u8)]
55
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
7+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
78
pub enum CommunicationLevel {
89
/// This value indicates that the reception and transmission of messages
910
/// shall be enabled for the specified communicationType.

src/uds/commands.rs

+31
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ crate::utils::enum_wrapper!(uds, UdsCommand, UdsCommandByte);
55
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
77
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
8+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89
pub enum UdsCommand {
910
/// The client requests to control a diagnostic session with a server(s).
1011
DiagnosticSessionControl = 0x10,
@@ -59,3 +60,33 @@ pub enum UdsCommand {
5960
/// The client requests the negotiation of a file transfer between server and client.
6061
RequestFileTransfer = 0x38,
6162
}
63+
64+
#[cfg(all(test, feature = "serde"))]
65+
mod tests {
66+
use super::*;
67+
68+
#[derive(serde::Serialize, serde::Deserialize)]
69+
struct TestStruct {
70+
command: UdsCommand,
71+
command_byte: UdsCommandByte,
72+
}
73+
74+
#[test]
75+
fn test_serde() {
76+
let test = TestStruct {
77+
command: UdsCommand::DiagnosticSessionControl,
78+
command_byte: UdsCommandByte::from(UdsCommand::DiagnosticSessionControl),
79+
};
80+
81+
let json = serde_json::to_string(&test).unwrap();
82+
assert_eq!(
83+
json,
84+
r###"{"command":"DiagnosticSessionControl","command_byte":{"Standard":"DiagnosticSessionControl"}}"###
85+
);
86+
87+
let deserialized: TestStruct = serde_json::from_str(&json).unwrap();
88+
89+
assert_eq!(test.command, deserialized.command);
90+
assert_eq!(test.command_byte, deserialized.command_byte);
91+
}
92+
}

src/uds/errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ enum_wrapper!(uds, UdsError, UdsErrorByte);
88
#[repr(u8)]
99
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
1010
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
11+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1112
pub enum UdsError {
1213
/// ECU rejected the request (No specific error)
1314
GeneralReject = 0x10,

src/uds/read_dtc_information.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ enum_wrapper!(uds, DtcSubFunction, DtcSubFunctionByte);
99
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
1010
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
1111
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
12+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1213
#[allow(clippy::doc_markdown)]
1314
pub enum DtcSubFunction {
1415
/// This function takes a 1 byte DTCStatusMask

src/uds/reset_types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ crate::utils::enum_wrapper!(uds, ResetType, ResetTypeByte);
44
#[repr(u8)]
55
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
7+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
78
pub enum ResetType {
89
/// Signals the ECU to perform a hard-reset,
910
/// simulating a forceful power off/on cycle

src/uds/routine.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ crate::utils::enum_wrapper!(uds, RoutineControlType, RoutineControlTypeByte);
55
#[repr(u8)]
66
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
77
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
8+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89
pub enum RoutineControlType {
910
/// Launches a routine on the ECU
1011
StartRoutine = 0x01,

src/uds/scaling_byte.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ crate::utils::enum_impls!(uds, ScalingType);
66
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
77
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
88
#[cfg_attr(feature = "display", derive(displaydoc::Display))]
9+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
910
pub enum ScalingType {
1011
/// Unsigned numeric integer. Must be followed by 1..4 bytes, given as a low nibble of the byte.
1112
UnsignedNumeric = 0x00,

src/uds/scaling_byte_ext.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ generate_enum! {
6363
/// or [`ScalingExtension::get_prefix`] to return the optional prefix of the scaling byte.
6464
#[repr(u8)]
6565
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66-
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
66+
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
67+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6768
pub enum ScalingExtension {
6869
/// No unit or presentation
6970
NoUnit = 0x00,

src/uds/security_access.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ crate::utils::enum_wrapper!(uds, SecurityOperation, SecurityOperationByte);
99
#[repr(u8)]
1010
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
1111
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
12+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1213
pub enum SecurityOperation {
1314
/// Asks the ECU for a security seed
1415
RequestSeed = 0x01,

src/uds/session_types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ crate::utils::enum_wrapper!(uds, UdsSessionType, UdsSessionTypeByte);
44
#[repr(u8)]
55
#[derive(strum::FromRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
66
#[cfg_attr(feature = "iter", derive(strum::EnumIter))]
7+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
78
pub enum UdsSessionType {
89
/// Default diagnostic session mode (ECU is normally in this mode on startup)
910
/// This session type does not require the diagnostic server to sent `TesterPresent` messages

src/utils.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use core::fmt::Debug;
33
/// A wrapper around a byte, which can be either an ISO-standardized value for a specific enum,
44
/// or an implementation-specific/invalid `Extended` value wrapping original byte.
55
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
6+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
67
pub enum ByteWrapper<T> {
78
Standard(T),
89
Extended(u8),

0 commit comments

Comments
 (0)