From dd13cba66c9cbb679f19668e7496b4092e120472 Mon Sep 17 00:00:00 2001 From: jorgeandrecastro Date: Mon, 28 Sep 2026 14:49:34 +0200 Subject: [PATCH 1/7] CAN: returning Result instead of Option (#741) --- embedded-can/src/id.rs | 54 +++++++++++++++++++++++++---------------- embedded-can/src/lib.rs | 18 +++++++++++--- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/embedded-can/src/id.rs b/embedded-can/src/id.rs index b15fd32f..df37a1f9 100644 --- a/embedded-can/src/id.rs +++ b/embedded-can/src/id.rs @@ -1,5 +1,8 @@ //! CAN Identifiers. +// Import ErrorKind to return standard CAN validation errors from ID constructors +use crate::ErrorKind; + /// Standard 11-bit CAN Identifier (`0..=0x7FF`). #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -12,16 +15,16 @@ impl StandardId { /// CAN ID `0x7FF`, the lowest priority. pub const MAX: Self = Self(0x7FF); - /// Tries to create a `StandardId` from a raw 16-bit integer. + /// Tries to create a `StandardId` from a raw 16-bit integer. /// - /// This will return `None` if `raw` is out of range of an 11-bit integer (`> 0x7FF`). + /// This will return an error if `raw` is out of range of an 11-bit integer (`> 0x7FF`). #[inline] #[must_use] - pub const fn new(raw: u16) -> Option { + pub const fn new(raw: u16) -> Result { if raw <= 0x7FF { - Some(Self(raw)) + Ok(Self(raw)) } else { - None + Err(ErrorKind::InvalidId) } } @@ -55,19 +58,18 @@ impl ExtendedId { /// CAN ID `0x1FFFFFFF`, the lowest priority. pub const MAX: Self = Self(0x1FFF_FFFF); - /// Tries to create a `ExtendedId` from a raw 32-bit integer. + /// Tries to create an `ExtendedId` from a raw 32-bit integer. /// - /// This will return `None` if `raw` is out of range of an 29-bit integer (`> 0x1FFF_FFFF`). + /// This will return an error if `raw` is out of range of a 29-bit integer (`> 0x1FFF_FFFF`). #[inline] #[must_use] - pub const fn new(raw: u32) -> Option { + pub const fn new(raw: u32) -> Result { if raw <= 0x1FFF_FFFF { - Some(Self(raw)) + Ok(Self(raw)) } else { - None + Err(ErrorKind::InvalidId) } } - /// Creates a new `ExtendedId` without checking if it is inside the valid range. /// /// # Safety @@ -178,36 +180,45 @@ impl From for Id { mod tests { use super::*; - #[test] + #[test] fn standard_id_new() { + // Test that a valid standard ID is successfully created assert_eq!( StandardId::new(StandardId::MAX.as_raw()), - Some(StandardId::MAX) + Ok(StandardId::MAX) ); } - #[test] + #[test] fn standard_id_new_out_of_range() { - assert_eq!(StandardId::new(StandardId::MAX.as_raw() + 1), None); + // Test that creating a standard ID out of bounds returns an InvalidId error + assert_eq!( + StandardId::new(StandardId::MAX.as_raw() + 1), + Err(ErrorKind::InvalidId) + ); } - #[test] fn standard_id_new_unchecked_out_of_range() { let id = StandardId::MAX.as_raw() + 1; assert_eq!(unsafe { StandardId::new_unchecked(id) }, StandardId(id)); } - #[test] + #[test] fn extended_id_new() { + // Test that a valid extended ID is successfully created assert_eq!( ExtendedId::new(ExtendedId::MAX.as_raw()), - Some(ExtendedId::MAX) + Ok(ExtendedId::MAX) ); } #[test] fn extended_id_new_out_of_range() { - assert_eq!(ExtendedId::new(ExtendedId::MAX.as_raw() + 1), None); + // Test that creating an extended ID out of bounds returns an InvalidId error + assert_eq!( + ExtendedId::new(ExtendedId::MAX.as_raw() + 1), + Err(ErrorKind::InvalidId) + ); } #[test] @@ -218,9 +229,10 @@ mod tests { #[test] fn get_standard_id_from_extended_id() { + // Test extracting standard ID from extended ID using Result unwrap assert_eq!( - Some(ExtendedId::MAX.standard_id()), - StandardId::new((ExtendedId::MAX.0 >> 18) as u16) + ExtendedId::MAX.standard_id(), + StandardId::new((ExtendedId::MAX.0 >> 18) as u16).unwrap() ); } diff --git a/embedded-can/src/lib.rs b/embedded-can/src/lib.rs index 86248f3c..733a9619 100644 --- a/embedded-can/src/lib.rs +++ b/embedded-can/src/lib.rs @@ -14,13 +14,13 @@ pub use id::*; pub trait Frame: Sized { /// Creates a new frame. /// - /// This will return `None` if the data slice is too long. - fn new(id: impl Into, data: &[u8]) -> Option; + /// This will return an error if the data slice is too long. + fn new(id: impl Into, data: &[u8]) -> Result; /// Creates a new remote frame (RTR bit set). /// - /// This will return `None` if the data length code (DLC) is not valid. - fn new_remote(id: impl Into, dlc: usize) -> Option; + /// This will return an error if the data length code (DLC) is not valid. + fn new_remote(id: impl Into, dlc: usize) -> Result; /// Returns true if this frame is an extended frame. fn is_extended(&self) -> bool; @@ -102,6 +102,12 @@ pub enum ErrorKind { /// A different error occurred. The original error may contain more information. Other, + + /// The provided identifier is invalid or out of range. + InvalidId, + + /// The data slice or DLC is too long or invalid. + DataTooLong, } impl Error for ErrorKind { @@ -115,6 +121,10 @@ impl core::error::Error for ErrorKind {} impl core::fmt::Display for ErrorKind { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { + // The provided identifier is invalid or out of range + Self::InvalidId => write!(f, "The provided identifier is invalid or out of range"), + // The data slice or DLC is too long or invalid + Self::DataTooLong => write!(f, "The data slice or DLC is too long or invalid"), Self::Overrun => write!(f, "The peripheral receive buffer was overrun"), Self::Bit => write!( f, From 29d3cf1d32fa45242f66e9c7e953b12209a6d96b Mon Sep 17 00:00:00 2001 From: jorgeandrecastro Date: Mon, 28 Sep 2026 15:02:07 +0200 Subject: [PATCH 2/7] style: fix code formatting --- embedded-can/src/id.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/embedded-can/src/id.rs b/embedded-can/src/id.rs index df37a1f9..3773c380 100644 --- a/embedded-can/src/id.rs +++ b/embedded-can/src/id.rs @@ -15,7 +15,7 @@ impl StandardId { /// CAN ID `0x7FF`, the lowest priority. pub const MAX: Self = Self(0x7FF); - /// Tries to create a `StandardId` from a raw 16-bit integer. + /// Tries to create a `StandardId` from a raw 16-bit integer. /// /// This will return an error if `raw` is out of range of an 11-bit integer (`> 0x7FF`). #[inline] @@ -58,7 +58,7 @@ impl ExtendedId { /// CAN ID `0x1FFFFFFF`, the lowest priority. pub const MAX: Self = Self(0x1FFF_FFFF); - /// Tries to create an `ExtendedId` from a raw 32-bit integer. + /// Tries to create an `ExtendedId` from a raw 32-bit integer. /// /// This will return an error if `raw` is out of range of a 29-bit integer (`> 0x1FFF_FFFF`). #[inline] @@ -180,7 +180,7 @@ impl From for Id { mod tests { use super::*; - #[test] + #[test] fn standard_id_new() { // Test that a valid standard ID is successfully created assert_eq!( @@ -189,7 +189,7 @@ mod tests { ); } - #[test] + #[test] fn standard_id_new_out_of_range() { // Test that creating a standard ID out of bounds returns an InvalidId error assert_eq!( @@ -203,7 +203,7 @@ mod tests { assert_eq!(unsafe { StandardId::new_unchecked(id) }, StandardId(id)); } - #[test] + #[test] fn extended_id_new() { // Test that a valid extended ID is successfully created assert_eq!( From dd64bdf0f9980081aad377d0d495bc8f5e760131 Mon Sep 17 00:00:00 2001 From: jorgeandrecastro Date: Mon, 28 Sep 2026 15:07:12 +0200 Subject: [PATCH 3/7] fix: resolve clippy warnings --- embedded-can/src/id.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embedded-can/src/id.rs b/embedded-can/src/id.rs index 3773c380..64102a94 100644 --- a/embedded-can/src/id.rs +++ b/embedded-can/src/id.rs @@ -19,7 +19,6 @@ impl StandardId { /// /// This will return an error if `raw` is out of range of an 11-bit integer (`> 0x7FF`). #[inline] - #[must_use] pub const fn new(raw: u16) -> Result { if raw <= 0x7FF { Ok(Self(raw)) @@ -62,7 +61,6 @@ impl ExtendedId { /// /// This will return an error if `raw` is out of range of a 29-bit integer (`> 0x1FFF_FFFF`). #[inline] - #[must_use] pub const fn new(raw: u32) -> Result { if raw <= 0x1FFF_FFFF { Ok(Self(raw)) From 8d33dac860d7899140c10662545506b36e71e315 Mon Sep 17 00:00:00 2001 From: jorgeandrecastro Date: Mon, 28 Sep 2026 15:14:27 +0200 Subject: [PATCH 4/7] ci: trigger workflow re-run From d477fa44e6291aed628283680c7d15075bb74a2f Mon Sep 17 00:00:00 2001 From: jorgeandrecastro Date: Tue, 29 Sep 2026 13:35:54 +0200 Subject: [PATCH 5/7] ci: bump MSRV to 1.85 for embedded-can --- embedded-can/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embedded-can/Cargo.toml b/embedded-can/Cargo.toml index cd07bcde..a37aab75 100644 --- a/embedded-can/Cargo.toml +++ b/embedded-can/Cargo.toml @@ -2,7 +2,7 @@ name = "embedded-can" version = "0.4.1" edition = "2021" -rust-version = "1.83" +rust-version = "1.85" description = "HAL traits for Controller Area Network (CAN) devices." categories = ["embedded", "hardware-support", "no-std"] From da7fdeb304cf2293c8a5dca2b9f234a630379bc7 Mon Sep 17 00:00:00 2001 From: jorgeandrecastro Date: Tue, 29 Sep 2026 13:43:03 +0200 Subject: [PATCH 6/7] ci: bump MSRV to 1.85 for workspace crates requiring it --- embedded-hal-bus/Cargo.toml | 2 +- embedded-hal-nb/Cargo.toml | 2 +- embedded-hal/Cargo.toml | 2 +- embedded-io-adapters/Cargo.toml | 2 +- embedded-io-async/Cargo.toml | 2 +- embedded-io/Cargo.toml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/embedded-hal-bus/Cargo.toml b/embedded-hal-bus/Cargo.toml index e4996982..240b3d03 100644 --- a/embedded-hal-bus/Cargo.toml +++ b/embedded-hal-bus/Cargo.toml @@ -6,7 +6,7 @@ categories = ["embedded", "hardware-support", "no-std"] description = "Bus/Device connection mechanisms for embedded-hal, a Hardware Abstraction Layer (HAL) for embedded systems" documentation = "https://docs.rs/embedded-hal-bus" edition = "2021" -rust-version = "1.83" +rust-version = "1.85" keywords = ["hal", "IO"] license = "MIT OR Apache-2.0" name = "embedded-hal-bus" diff --git a/embedded-hal-nb/Cargo.toml b/embedded-hal-nb/Cargo.toml index 9f6d7dae..44b5cc4e 100644 --- a/embedded-hal-nb/Cargo.toml +++ b/embedded-hal-nb/Cargo.toml @@ -2,7 +2,7 @@ name = "embedded-hal-nb" version = "1.0.0" edition = "2021" -rust-version = "1.83" +rust-version = "1.85" categories = ["embedded", "hardware-support", "no-std"] description = "Non-blocking Hardware Abstraction Layer (HAL) for embedded systems using the `nb` crate." diff --git a/embedded-hal/Cargo.toml b/embedded-hal/Cargo.toml index faadf4b6..3e03bb6e 100644 --- a/embedded-hal/Cargo.toml +++ b/embedded-hal/Cargo.toml @@ -8,7 +8,7 @@ categories = ["asynchronous", "embedded", "hardware-support", "no-std"] description = " A Hardware Abstraction Layer (HAL) for embedded systems " documentation = "https://docs.rs/embedded-hal" edition = "2021" -rust-version = "1.83" +rust-version = "1.85" keywords = ["hal", "IO"] license = "MIT OR Apache-2.0" name = "embedded-hal" diff --git a/embedded-io-adapters/Cargo.toml b/embedded-io-adapters/Cargo.toml index ede48d7c..d9ae3188 100644 --- a/embedded-io-adapters/Cargo.toml +++ b/embedded-io-adapters/Cargo.toml @@ -2,7 +2,7 @@ name = "embedded-io-adapters" version = "0.7.0" edition = "2021" -rust-version = "1.83" +rust-version = "1.85" description = "Adapters between the `embedded-io` traits and other I/O traits" repository = "https://github.com/rust-embedded/embedded-hal" readme = "README.md" diff --git a/embedded-io-async/Cargo.toml b/embedded-io-async/Cargo.toml index fa1d594c..76948e39 100644 --- a/embedded-io-async/Cargo.toml +++ b/embedded-io-async/Cargo.toml @@ -2,7 +2,7 @@ name = "embedded-io-async" version = "0.7.0" edition = "2021" -rust-version = "1.83" +rust-version = "1.85" description = "Async embedded IO traits" repository = "https://github.com/rust-embedded/embedded-hal" readme = "README.md" diff --git a/embedded-io/Cargo.toml b/embedded-io/Cargo.toml index 6eaf54b5..e3167b9e 100644 --- a/embedded-io/Cargo.toml +++ b/embedded-io/Cargo.toml @@ -2,7 +2,7 @@ name = "embedded-io" version = "0.7.1" edition = "2021" -rust-version = "1.83" +rust-version = "1.85" description = "Embedded IO traits" repository = "https://github.com/rust-embedded/embedded-hal" readme = "README.md" From 57b0f43ccbcea294f384ee0b6afec47c5c351b32 Mon Sep 17 00:00:00 2001 From: jorgeandrecastro Date: Tue, 29 Sep 2026 13:48:01 +0200 Subject: [PATCH 7/7] ci: update MSRV workflow to use Rust 1.85 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 754e1713..4c95825b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,5 +42,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@1.83 + - uses: dtolnay/rust-toolchain@1.85 - run: cargo test --workspace --all-features