From 6b39610845dca5452072e253b7bc5f882771dbae Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 7 Nov 2026 17:50:01 +0100 Subject: [PATCH 1/2] simplify cortex-m-types error handling --- cortex-m-types/CHANGELOG.md | 3 ++ cortex-m-types/Cargo.toml | 6 +++ cortex-m-types/src/lib.rs | 93 ++++++++++++++++++++++++++---------- cortex-m-types/src/result.rs | 61 ----------------------- 4 files changed, 77 insertions(+), 86 deletions(-) delete mode 100644 cortex-m-types/src/result.rs diff --git a/cortex-m-types/CHANGELOG.md b/cortex-m-types/CHANGELOG.md index 1663330b..01e4f761 100644 --- a/cortex-m-types/CHANGELOG.md +++ b/cortex-m-types/CHANGELOG.md @@ -9,3 +9,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - MSRV bumped to 1.85 - Updated references from 'Cortex-M Team' to 'Arm Team' +- Breaking: Replaced the `result` module and its `Error` enum with a dedicated error type per + trait. `from_number` now returns `InvalidExceptionNumberError`, `InvalidInterruptNumberError`, + `InvalidPriorityNumberError` or `InvalidCoreIdNumberError`. diff --git a/cortex-m-types/Cargo.toml b/cortex-m-types/Cargo.toml index e415efab..32e161c3 100644 --- a/cortex-m-types/Cargo.toml +++ b/cortex-m-types/Cargo.toml @@ -11,6 +11,12 @@ license = "MIT OR Apache-2.0" readme = "README.md" rust-version = "1.85" +[features] +defmt = ["dep:defmt"] + +[dependencies] +defmt = { version = "1", optional = true } + [package.metadata.docs.rs] targets = [ "thumbv8m.main-none-eabihf", diff --git a/cortex-m-types/src/lib.rs b/cortex-m-types/src/lib.rs index ea175ce5..1887213d 100644 --- a/cortex-m-types/src/lib.rs +++ b/cortex-m-types/src/lib.rs @@ -1,9 +1,5 @@ #![no_std] -pub mod result; - -use result::Result; - /// Trait for enums of target-specific exception numbers. /// /// This trait should be implemented by a peripheral access crate (PAC) on its enum of available @@ -26,9 +22,21 @@ pub unsafe trait ExceptionNumber: Copy { fn number(self) -> usize; /// Tries to convert a number to a valid exception. - fn from_number(value: usize) -> Result; + fn from_number(value: usize) -> Result; +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct InvalidExceptionNumberError; + +impl core::fmt::Display for InvalidExceptionNumberError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "invalid exception number") + } } +impl core::error::Error for InvalidExceptionNumberError {} + /// Trait for enums of target-specific interrupt numbers. /// /// This trait should be implemented by a peripheral access crate (PAC) on its enum of available @@ -50,9 +58,21 @@ pub unsafe trait InterruptNumber: Copy { fn number(self) -> usize; /// Tries to convert a number to a valid interrupt. - fn from_number(value: usize) -> Result; + fn from_number(value: usize) -> Result; +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct InvalidInterruptNumberError; + +impl core::fmt::Display for InvalidInterruptNumberError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "invalid interrupt number") + } } +impl core::error::Error for InvalidInterruptNumberError {} + /// Trait for enums of priority levels. /// /// This trait should be implemented by a peripheral access crate (PAC) on its enum of available @@ -74,9 +94,21 @@ pub unsafe trait PriorityNumber: Copy { fn number(self) -> usize; /// Tries to convert a number to a valid priority level. - fn from_number(value: usize) -> Result; + fn from_number(value: usize) -> Result; +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct InvalidPriorityNumberError; + +impl core::fmt::Display for InvalidPriorityNumberError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "invalid priority number") + } } +impl core::error::Error for InvalidPriorityNumberError {} + /// Trait for enums of core identifiers. /// /// This trait should be implemented by a peripheral access crate (PAC) on its enum of available @@ -98,13 +130,24 @@ pub unsafe trait CoreIdNumber: Copy { fn number(self) -> usize; /// Tries to convert a number to a valid Core ID. - fn from_number(value: usize) -> Result; + fn from_number(value: usize) -> Result; } +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct InvalidCoreIdNumberError; + +impl core::fmt::Display for InvalidCoreIdNumberError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "invalid core ID number") + } +} + +impl core::error::Error for InvalidCoreIdNumberError {} + #[cfg(test)] mod test { use super::*; - use crate::result::Error; #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum Exception { @@ -143,11 +186,11 @@ mod test { } #[inline] - fn from_number(number: usize) -> Result { + fn from_number(number: usize) -> Result { match number { 1 => Ok(Exception::E1), 3 => Ok(Exception::E3), - _ => Err(Error::InvalidVariant(number)), + _ => Err(InvalidExceptionNumberError), } } } @@ -161,12 +204,12 @@ mod test { } #[inline] - fn from_number(number: usize) -> Result { + fn from_number(number: usize) -> Result { match number { 1 => Ok(Interrupt::I1), 2 => Ok(Interrupt::I2), 4 => Ok(Interrupt::I4), - _ => Err(Error::InvalidVariant(number)), + _ => Err(InvalidInterruptNumberError), } } } @@ -180,13 +223,13 @@ mod test { } #[inline] - fn from_number(number: usize) -> Result { + fn from_number(number: usize) -> Result { match number { 0 => Ok(Priority::P0), 1 => Ok(Priority::P1), 2 => Ok(Priority::P2), 3 => Ok(Priority::P3), - _ => Err(Error::InvalidVariant(number)), + _ => Err(InvalidPriorityNumberError), } } } @@ -200,12 +243,12 @@ mod test { } #[inline] - fn from_number(number: usize) -> Result { + fn from_number(number: usize) -> Result { match number { 0 => Ok(CoreId::H0), 1 => Ok(CoreId::H1), 2 => Ok(CoreId::H2), - _ => Err(Error::InvalidVariant(number)), + _ => Err(InvalidCoreIdNumberError), } } } @@ -215,11 +258,11 @@ mod test { assert_eq!(Exception::E1.number(), 1); assert_eq!(Exception::E3.number(), 3); - assert_eq!(Exception::from_number(0), Err(Error::InvalidVariant(0))); + assert_eq!(Exception::from_number(0), Err(InvalidExceptionNumberError)); assert_eq!(Exception::from_number(1), Ok(Exception::E1)); - assert_eq!(Exception::from_number(2), Err(Error::InvalidVariant(2))); + assert_eq!(Exception::from_number(2), Err(InvalidExceptionNumberError)); assert_eq!(Exception::from_number(3), Ok(Exception::E3)); - assert_eq!(Exception::from_number(4), Err(Error::InvalidVariant(4))); + assert_eq!(Exception::from_number(4), Err(InvalidExceptionNumberError)); } #[test] @@ -228,12 +271,12 @@ mod test { assert_eq!(Interrupt::I2.number(), 2); assert_eq!(Interrupt::I4.number(), 4); - assert_eq!(Interrupt::from_number(0), Err(Error::InvalidVariant(0))); + assert_eq!(Interrupt::from_number(0), Err(InvalidInterruptNumberError)); assert_eq!(Interrupt::from_number(1), Ok(Interrupt::I1)); assert_eq!(Interrupt::from_number(2), Ok(Interrupt::I2)); - assert_eq!(Interrupt::from_number(3), Err(Error::InvalidVariant(3))); + assert_eq!(Interrupt::from_number(3), Err(InvalidInterruptNumberError)); assert_eq!(Interrupt::from_number(4), Ok(Interrupt::I4)); - assert_eq!(Interrupt::from_number(5), Err(Error::InvalidVariant(5))); + assert_eq!(Interrupt::from_number(5), Err(InvalidInterruptNumberError)); } #[test] @@ -247,7 +290,7 @@ mod test { assert_eq!(Priority::from_number(1), Ok(Priority::P1)); assert_eq!(Priority::from_number(2), Ok(Priority::P2)); assert_eq!(Priority::from_number(3), Ok(Priority::P3)); - assert_eq!(Priority::from_number(4), Err(Error::InvalidVariant(4))); + assert_eq!(Priority::from_number(4), Err(InvalidPriorityNumberError)); } #[test] @@ -259,6 +302,6 @@ mod test { assert_eq!(CoreId::from_number(0), Ok(CoreId::H0)); assert_eq!(CoreId::from_number(1), Ok(CoreId::H1)); assert_eq!(CoreId::from_number(2), Ok(CoreId::H2)); - assert_eq!(CoreId::from_number(3), Err(Error::InvalidVariant(3))); + assert_eq!(CoreId::from_number(3), Err(InvalidCoreIdNumberError)); } } diff --git a/cortex-m-types/src/result.rs b/cortex-m-types/src/result.rs deleted file mode 100644 index fa158529..00000000 --- a/cortex-m-types/src/result.rs +++ /dev/null @@ -1,61 +0,0 @@ -use core::fmt; - -/// Convenience alias for the [Result](core::result::Result) type for the library. -pub type Result = core::result::Result; - -/// Represents error variants for the library. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[non_exhaustive] -pub enum Error { - /// Attempted out-of-bounds access. - IndexOutOfBounds { - index: usize, - min: usize, - max: usize, - }, - /// Invalid field value. - InvalidFieldValue { - field: &'static str, - value: usize, - bitmask: usize, - }, - /// Invalid value of a register field that does not match any known variants. - InvalidFieldVariant { field: &'static str, value: usize }, - /// Invalid value. - InvalidValue { value: usize, bitmask: usize }, - /// Invalid value that does not match any known variants. - InvalidVariant(usize), - /// Unimplemented function or type. - Unimplemented, -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::IndexOutOfBounds { index, min, max } => write!( - f, - "out-of-bounds access, index: {index}, min: {min}, max: {max}" - ), - Self::InvalidFieldValue { - field, - value, - bitmask, - } => write!( - f, - "invalid {field} field value: {value:#x}, valid bitmask: {bitmask:#x}", - ), - Self::InvalidFieldVariant { field, value } => { - write!(f, "invalid {field} field variant: {value:#x}") - } - Self::InvalidValue { value, bitmask } => { - write!(f, "invalid value: {value:#x}, valid bitmask: {bitmask:#x}",) - } - Self::InvalidVariant(value) => { - write!(f, "invalid variant: {value:#x}") - } - Self::Unimplemented => write!(f, "unimplemented"), - } - } -} - -impl core::error::Error for Error {} From d4e4e6ac1b0e4c2fe0ecaddd45c60649e296b545 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 10 Nov 2026 20:06:54 +0100 Subject: [PATCH 2/2] simplify error types even further --- cortex-m-types/CHANGELOG.md | 5 +- cortex-m-types/src/lib.rs | 100 ++++++++++++------------------------ 2 files changed, 34 insertions(+), 71 deletions(-) diff --git a/cortex-m-types/CHANGELOG.md b/cortex-m-types/CHANGELOG.md index 01e4f761..e7af96b8 100644 --- a/cortex-m-types/CHANGELOG.md +++ b/cortex-m-types/CHANGELOG.md @@ -9,6 +9,5 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - MSRV bumped to 1.85 - Updated references from 'Cortex-M Team' to 'Arm Team' -- Breaking: Replaced the `result` module and its `Error` enum with a dedicated error type per - trait. `from_number` now returns `InvalidExceptionNumberError`, `InvalidInterruptNumberError`, - `InvalidPriorityNumberError` or `InvalidCoreIdNumberError`. +- Breaking: Replaced the `result` module and its `Error` enum with a single `InvalidNumberError` + type, returned by all `from_number` methods. diff --git a/cortex-m-types/src/lib.rs b/cortex-m-types/src/lib.rs index 1887213d..7488ef03 100644 --- a/cortex-m-types/src/lib.rs +++ b/cortex-m-types/src/lib.rs @@ -1,5 +1,17 @@ #![no_std] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct InvalidNumberError; + +impl core::fmt::Display for InvalidNumberError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "invalid number") + } +} + +impl core::error::Error for InvalidNumberError {} + /// Trait for enums of target-specific exception numbers. /// /// This trait should be implemented by a peripheral access crate (PAC) on its enum of available @@ -22,21 +34,9 @@ pub unsafe trait ExceptionNumber: Copy { fn number(self) -> usize; /// Tries to convert a number to a valid exception. - fn from_number(value: usize) -> Result; -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct InvalidExceptionNumberError; - -impl core::fmt::Display for InvalidExceptionNumberError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "invalid exception number") - } + fn from_number(value: usize) -> Result; } -impl core::error::Error for InvalidExceptionNumberError {} - /// Trait for enums of target-specific interrupt numbers. /// /// This trait should be implemented by a peripheral access crate (PAC) on its enum of available @@ -58,21 +58,9 @@ pub unsafe trait InterruptNumber: Copy { fn number(self) -> usize; /// Tries to convert a number to a valid interrupt. - fn from_number(value: usize) -> Result; -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct InvalidInterruptNumberError; - -impl core::fmt::Display for InvalidInterruptNumberError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "invalid interrupt number") - } + fn from_number(value: usize) -> Result; } -impl core::error::Error for InvalidInterruptNumberError {} - /// Trait for enums of priority levels. /// /// This trait should be implemented by a peripheral access crate (PAC) on its enum of available @@ -94,21 +82,9 @@ pub unsafe trait PriorityNumber: Copy { fn number(self) -> usize; /// Tries to convert a number to a valid priority level. - fn from_number(value: usize) -> Result; -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct InvalidPriorityNumberError; - -impl core::fmt::Display for InvalidPriorityNumberError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "invalid priority number") - } + fn from_number(value: usize) -> Result; } -impl core::error::Error for InvalidPriorityNumberError {} - /// Trait for enums of core identifiers. /// /// This trait should be implemented by a peripheral access crate (PAC) on its enum of available @@ -130,21 +106,9 @@ pub unsafe trait CoreIdNumber: Copy { fn number(self) -> usize; /// Tries to convert a number to a valid Core ID. - fn from_number(value: usize) -> Result; -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct InvalidCoreIdNumberError; - -impl core::fmt::Display for InvalidCoreIdNumberError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "invalid core ID number") - } + fn from_number(value: usize) -> Result; } -impl core::error::Error for InvalidCoreIdNumberError {} - #[cfg(test)] mod test { use super::*; @@ -186,11 +150,11 @@ mod test { } #[inline] - fn from_number(number: usize) -> Result { + fn from_number(number: usize) -> Result { match number { 1 => Ok(Exception::E1), 3 => Ok(Exception::E3), - _ => Err(InvalidExceptionNumberError), + _ => Err(InvalidNumberError), } } } @@ -204,12 +168,12 @@ mod test { } #[inline] - fn from_number(number: usize) -> Result { + fn from_number(number: usize) -> Result { match number { 1 => Ok(Interrupt::I1), 2 => Ok(Interrupt::I2), 4 => Ok(Interrupt::I4), - _ => Err(InvalidInterruptNumberError), + _ => Err(InvalidNumberError), } } } @@ -223,13 +187,13 @@ mod test { } #[inline] - fn from_number(number: usize) -> Result { + fn from_number(number: usize) -> Result { match number { 0 => Ok(Priority::P0), 1 => Ok(Priority::P1), 2 => Ok(Priority::P2), 3 => Ok(Priority::P3), - _ => Err(InvalidPriorityNumberError), + _ => Err(InvalidNumberError), } } } @@ -243,12 +207,12 @@ mod test { } #[inline] - fn from_number(number: usize) -> Result { + fn from_number(number: usize) -> Result { match number { 0 => Ok(CoreId::H0), 1 => Ok(CoreId::H1), 2 => Ok(CoreId::H2), - _ => Err(InvalidCoreIdNumberError), + _ => Err(InvalidNumberError), } } } @@ -258,11 +222,11 @@ mod test { assert_eq!(Exception::E1.number(), 1); assert_eq!(Exception::E3.number(), 3); - assert_eq!(Exception::from_number(0), Err(InvalidExceptionNumberError)); + assert_eq!(Exception::from_number(0), Err(InvalidNumberError)); assert_eq!(Exception::from_number(1), Ok(Exception::E1)); - assert_eq!(Exception::from_number(2), Err(InvalidExceptionNumberError)); + assert_eq!(Exception::from_number(2), Err(InvalidNumberError)); assert_eq!(Exception::from_number(3), Ok(Exception::E3)); - assert_eq!(Exception::from_number(4), Err(InvalidExceptionNumberError)); + assert_eq!(Exception::from_number(4), Err(InvalidNumberError)); } #[test] @@ -271,12 +235,12 @@ mod test { assert_eq!(Interrupt::I2.number(), 2); assert_eq!(Interrupt::I4.number(), 4); - assert_eq!(Interrupt::from_number(0), Err(InvalidInterruptNumberError)); + assert_eq!(Interrupt::from_number(0), Err(InvalidNumberError)); assert_eq!(Interrupt::from_number(1), Ok(Interrupt::I1)); assert_eq!(Interrupt::from_number(2), Ok(Interrupt::I2)); - assert_eq!(Interrupt::from_number(3), Err(InvalidInterruptNumberError)); + assert_eq!(Interrupt::from_number(3), Err(InvalidNumberError)); assert_eq!(Interrupt::from_number(4), Ok(Interrupt::I4)); - assert_eq!(Interrupt::from_number(5), Err(InvalidInterruptNumberError)); + assert_eq!(Interrupt::from_number(5), Err(InvalidNumberError)); } #[test] @@ -290,7 +254,7 @@ mod test { assert_eq!(Priority::from_number(1), Ok(Priority::P1)); assert_eq!(Priority::from_number(2), Ok(Priority::P2)); assert_eq!(Priority::from_number(3), Ok(Priority::P3)); - assert_eq!(Priority::from_number(4), Err(InvalidPriorityNumberError)); + assert_eq!(Priority::from_number(4), Err(InvalidNumberError)); } #[test] @@ -302,6 +266,6 @@ mod test { assert_eq!(CoreId::from_number(0), Ok(CoreId::H0)); assert_eq!(CoreId::from_number(1), Ok(CoreId::H1)); assert_eq!(CoreId::from_number(2), Ok(CoreId::H2)); - assert_eq!(CoreId::from_number(3), Err(InvalidCoreIdNumberError)); + assert_eq!(CoreId::from_number(3), Err(InvalidNumberError)); } }