someip_rs/
types.rs

1//! Core SOME/IP types and constants.
2
3/// SOME/IP protocol version (always 0x01).
4pub const PROTOCOL_VERSION: u8 = 0x01;
5
6/// SOME/IP message types as defined in the specification.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[repr(u8)]
9pub enum MessageType {
10    /// Request expecting a response.
11    Request = 0x00,
12    /// Request not expecting a response (fire-and-forget).
13    RequestNoReturn = 0x01,
14    /// Cyclic or event-based notification.
15    Notification = 0x02,
16    /// Response to a request.
17    Response = 0x80,
18    /// Error response to a request.
19    Error = 0x81,
20    /// TP Request (segmented).
21    TpRequest = 0x20,
22    /// TP Request not expecting a response.
23    TpRequestNoReturn = 0x21,
24    /// TP Notification.
25    TpNotification = 0x22,
26    /// TP Response.
27    TpResponse = 0xA0,
28    /// TP Error.
29    TpError = 0xA1,
30}
31
32impl MessageType {
33    /// Create a MessageType from a raw byte value.
34    pub fn from_u8(value: u8) -> Option<Self> {
35        match value {
36            0x00 => Some(Self::Request),
37            0x01 => Some(Self::RequestNoReturn),
38            0x02 => Some(Self::Notification),
39            0x80 => Some(Self::Response),
40            0x81 => Some(Self::Error),
41            0x20 => Some(Self::TpRequest),
42            0x21 => Some(Self::TpRequestNoReturn),
43            0x22 => Some(Self::TpNotification),
44            0xA0 => Some(Self::TpResponse),
45            0xA1 => Some(Self::TpError),
46            _ => None,
47        }
48    }
49
50    /// Check if this message type expects a response.
51    pub fn expects_response(&self) -> bool {
52        matches!(self, Self::Request | Self::TpRequest)
53    }
54
55    /// Check if this is a response message type.
56    pub fn is_response(&self) -> bool {
57        matches!(
58            self,
59            Self::Response | Self::Error | Self::TpResponse | Self::TpError
60        )
61    }
62
63    /// Check if this is a TP (Transport Protocol) segmented message.
64    pub fn is_tp(&self) -> bool {
65        matches!(
66            self,
67            Self::TpRequest
68                | Self::TpRequestNoReturn
69                | Self::TpNotification
70                | Self::TpResponse
71                | Self::TpError
72        )
73    }
74}
75
76/// SOME/IP return codes as defined in the specification.
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
78#[repr(u8)]
79pub enum ReturnCode {
80    /// No error occurred.
81    Ok = 0x00,
82    /// An unspecified error occurred.
83    NotOk = 0x01,
84    /// The requested Service ID is unknown.
85    UnknownService = 0x02,
86    /// The requested Method ID is unknown.
87    UnknownMethod = 0x03,
88    /// Service is not ready.
89    NotReady = 0x04,
90    /// Service is not reachable.
91    NotReachable = 0x05,
92    /// Timeout occurred.
93    Timeout = 0x06,
94    /// Wrong protocol version.
95    WrongProtocolVersion = 0x07,
96    /// Wrong interface version.
97    WrongInterfaceVersion = 0x08,
98    /// Malformed message.
99    MalformedMessage = 0x09,
100    /// Wrong message type.
101    WrongMessageType = 0x0A,
102    /// E2E repeated.
103    E2ERepeated = 0x0B,
104    /// E2E wrong sequence.
105    E2EWrongSequence = 0x0C,
106    /// E2E error (not further specified).
107    E2E = 0x0D,
108    /// E2E not available.
109    E2ENotAvailable = 0x0E,
110    /// E2E no new data.
111    E2ENoNewData = 0x0F,
112}
113
114impl ReturnCode {
115    /// Create a ReturnCode from a raw byte value.
116    pub fn from_u8(value: u8) -> Option<Self> {
117        match value {
118            0x00 => Some(Self::Ok),
119            0x01 => Some(Self::NotOk),
120            0x02 => Some(Self::UnknownService),
121            0x03 => Some(Self::UnknownMethod),
122            0x04 => Some(Self::NotReady),
123            0x05 => Some(Self::NotReachable),
124            0x06 => Some(Self::Timeout),
125            0x07 => Some(Self::WrongProtocolVersion),
126            0x08 => Some(Self::WrongInterfaceVersion),
127            0x09 => Some(Self::MalformedMessage),
128            0x0A => Some(Self::WrongMessageType),
129            0x0B => Some(Self::E2ERepeated),
130            0x0C => Some(Self::E2EWrongSequence),
131            0x0D => Some(Self::E2E),
132            0x0E => Some(Self::E2ENotAvailable),
133            0x0F => Some(Self::E2ENoNewData),
134            _ => None,
135        }
136    }
137
138    /// Check if this return code indicates success.
139    pub fn is_ok(&self) -> bool {
140        *self == Self::Ok
141    }
142
143    /// Check if this return code indicates an error.
144    pub fn is_error(&self) -> bool {
145        *self != Self::Ok
146    }
147}
148
149impl Default for ReturnCode {
150    fn default() -> Self {
151        Self::Ok
152    }
153}
154
155#[cfg(test)]
156mod tests {
157    use super::*;
158
159    #[test]
160    fn test_message_type_from_u8() {
161        assert_eq!(MessageType::from_u8(0x00), Some(MessageType::Request));
162        assert_eq!(MessageType::from_u8(0x80), Some(MessageType::Response));
163        assert_eq!(MessageType::from_u8(0xFF), None);
164    }
165
166    #[test]
167    fn test_message_type_expects_response() {
168        assert!(MessageType::Request.expects_response());
169        assert!(!MessageType::RequestNoReturn.expects_response());
170        assert!(!MessageType::Notification.expects_response());
171        assert!(!MessageType::Response.expects_response());
172    }
173
174    #[test]
175    fn test_return_code_from_u8() {
176        assert_eq!(ReturnCode::from_u8(0x00), Some(ReturnCode::Ok));
177        assert_eq!(ReturnCode::from_u8(0x02), Some(ReturnCode::UnknownService));
178        assert_eq!(ReturnCode::from_u8(0xFF), None);
179    }
180
181    #[test]
182    fn test_return_code_is_ok() {
183        assert!(ReturnCode::Ok.is_ok());
184        assert!(!ReturnCode::NotOk.is_ok());
185        assert!(!ReturnCode::Timeout.is_ok());
186    }
187}