Skip to content

Commit

Permalink
can: Only allow valid Id s to be constructed
Browse files Browse the repository at this point in the history
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.
timokroeger/embedded-can#7
  • Loading branch information
timokroeger committed Nov 18, 2020
1 parent 103b41e commit 7daeaba
Showing 1 changed file with 73 additions and 11 deletions.
84 changes: 73 additions & 11 deletions src/can.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,96 @@
//! Controller Area Network
/// 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<StandardId, ()> {
if id <= 0x7FF {
Ok(StandardId(id))
} else {
Err(())
}
}
}

impl core::convert::From<StandardId> for u16 {
fn from(id: StandardId) -> u16 {
id.0
}
}

impl core::convert::From<StandardId> for u32 {
fn from(id: StandardId) -> u32 {
id.0 as u32
}
}

impl ExtendedId {
/// Creates a new extended identifier.
pub fn new(id: u32) -> Result<ExtendedId, ()> {
if id <= 0x1FFF_FFFF {
Ok(ExtendedId(id))
} else {
Err(())
}
}
}

impl core::convert::From<ExtendedId> 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<Id, ()> {
Ok(StandardId::new(id)?.into())
}

/// Creates a new extended identifier.
pub fn new_extended(id: u32) -> Result<Id, ()> {
Ok(ExtendedId::new(id)?.into())
}
}

impl core::convert::From<StandardId> for Id {
fn from(id: StandardId) -> Id {
Id::Standard(id)
}
}

impl core::convert::From<ExtendedId> 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<Self, ()>;

/// Creates a new remote frame (RTR bit set).
/// Returns an error when the the identifier is or the data length code (DLC) not valid.
/// Returns an error when the data length code (DLC) is not valid.
fn new_remote(id: Id, dlc: usize) -> Result<Self, ()>;

/// Returns true if this frame is a extended frame.
Expand Down

0 comments on commit 7daeaba

Please sign in to comment.