simple_someip/protocol/
message_type.rs1use super::Error;
2
3pub const MESSAGE_TYPE_TP_FLAG: u8 = 0x20;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub enum MessageType {
9 Request,
10 RequestNoReturn,
11 Notification,
12 Response,
13 Error,
14}
15
16impl MessageType {
17 const fn try_from(value: u8) -> Result<Self, Error> {
18 match value & !MESSAGE_TYPE_TP_FLAG {
19 0x00 => Ok(MessageType::Request),
20 0x01 => Ok(MessageType::RequestNoReturn),
21 0x02 => Ok(MessageType::Notification),
22 0x80 => Ok(MessageType::Response),
23 0x81 => Ok(MessageType::Error),
24 _ => Err(Error::InvalidMessageTypeField(value)),
25 }
26 }
27}
28
29impl TryFrom<u8> for MessageType {
30 type Error = Error;
31 fn try_from(value: u8) -> Result<Self, Error> {
32 MessageType::try_from(value)
33 }
34}
35
36#[derive(Clone, Copy, Debug, Eq, PartialEq)]
40pub struct MessageTypeField(u8);
41
42impl TryFrom<u8> for MessageTypeField {
43 type Error = Error;
44 fn try_from(value: u8) -> Result<Self, Self::Error> {
45 MessageType::try_from(value)?;
46 Ok(MessageTypeField(value))
47 }
48}
49
50impl From<MessageTypeField> for u8 {
51 fn from(message_type_field: MessageTypeField) -> u8 {
52 message_type_field.0
53 }
54}
55
56impl MessageTypeField {
57 #[must_use]
58 pub const fn new(msg_type: MessageType, tp: bool) -> Self {
59 let message_type_byte = if tp {
60 msg_type as u8 | MESSAGE_TYPE_TP_FLAG
61 } else {
62 msg_type as u8
63 };
64 MessageTypeField(message_type_byte)
65 }
66
67 #[must_use]
68 pub const fn new_sd() -> Self {
69 Self::new(MessageType::Notification, false)
70 }
71
72 #[must_use]
74 pub fn message_type(&self) -> MessageType {
75 MessageType::try_from(self.0).unwrap()
77 }
78
79 #[must_use]
80 pub const fn is_tp(&self) -> bool {
81 self.0 & MESSAGE_TYPE_TP_FLAG != 0
82 }
83}
84
85#[cfg(test)]
86mod tests {
87
88 use super::*;
89 #[test]
91 fn test_all_u8_values() {
92 let valid_inputs: [u8; 10] = [0x00, 0x01, 0x02, 0x80, 0x81, 0x20, 0x21, 0x22, 0xA0, 0xA1];
93 for i in 0..=255 {
94 let msg_type = MessageTypeField::try_from(i);
95 if valid_inputs.contains(&i) {
96 assert!(msg_type.is_ok());
97 let msg_type = msg_type.unwrap();
98 match i {
99 0x00 => {
100 assert_eq!(msg_type.message_type(), MessageType::Request);
101 assert!(!msg_type.is_tp());
102 }
103 0x01 => {
104 assert_eq!(msg_type.message_type(), MessageType::RequestNoReturn);
105 assert!(!msg_type.is_tp());
106 }
107 0x02 => {
108 assert_eq!(msg_type.message_type(), MessageType::Notification);
109 assert!(!msg_type.is_tp());
110 }
111 0x80 => {
112 assert_eq!(msg_type.message_type(), MessageType::Response);
113 assert!(!msg_type.is_tp());
114 }
115 0x81 => {
116 assert_eq!(msg_type.message_type(), MessageType::Error);
117 assert!(!msg_type.is_tp());
118 }
119 0x20 => {
120 assert_eq!(msg_type.message_type(), MessageType::Request);
121 assert!(msg_type.is_tp());
122 }
123 0x21 => {
124 assert_eq!(msg_type.message_type(), MessageType::RequestNoReturn);
125 assert!(msg_type.is_tp());
126 }
127 0x22 => {
128 assert_eq!(msg_type.message_type(), MessageType::Notification);
129 assert!(msg_type.is_tp());
130 }
131 0xA0 => {
132 assert_eq!(msg_type.message_type(), MessageType::Response);
133 assert!(msg_type.is_tp());
134 }
135 0xA1 => {
136 assert_eq!(msg_type.message_type(), MessageType::Error);
137 assert!(msg_type.is_tp());
138 }
139
140 _ => unreachable!("Only valid inputs should have made it to this point"),
141 }
142 } else {
143 assert!(msg_type.is_err());
144 }
145 }
146 }
147}