diff --git a/backend/src/domain/relay/controler.rs b/backend/src/domain/relay/controler.rs new file mode 100644 index 0000000..50bc63e --- /dev/null +++ b/backend/src/domain/relay/controler.rs @@ -0,0 +1,7 @@ +/// Errors that can occur during relay controller operations. +#[derive(Debug, thiserror::Error)] +pub enum ControllerError { + /// The provided relay ID is outside the valid range (1-8). + #[error("Invalid relay ID: {0}")] + InvalidRelayId(u8), +} diff --git a/backend/src/domain/relay/mod.rs b/backend/src/domain/relay/mod.rs index 0f64921..4e63f39 100644 --- a/backend/src/domain/relay/mod.rs +++ b/backend/src/domain/relay/mod.rs @@ -7,3 +7,5 @@ pub mod repository; /// Domain types for relay identification and control. pub mod types; +/// Controller error types for relay operations. +pub mod controler; diff --git a/backend/src/domain/relay/types/mod.rs b/backend/src/domain/relay/types/mod.rs new file mode 100644 index 0000000..d5467b3 --- /dev/null +++ b/backend/src/domain/relay/types/mod.rs @@ -0,0 +1,2 @@ +mod relayid; +pub use relayid::RelayId; diff --git a/backend/src/domain/relay/types.rs b/backend/src/domain/relay/types/relayid.rs similarity index 65% rename from backend/src/domain/relay/types.rs rename to backend/src/domain/relay/types/relayid.rs index 21dc380..835ccd0 100644 --- a/backend/src/domain/relay/types.rs +++ b/backend/src/domain/relay/types/relayid.rs @@ -1,3 +1,5 @@ +use crate::domain::relay::controler::ControllerError; + /// Unique identifier for a relay in the system. /// /// Uses the newtype pattern to provide type safety and prevent mixing relay IDs @@ -7,6 +9,33 @@ #[repr(transparent)] pub struct RelayId(u8); +impl RelayId { + /// Creates a new `RelayId` from a relay channel number. + /// + /// This is a smart constructor that validates the relay ID is within the + /// valid range (1-8) for an 8-channel relay controller. + /// + /// # Errors + /// + /// Returns `ControllerError::InvalidRelayId` if the ID is not in the range 1-8. + pub const fn new(id: u8) -> Result { + if id > 0 && id < 9 { + Ok(Self(id)) + } else { + Err(ControllerError::InvalidRelayId(id)) + } + } + + /// Returns the inner `u8` value of the relay ID. + /// + /// This accessor method provides access to the underlying relay channel number. + #[must_use] + pub const fn as_u8(&self) -> u8 { + self.0 + } + +} + impl std::fmt::Display for RelayId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.0.fmt(f) diff --git a/specs/001-modbus-relay-control/tasks.md b/specs/001-modbus-relay-control/tasks.md index 70f955a..bddaa4c 100644 --- a/specs/001-modbus-relay-control/tasks.md +++ b/specs/001-modbus-relay-control/tasks.md @@ -211,7 +211,7 @@ - **File**: src/domain/relay.rs - **Complexity**: Low | **Uncertainty**: Low -- [ ] **T018** [US1] [TDD] Implement RelayId newtype with validation +- [x] **T018** [US1] [TDD] Implement RelayId newtype with validation - #[repr(transparent)] newtype wrapping u8 - Constructor validates 1..=8 range - Implement Display, Debug, Clone, Copy, PartialEq, Eq