simple_someip/protocol/
message_id.rs1use crate::SD_MESSAGE_ID_VALUE;
2
3#[derive(Clone, Copy, Eq, PartialEq)]
8pub struct MessageId(u32);
9
10impl From<u32> for MessageId {
11 fn from(message_id: u32) -> Self {
12 MessageId(message_id)
13 }
14}
15
16impl MessageId {
17 pub const SD: Self = Self::new(SD_MESSAGE_ID_VALUE);
19
20 #[must_use]
22 pub const fn new(message_id: u32) -> Self {
23 MessageId(message_id)
24 }
25
26 #[must_use]
28 pub const fn new_from_service_and_method(service_id: u16, method_id: u16) -> Self {
29 MessageId(((service_id as u32) << 16) | method_id as u32)
30 }
31
32 #[inline]
34 #[must_use]
35 pub const fn message_id(&self) -> u32 {
36 self.0
37 }
38
39 #[inline]
41 pub const fn set_message_id(&mut self, message_id: u32) {
42 self.0 = message_id;
43 }
44
45 #[inline]
47 #[must_use]
48 pub const fn service_id(&self) -> u16 {
49 (self.0 >> 16) as u16
50 }
51
52 #[inline]
54 pub const fn set_service_id(&mut self, service_id: u16) {
55 self.0 = (self.0 & 0xFFFF) | ((service_id as u32) << 16);
56 }
57
58 #[inline]
60 #[must_use]
61 pub const fn method_id(&self) -> u16 {
62 (self.0 & 0xFFFF) as u16
63 }
64
65 #[inline]
67 pub const fn set_method_id(&mut self, method_id: u16) {
68 self.0 = (self.0 & 0xFFFF_0000) | method_id as u32;
69 }
70
71 #[inline]
73 #[must_use]
74 pub const fn is_event(&self) -> bool {
75 self.method_id() & 0x8000 != 0
76 }
77
78 #[inline]
80 #[must_use]
81 pub const fn is_sd(&self) -> bool {
82 self.0 == crate::SD_MESSAGE_ID_VALUE
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
93 fn from_u32() {
94 let mid = MessageId::from(0x1234_5678);
95 assert_eq!(mid.message_id(), 0x1234_5678);
96 }
97
98 #[test]
99 fn new() {
100 let mid = MessageId::new(0xABCD_EF01);
101 assert_eq!(mid.message_id(), 0xABCD_EF01);
102 }
103
104 #[test]
105 fn new_from_service_and_method() {
106 let mid = MessageId::new_from_service_and_method(0x1234, 0x5678);
107 assert_eq!(mid.message_id(), 0x1234_5678);
108 assert_eq!(mid.service_id(), 0x1234);
109 assert_eq!(mid.method_id(), 0x5678);
110 }
111
112 #[test]
115 fn set_message_id() {
116 let mut mid = MessageId::new(0);
117 mid.set_message_id(0xDEAD_BEEF);
118 assert_eq!(mid.message_id(), 0xDEAD_BEEF);
119 }
120
121 #[test]
122 fn set_service_id_preserves_method() {
123 let mut mid = MessageId::new_from_service_and_method(0x0001, 0x00FF);
124 mid.set_service_id(0xAAAA);
125 assert_eq!(mid.service_id(), 0xAAAA);
126 assert_eq!(mid.method_id(), 0x00FF);
127 }
128
129 #[test]
130 fn set_method_id_preserves_service() {
131 let mut mid = MessageId::new_from_service_and_method(0x00FF, 0x0001);
132 mid.set_method_id(0xBBBB);
133 assert_eq!(mid.service_id(), 0x00FF);
134 assert_eq!(mid.method_id(), 0xBBBB);
135 }
136
137 #[test]
140 fn is_event_true_when_method_high_bit_set() {
141 let mid = MessageId::new_from_service_and_method(0x0001, 0x8001);
142 assert!(mid.is_event());
143 }
144
145 #[test]
146 fn is_event_false_when_method_high_bit_clear() {
147 let mid = MessageId::new_from_service_and_method(0x0001, 0x0001);
148 assert!(!mid.is_event());
149 }
150
151 #[test]
154 fn is_sd_true_for_sd_constant() {
155 assert!(MessageId::SD.is_sd());
156 }
157
158 #[test]
159 fn is_sd_false_for_other() {
160 let mid = MessageId::new(0x0001_0001);
161 assert!(!mid.is_sd());
162 }
163
164 #[test]
167 fn sd_constant_value() {
168 assert_eq!(MessageId::SD.message_id(), 0xFFFF_8100);
169 }
170
171 #[test]
174 fn debug_format() {
175 use core::fmt::Write;
176 let mid = MessageId::new_from_service_and_method(0x1234, 0x0001);
177 let mut buf = heapless::String::<128>::new();
178 write!(buf, "{mid:?}").unwrap();
179 assert!(buf.contains("service_id"));
180 assert!(buf.contains("method_id"));
181 }
182}
183
184impl core::fmt::Debug for MessageId {
185 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
186 write!(
187 f,
188 "Message Id: {{ service_id: {:#02X}, method_id: {:#02X} }}",
189 self.service_id(),
190 self.method_id(),
191 )
192 }
193}