1use bytes::Bytes;
4
5use crate::error::{Result, SomeIpError};
6use crate::header::{ClientId, MethodId, ServiceId, SessionId, SomeIpHeader, HEADER_SIZE};
7use crate::types::{MessageType, ReturnCode};
8
9pub const DEFAULT_MAX_PAYLOAD_SIZE: usize = 1400;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct SomeIpMessage {
15 pub header: SomeIpHeader,
17 pub payload: Bytes,
19}
20
21impl SomeIpMessage {
22 pub fn new(mut header: SomeIpHeader, payload: impl Into<Bytes>) -> Self {
24 let payload = payload.into();
25 header.set_payload_length(payload.len() as u32);
26 Self { header, payload }
27 }
28
29 pub fn with_header(header: SomeIpHeader) -> Self {
31 Self::new(header, Bytes::new())
32 }
33
34 pub fn request(service_id: ServiceId, method_id: MethodId) -> MessageBuilder {
36 MessageBuilder::new(service_id, method_id, MessageType::Request)
37 }
38
39 pub fn request_no_return(service_id: ServiceId, method_id: MethodId) -> MessageBuilder {
41 MessageBuilder::new(service_id, method_id, MessageType::RequestNoReturn)
42 }
43
44 pub fn notification(service_id: ServiceId, method_id: MethodId) -> MessageBuilder {
46 MessageBuilder::new(service_id, method_id, MessageType::Notification)
47 }
48
49 pub fn create_response(&self) -> MessageBuilder {
51 let mut builder = MessageBuilder::new(
52 self.header.service_id,
53 self.header.method_id,
54 MessageType::Response,
55 );
56 builder.client_id = self.header.client_id;
57 builder.session_id = self.header.session_id;
58 builder.interface_version = self.header.interface_version;
59 builder
60 }
61
62 pub fn create_error_response(&self, return_code: ReturnCode) -> MessageBuilder {
64 let mut builder = MessageBuilder::new(
65 self.header.service_id,
66 self.header.method_id,
67 MessageType::Error,
68 );
69 builder.client_id = self.header.client_id;
70 builder.session_id = self.header.session_id;
71 builder.interface_version = self.header.interface_version;
72 builder.return_code = return_code;
73 builder
74 }
75
76 pub fn from_bytes(data: &[u8]) -> Result<Self> {
78 if data.len() < HEADER_SIZE {
79 return Err(SomeIpError::MessageTooShort {
80 expected: HEADER_SIZE,
81 actual: data.len(),
82 });
83 }
84
85 let header = SomeIpHeader::from_bytes(data)?;
86 let expected_total = HEADER_SIZE + header.payload_length() as usize;
87
88 if data.len() < expected_total {
89 return Err(SomeIpError::LengthMismatch {
90 header_length: header.length,
91 actual_length: data.len() - 8,
92 });
93 }
94
95 let payload = Bytes::copy_from_slice(&data[HEADER_SIZE..expected_total]);
96
97 Ok(Self { header, payload })
98 }
99
100 pub fn to_bytes(&self) -> Vec<u8> {
102 let mut buf = Vec::with_capacity(HEADER_SIZE + self.payload.len());
103 buf.extend_from_slice(&self.header.to_bytes());
104 buf.extend_from_slice(&self.payload);
105 buf
106 }
107
108 pub fn total_size(&self) -> usize {
110 HEADER_SIZE + self.payload.len()
111 }
112
113 pub fn is_request(&self) -> bool {
115 matches!(
116 self.header.message_type,
117 MessageType::Request | MessageType::TpRequest
118 )
119 }
120
121 pub fn is_response(&self) -> bool {
123 self.header.message_type.is_response()
124 }
125
126 pub fn expects_response(&self) -> bool {
128 self.header.message_type.expects_response()
129 }
130
131 pub fn service_id(&self) -> ServiceId {
133 self.header.service_id
134 }
135
136 pub fn method_id(&self) -> MethodId {
138 self.header.method_id
139 }
140
141 pub fn client_id(&self) -> ClientId {
143 self.header.client_id
144 }
145
146 pub fn session_id(&self) -> SessionId {
148 self.header.session_id
149 }
150
151 pub fn return_code(&self) -> ReturnCode {
153 self.header.return_code
154 }
155
156 pub fn is_ok(&self) -> bool {
158 self.header.return_code.is_ok()
159 }
160}
161
162#[derive(Debug, Clone)]
164pub struct MessageBuilder {
165 service_id: ServiceId,
166 method_id: MethodId,
167 client_id: ClientId,
168 session_id: SessionId,
169 interface_version: u8,
170 message_type: MessageType,
171 return_code: ReturnCode,
172 payload: Bytes,
173}
174
175impl MessageBuilder {
176 pub fn new(service_id: ServiceId, method_id: MethodId, message_type: MessageType) -> Self {
178 Self {
179 service_id,
180 method_id,
181 client_id: ClientId::default(),
182 session_id: SessionId::default(),
183 interface_version: 1,
184 message_type,
185 return_code: ReturnCode::Ok,
186 payload: Bytes::new(),
187 }
188 }
189
190 pub fn client_id(mut self, client_id: ClientId) -> Self {
192 self.client_id = client_id;
193 self
194 }
195
196 pub fn session_id(mut self, session_id: SessionId) -> Self {
198 self.session_id = session_id;
199 self
200 }
201
202 pub fn interface_version(mut self, version: u8) -> Self {
204 self.interface_version = version;
205 self
206 }
207
208 pub fn return_code(mut self, code: ReturnCode) -> Self {
210 self.return_code = code;
211 self
212 }
213
214 pub fn payload(mut self, payload: impl Into<Bytes>) -> Self {
216 self.payload = payload.into();
217 self
218 }
219
220 pub fn payload_vec(mut self, payload: Vec<u8>) -> Self {
222 self.payload = Bytes::from(payload);
223 self
224 }
225
226 pub fn build(self) -> SomeIpMessage {
228 let header = SomeIpHeader {
229 service_id: self.service_id,
230 method_id: self.method_id,
231 length: 8 + self.payload.len() as u32,
232 client_id: self.client_id,
233 session_id: self.session_id,
234 protocol_version: crate::types::PROTOCOL_VERSION,
235 interface_version: self.interface_version,
236 message_type: self.message_type,
237 return_code: self.return_code,
238 };
239
240 SomeIpMessage {
241 header,
242 payload: self.payload,
243 }
244 }
245}
246
247#[cfg(test)]
248mod tests {
249 use super::*;
250
251 #[test]
252 fn test_message_builder() {
253 let msg = SomeIpMessage::request(ServiceId(0x1234), MethodId(0x0001))
254 .client_id(ClientId(0x0100))
255 .session_id(SessionId(0x0001))
256 .payload(b"hello".as_slice())
257 .build();
258
259 assert_eq!(msg.header.service_id, ServiceId(0x1234));
260 assert_eq!(msg.header.method_id, MethodId(0x0001));
261 assert_eq!(msg.header.client_id, ClientId(0x0100));
262 assert_eq!(msg.header.session_id, SessionId(0x0001));
263 assert_eq!(msg.header.message_type, MessageType::Request);
264 assert_eq!(msg.payload.as_ref(), b"hello");
265 assert_eq!(msg.header.length, 8 + 5); }
267
268 #[test]
269 fn test_message_roundtrip() {
270 let original = SomeIpMessage::request(ServiceId(0x1234), MethodId(0x5678))
271 .client_id(ClientId(0xABCD))
272 .session_id(SessionId(0x0001))
273 .payload(vec![1, 2, 3, 4, 5])
274 .build();
275
276 let bytes = original.to_bytes();
277 let parsed = SomeIpMessage::from_bytes(&bytes).unwrap();
278
279 assert_eq!(original, parsed);
280 }
281
282 #[test]
283 fn test_create_response() {
284 let request = SomeIpMessage::request(ServiceId(0x1234), MethodId(0x0001))
285 .client_id(ClientId(0x0100))
286 .session_id(SessionId(0x0042))
287 .build();
288
289 let response = request
290 .create_response()
291 .payload(b"response data".as_slice())
292 .build();
293
294 assert_eq!(response.header.service_id, request.header.service_id);
295 assert_eq!(response.header.method_id, request.header.method_id);
296 assert_eq!(response.header.client_id, request.header.client_id);
297 assert_eq!(response.header.session_id, request.header.session_id);
298 assert_eq!(response.header.message_type, MessageType::Response);
299 }
300
301 #[test]
302 fn test_create_error_response() {
303 let request = SomeIpMessage::request(ServiceId(0x1234), MethodId(0x0001))
304 .client_id(ClientId(0x0100))
305 .session_id(SessionId(0x0042))
306 .build();
307
308 let error = request
309 .create_error_response(ReturnCode::UnknownMethod)
310 .build();
311
312 assert_eq!(error.header.message_type, MessageType::Error);
313 assert_eq!(error.header.return_code, ReturnCode::UnknownMethod);
314 }
315
316 #[test]
317 fn test_total_size() {
318 let msg = SomeIpMessage::request(ServiceId(0x1234), MethodId(0x0001))
319 .payload(vec![0u8; 100])
320 .build();
321
322 assert_eq!(msg.total_size(), HEADER_SIZE + 100);
323 }
324
325 #[test]
326 fn test_parse_too_short() {
327 let data = vec![0u8; 10];
328 let result = SomeIpMessage::from_bytes(&data);
329 assert!(matches!(result, Err(SomeIpError::MessageTooShort { .. })));
330 }
331}