can_dbc/ast/
message_id.rs1use can_dbc_pest::{Pair, Rule};
2
3use crate::parser::parse_uint;
4use crate::DbcError;
5
6#[derive(Copy, Clone, Debug, PartialEq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub enum MessageId {
11 Standard(u16),
12 Extended(u32),
15}
16
17impl MessageId {
18 #[must_use]
20 pub fn raw(self) -> u32 {
21 match self {
22 Self::Standard(id) => u32::from(id),
23 Self::Extended(id) => id | 1 << 31,
24 }
25 }
26}
27
28impl TryFrom<u64> for MessageId {
29 type Error = DbcError;
30
31 fn try_from(value: u64) -> Result<Self, Self::Error> {
32 u32::try_from(value)
33 .map_err(|_| DbcError::MessageIdOutOfRange(value))?
34 .try_into()
35 }
36}
37
38impl TryFrom<u32> for MessageId {
39 type Error = DbcError;
40
41 fn try_from(value: u32) -> Result<Self, Self::Error> {
46 const EXTENDED_ID_FLAG: u32 = 1 << 31;
47 Ok(if value & EXTENDED_ID_FLAG != 0 {
48 Self::Extended(value & 0x1FFF_FFFF)
49 } else {
50 #[allow(clippy::cast_possible_truncation)]
54 let v = value as u16;
55
56 Self::Standard(v)
57 })
58 }
59}
60
61impl TryFrom<Pair<'_, Rule>> for MessageId {
62 type Error = DbcError;
63
64 fn try_from(value: Pair<'_, Rule>) -> Result<Self, Self::Error> {
65 Self::try_from(parse_uint(&value)?)
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use can_dbc_pest::Rule;
72
73 use crate::test_helpers::*;
74 use crate::MessageId;
75
76 #[test]
77 fn extended_message_id_raw() {
78 let id = MessageId::Extended(2);
79 assert_eq!(id.raw(), 2 | 1 << 31);
80 let id = MessageId::Extended(2 ^ 29);
81 assert_eq!(id.raw(), 2 ^ 29 | 1 << 31);
82 }
83
84 #[test]
85 fn standard_message_id_raw() {
86 let id = MessageId::Standard(2);
87 assert_eq!(id.raw(), 2);
88 }
89
90 #[test]
91 fn try_from_u32_standard() {
92 let id = MessageId::try_from(500u32).unwrap();
93 assert_eq!(id, MessageId::Standard(500));
94 }
95
96 #[test]
97 fn try_from_u32_extended() {
98 let id = MessageId::try_from(2u32 | (1 << 31)).unwrap();
99 assert_eq!(id, MessageId::Extended(2));
100 }
101
102 #[test]
103 fn try_from_u64_standard() {
104 let id = MessageId::try_from(500u64).unwrap();
105 assert_eq!(id, MessageId::Standard(500));
106 }
107
108 #[test]
109 fn try_from_u64_extended() {
110 let id = MessageId::try_from(2u64 | (1 << 31)).unwrap();
111 assert_eq!(id, MessageId::Extended(2));
112 }
113
114 #[test]
115 fn standard_message_id_test() {
116 let val = test_into::<MessageId>("2", Rule::message_id);
117 assert_eq!(val, MessageId::Standard(2));
118 }
119
120 #[test]
121 fn extended_low_message_id_test() {
122 let s = (2u32 | 1 << 31).to_string();
123 let val = test_into::<MessageId>(&s, Rule::message_id);
124 assert_eq!(val, MessageId::Extended(2));
125 }
126
127 #[test]
128 fn extended_message_id_test() {
129 let s = (0x1FFF_FFFF_u32 | 1 << 31).to_string();
130 let val = test_into::<MessageId>(&s, Rule::message_id);
131 assert_eq!(val, MessageId::Extended(0x1FFF_FFFF));
132 }
133
134 #[test]
135 fn extended_message_id_test_max_29bit() {
136 let s = u32::MAX.to_string();
137 let val = test_into::<MessageId>(&s, Rule::message_id);
138 assert_eq!(val, MessageId::Extended(0x1FFF_FFFF));
139 }
140}