Skip to content

Commit 78cf640

Browse files
committed
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.
1 parent c085205 commit 78cf640

File tree

1 file changed

+74
-11
lines changed

1 file changed

+74
-11
lines changed

src/lib.rs

+74-11
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,98 @@
33

44
pub mod blocking;
55

6+
/// Standard 11bit Identifier (0..=0x7FF)
7+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
8+
pub struct StandardId(u16);
9+
10+
impl StandardId {
11+
/// Creates a new standard identifier.
12+
pub fn new(id: u16) -> Result<StandardId, ()> {
13+
if id <= 0x7FF {
14+
Ok(StandardId(id))
15+
} else {
16+
Err(())
17+
}
18+
}
19+
}
20+
21+
impl core::convert::From<StandardId> for u16 {
22+
fn from(id: StandardId) -> u16 {
23+
id.0
24+
}
25+
}
26+
27+
impl core::convert::From<StandardId> for u32 {
28+
fn from(id: StandardId) -> u32 {
29+
id.0 as u32
30+
}
31+
}
32+
33+
impl ExtendedId {
34+
/// Creates a new extended identifier.
35+
pub fn new(id: u32) -> Result<ExtendedId, ()> {
36+
if id <= 0x1FFF_FFFF {
37+
Ok(ExtendedId(id))
38+
} else {
39+
Err(())
40+
}
41+
}
42+
}
43+
44+
impl core::convert::From<ExtendedId> for u32 {
45+
fn from(id: ExtendedId) -> u32 {
46+
id.0
47+
}
48+
}
49+
50+
/// Extended 29bit Identifier (0..=0x1FFF_FFFF)
51+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
52+
pub struct ExtendedId(u32);
53+
654
/// CAN Identifier
55+
///
56+
/// The variants are wrapped in newtypes so they can only be costructed with valid values.
757
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
858
pub enum Id {
959
/// Standard 11bit Identifier (0..=0x7FF)
10-
Standard(u32),
60+
Standard(StandardId),
1161

1262
/// Extended 29bit Identifier (0..=0x1FFF_FFFF)
13-
Extended(u32),
63+
Extended(ExtendedId),
1464
}
1565

1666
impl Id {
17-
/// Returs true when the identifier is valid, false otherwise.
18-
pub fn valid(self) -> bool {
19-
match self {
20-
Id::Standard(id) if id <= 0x7FF => true,
21-
Id::Extended(id) if id <= 0x1FFF_FFFF => true,
22-
_ => false,
23-
}
67+
/// Creates a new standard identifier.
68+
pub fn new_standard(id: u16) -> Result<Id, ()> {
69+
Ok(StandardId::new(id)?.into())
70+
}
71+
72+
/// Creates a new extended identifier.
73+
pub fn new_extended(id: u32) -> Result<Id, ()> {
74+
Ok(ExtendedId::new(id)?.into())
75+
}
76+
}
77+
78+
impl core::convert::From<StandardId> for Id {
79+
fn from(id: StandardId) -> Id {
80+
Id::Standard(id)
81+
}
82+
}
83+
84+
impl core::convert::From<ExtendedId> for Id {
85+
fn from(id: ExtendedId) -> Id {
86+
Id::Extended(id)
2487
}
2588
}
2689

2790
/// A CAN2.0 Frame
2891
pub trait Frame: Sized {
2992
/// Creates a new frame.
30-
/// Returns an error when the the identifier is not valid or the data slice is too long.
93+
/// Returns an error when the data slice is too long.
3194
fn new(id: Id, data: &[u8]) -> Result<Self, ()>;
3295

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

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

0 commit comments

Comments
 (0)