From 78cf64078c10b1391ab24299920e0e743292781f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Sun, 15 Nov 2020 21:34:21 +0100 Subject: [PATCH] Only allow valid `Id` s to be constructed Use newtypes for the enum variants so they cannot be constructed anymore. Implement the `From` trait for the variants to access the id value as integer. --- src/lib.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2d3ecbd..f5f3986 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,35 +3,98 @@ pub mod blocking; +/// Standard 11bit Identifier (0..=0x7FF) +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct StandardId(u16); + +impl StandardId { + /// Creates a new standard identifier. + pub fn new(id: u16) -> Result { + if id <= 0x7FF { + Ok(StandardId(id)) + } else { + Err(()) + } + } +} + +impl core::convert::From for u16 { + fn from(id: StandardId) -> u16 { + id.0 + } +} + +impl core::convert::From for u32 { + fn from(id: StandardId) -> u32 { + id.0 as u32 + } +} + +impl ExtendedId { + /// Creates a new extended identifier. + pub fn new(id: u32) -> Result { + if id <= 0x1FFF_FFFF { + Ok(ExtendedId(id)) + } else { + Err(()) + } + } +} + +impl core::convert::From for u32 { + fn from(id: ExtendedId) -> u32 { + id.0 + } +} + +/// Extended 29bit Identifier (0..=0x1FFF_FFFF) +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct ExtendedId(u32); + /// CAN Identifier +/// +/// The variants are wrapped in newtypes so they can only be costructed with valid values. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Id { /// Standard 11bit Identifier (0..=0x7FF) - Standard(u32), + Standard(StandardId), /// Extended 29bit Identifier (0..=0x1FFF_FFFF) - Extended(u32), + Extended(ExtendedId), } impl Id { - /// Returs true when the identifier is valid, false otherwise. - pub fn valid(self) -> bool { - match self { - Id::Standard(id) if id <= 0x7FF => true, - Id::Extended(id) if id <= 0x1FFF_FFFF => true, - _ => false, - } + /// Creates a new standard identifier. + pub fn new_standard(id: u16) -> Result { + Ok(StandardId::new(id)?.into()) + } + + /// Creates a new extended identifier. + pub fn new_extended(id: u32) -> Result { + Ok(ExtendedId::new(id)?.into()) + } +} + +impl core::convert::From for Id { + fn from(id: StandardId) -> Id { + Id::Standard(id) + } +} + +impl core::convert::From for Id { + fn from(id: ExtendedId) -> Id { + Id::Extended(id) } } /// A CAN2.0 Frame pub trait Frame: Sized { /// Creates a new frame. - /// Returns an error when the the identifier is not valid or the data slice is too long. + /// Returns an error when the data slice is too long. fn new(id: Id, data: &[u8]) -> Result; /// Creates a new remote frame (RTR bit set). - /// Returns an error when the identifier or the data length code (DLC) is not valid. + /// Returns an error when the data length code (DLC) is not valid. fn new_remote(id: Id, dlc: usize) -> Result; /// Returns true if this frame is a extended frame.