Skip to content

Commit 7daeaba

Browse files
committed
can: 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. timokroeger/embedded-can#7
1 parent 103b41e commit 7daeaba

File tree

1 file changed

+73
-11
lines changed

1 file changed

+73
-11
lines changed

src/can.rs

+73-11
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,96 @@
11
//! Controller Area Network
2+
/// Standard 11bit Identifier (0..=0x7FF)
3+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
4+
pub struct StandardId(u16);
5+
6+
impl StandardId {
7+
/// Creates a new standard identifier.
8+
pub fn new(id: u16) -> Result<StandardId, ()> {
9+
if id <= 0x7FF {
10+
Ok(StandardId(id))
11+
} else {
12+
Err(())
13+
}
14+
}
15+
}
16+
17+
impl core::convert::From<StandardId> for u16 {
18+
fn from(id: StandardId) -> u16 {
19+
id.0
20+
}
21+
}
22+
23+
impl core::convert::From<StandardId> for u32 {
24+
fn from(id: StandardId) -> u32 {
25+
id.0 as u32
26+
}
27+
}
28+
29+
impl ExtendedId {
30+
/// Creates a new extended identifier.
31+
pub fn new(id: u32) -> Result<ExtendedId, ()> {
32+
if id <= 0x1FFF_FFFF {
33+
Ok(ExtendedId(id))
34+
} else {
35+
Err(())
36+
}
37+
}
38+
}
39+
40+
impl core::convert::From<ExtendedId> for u32 {
41+
fn from(id: ExtendedId) -> u32 {
42+
id.0
43+
}
44+
}
45+
46+
/// Extended 29bit Identifier (0..=0x1FFF_FFFF)
47+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
48+
pub struct ExtendedId(u32);
249

350
/// CAN Identifier
51+
///
52+
/// The variants are wrapped in newtypes so they can only be costructed with valid values.
453
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
554
pub enum Id {
655
/// Standard 11bit Identifier (0..=0x7FF)
7-
Standard(u32),
56+
Standard(StandardId),
857

958
/// Extended 29bit Identifier (0..=0x1FFF_FFFF)
10-
Extended(u32),
59+
Extended(ExtendedId),
1160
}
1261

1362
impl Id {
14-
/// Returs true when the identifier is valid, false otherwise.
15-
pub fn valid(self) -> bool {
16-
match self {
17-
Id::Standard(id) if id <= 0x7FF => true,
18-
Id::Extended(id) if id <= 0x1FFF_FFFF => true,
19-
_ => false,
20-
}
63+
/// Creates a new standard identifier.
64+
pub fn new_standard(id: u16) -> Result<Id, ()> {
65+
Ok(StandardId::new(id)?.into())
66+
}
67+
68+
/// Creates a new extended identifier.
69+
pub fn new_extended(id: u32) -> Result<Id, ()> {
70+
Ok(ExtendedId::new(id)?.into())
71+
}
72+
}
73+
74+
impl core::convert::From<StandardId> for Id {
75+
fn from(id: StandardId) -> Id {
76+
Id::Standard(id)
77+
}
78+
}
79+
80+
impl core::convert::From<ExtendedId> for Id {
81+
fn from(id: ExtendedId) -> Id {
82+
Id::Extended(id)
2183
}
2284
}
2385

2486
/// A CAN2.0 Frame
2587
pub trait Frame: Sized {
2688
/// Creates a new frame.
27-
/// Returns an error when the the identifier is not valid or the data slice is too long.
89+
/// Returns an error when the data slice is too long.
2890
fn new(id: Id, data: &[u8]) -> Result<Self, ()>;
2991

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

3496
/// Returns true if this frame is a extended frame.

0 commit comments

Comments
 (0)