someip_wire/
lib.rs

1//! # SOME/IP-wire
2//!
3//! This crate provides the means for parsing byte arrays into higher-level
4//! SOME/IP representations, and vice versa. It is designed to be used in embedded
5//! environments and is a `no_std` crate by default.
6//!
7//! ## Scope
8//!
9//! **This crate focuses solely on SOME/IP header parsing and serialization.**
10//!
11//! The crate parses the standardized 16-byte SOME/IP header and provides the payload
12//! data as a raw byte slice. It does NOT parse the payload content itself, as payload
13//! format is entirely application-specific and defined by service interface definitions
14//! (e.g., FIDL/Franca IDL).
15//!
16//! To use this crate in a complete SOME/IP stack, you need to:
17//! 1. Use this crate to parse/emit SOME/IP headers
18//! 2. Implement your own payload parser/serializer based on your service definitions
19//! 3. Connect service/method IDs to their respective payload handlers
20//!
21//! This separation keeps the crate focused, lightweight, and universally applicable
22//! across different SOME/IP service implementations.
23//!
24//! ## Features
25//!
26//! - `no_std` compatible by default
27//! - Zero-allocation parsing and serialization
28//! - Support for all SOME/IP message types
29//! - Clean enum-based API for return codes and message types
30//! - Wire format using simple u8 for efficiency
31//!
32//! ## Examples
33//!
34//! ### Parsing a SOME/IP packet
35//!
36//! ```rust
37//! use someip_wire::packet::Packet;
38//! use someip_wire::payload::Repr;
39//! use someip_wire::types::{MessageId, RequestId, MessageType, ReturnCode};
40//!
41//! // Example SOME/IP packet bytes (16-byte header + payload)
42//! let buffer = [
43//!     0x12, 0x34, 0x00, 0x01, // Message ID (service 0x1234, method 0x0001)
44//!     0x00, 0x00, 0x00, 0x08, // Length (8 bytes payload)
45//!     0x00, 0x01, 0x00, 0x00, // Request ID (client 0x0001, session 0x0000)
46//!     0x01,                   // Protocol version
47//!     0x01,                   // Interface version
48//!     0x00,                   // Message type (Request)
49//!     0x00,                   // Return code (E_OK)
50//!     // Payload data follows...
51//!     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
52//! ];
53//!
54//! let packet = Packet::new_unchecked(&buffer);
55//! let repr = Repr::parse(&packet).unwrap();
56//!
57//! assert_eq!(repr.message_type, MessageType::Request);
58//! assert_eq!(repr.return_code, ReturnCode::E_OK);
59//! assert_eq!(repr.protocol_version, 0x01);
60//! assert_eq!(repr.data.len(), 8);
61//! ```
62//!
63//! ### Creating and emitting a SOME/IP packet
64//!
65//! ```rust
66//! use someip_wire::packet::Packet;
67//! use someip_wire::payload::Repr;
68//! use someip_wire::types::{MessageId, RequestId, ClientId, MessageType, ReturnCode};
69//!
70//! let repr = Repr {
71//!     message_id: MessageId {
72//!         service_id: 0x1234,
73//!         method_id: 0x0001,
74//!     },
75//!     length: 8,
76//!     request_id: RequestId {
77//!         client_id: ClientId {
78//!             client_id_prefix: 0x00,
79//!             client_id: 0x01,
80//!         },
81//!         session_id: 0x0000,
82//!     },
83//!     protocol_version: 0x01,
84//!     interface_version: 0x01,
85//!     message_type: MessageType::Response,
86//!     return_code: ReturnCode::E_OK,
87//!     data: &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
88//! };
89//!
90//! let mut buffer = [0u8; 24]; // 16-byte header + 8-byte payload
91//! let mut packet = Packet::new_unchecked(&mut buffer);
92//! repr.emit(&mut packet);
93//!
94//! assert_eq!(packet.message_type(), 0x03); // Response
95//! assert_eq!(packet.return_code(), 0x00); // E_OK
96//! ```
97//!
98//! ### Working with return codes
99//!
100//! ```rust
101//! use someip_wire::types::ReturnCode;
102//!
103//! // Named return codes
104//! let ok = ReturnCode::E_OK;
105//! let error = ReturnCode::E_NOT_OK;
106//! let timeout = ReturnCode::E_TIMEOUT;
107//!
108//! // Reserved ranges
109//! let someip_reserved = ReturnCode::ReservedSomeIP(0x15);
110//! let service_reserved = ReturnCode::ReservedServiceMethod(0x30);
111//!
112//! // Convert to/from u8
113//! assert_eq!(ok.as_u8(), 0x00);
114//! assert_eq!(ReturnCode::from_u8(0x01), Some(ReturnCode::E_NOT_OK));
115//!
116//! // Check return code properties
117//! assert!(ok.is_ok());
118//! assert!(someip_reserved.is_reserved_someip());
119//! assert!(service_reserved.is_reserved_service_method());
120//! ```
121//!
122//! ## Modules
123//!
124//! - `error`: Contains the error type for SOME/IP packet parsing
125//! - `field`: Contains the field definitions for the SOME/IP header
126//! - `packet`: Contains the `Packet` type for low-level packet access (wire format)
127//! - `payload`: Contains the `Repr` type for high-level SOME/IP representation
128//! - `types`: Contains SOME/IP type definitions (MessageId, RequestId, ReturnCode, MessageType)
129//!
130//! ## Architecture
131//!
132//! The crate uses a two-layer architecture:
133//! - **Wire format layer** (`packet`): Works directly with u8 values for efficiency
134//! - **Representation layer** (`payload`, `types`): Provides clean enums and type-safe APIs
135//!
136//! This design ensures zero-cost abstractions while maintaining a pleasant developer experience.
137//!
138
139#![no_std]
140
141pub mod error;
142pub mod field;
143pub mod packet;
144pub mod payload;
145pub mod types;
146
147#[cfg(test)]
148mod tests {
149    use crate::{
150        packet::Packet,
151        payload::Repr,
152        types::{ClientId, MessageId, MessageType, RequestId, ReturnCode},
153    };
154
155    #[test]
156    fn test_deconstruct_without_payload() {
157        let raw_packet: [u8; 16] = [
158            0x12, 0x34, 0x00, 0x01, // Message ID
159            0x00, 0x00, 0x00, 0x00, // Length
160            0x01, 0x02, 0x00, 0x01, // Request ID
161            0x01, // Protocol Version
162            0x01, // Interface Version
163            0x00, // Message Type
164            0x00, // Return Code
165        ];
166
167        let packet = Packet::new_checked(&raw_packet[..]).unwrap();
168        let repr = Repr::parse(&packet).unwrap();
169
170        assert_eq!(
171            repr.message_id,
172            MessageId {
173                service_id: 0x1234,
174                method_id: 0x0001,
175            }
176        );
177        assert_eq!(repr.length, 0);
178
179        assert_eq!(
180            repr.request_id,
181            RequestId {
182                client_id: ClientId {
183                    client_id_prefix: 0x01,
184                    client_id: 0x02,
185                },
186                session_id: 0x0001,
187            }
188        );
189        assert_eq!(repr.protocol_version, 0x01);
190        assert_eq!(repr.interface_version, 0x01);
191        assert_eq!(repr.message_type, MessageType::Request);
192        assert_eq!(repr.return_code, ReturnCode::E_OK);
193        assert_eq!(repr.data, &[]);
194    }
195
196    #[test]
197    fn test_deconstruct_with_payload() {
198        let raw_packet: [u8; 20] = [
199            0x12, 0x34, 0x00, 0x01, // Message ID
200            0x00, 0x00, 0x00, 0x04, // Length
201            0x01, 0x02, 0x00, 0x01, // Request ID
202            0x01, // Protocol Version
203            0x01, // Interface Version
204            0x00, // Message Type
205            0x00, // Return Code
206            0xDE, 0xAD, 0xBE, 0xEF, // Payload
207        ];
208
209        let packet = Packet::new_checked(&raw_packet[..]).unwrap();
210        let repr = Repr::parse(&packet).unwrap();
211
212        assert_eq!(
213            repr.message_id,
214            MessageId {
215                service_id: 0x1234,
216                method_id: 0x0001,
217            }
218        );
219        assert_eq!(repr.length, 4);
220
221        assert_eq!(
222            repr.request_id,
223            RequestId {
224                client_id: ClientId {
225                    client_id_prefix: 0x01,
226                    client_id: 0x02,
227                },
228                session_id: 0x0001,
229            }
230        );
231        assert_eq!(repr.protocol_version, 0x01);
232        assert_eq!(repr.interface_version, 0x01);
233        assert_eq!(repr.message_type, MessageType::Request);
234        assert_eq!(repr.return_code, ReturnCode::E_OK);
235        assert_eq!(repr.data, &[0xDE, 0xAD, 0xBE, 0xEF]);
236    }
237
238    #[test]
239    fn test_repr_parse() {
240        let raw_packet: [u8; 16] = [
241            0x12, 0x34, 0x00, 0x01, // Message ID
242            0x00, 0x00, 0x00, 0x00, // Length
243            0x01, 0x02, 0x00, 0x01, // Request ID
244            0x01, // Protocol Version
245            0x01, // Interface Version
246            0x00, // Message Type
247            0x00, // Return Code
248        ];
249
250        let packet = Packet::new_checked(&raw_packet[..]).unwrap();
251        let repr = Repr::parse(&packet).unwrap();
252
253        assert_eq!(
254            repr,
255            Repr {
256                message_id: MessageId {
257                    service_id: 0x1234,
258                    method_id: 0x0001,
259                },
260                length: 0,
261                request_id: RequestId {
262                    client_id: ClientId {
263                        client_id_prefix: 0x01,
264                        client_id: 0x02,
265                    },
266                    session_id: 0x0001,
267                },
268                protocol_version: 0x01,
269                interface_version: 0x01,
270                message_type: MessageType::Request,
271                return_code: ReturnCode::E_OK,
272                data: &[],
273            }
274        );
275    }
276
277    #[test]
278    fn test_repr_emit() {
279        let repr = Repr {
280            message_id: MessageId {
281                service_id: 0x1234,
282                method_id: 0x0001,
283            },
284            length: 4,
285            request_id: RequestId {
286                client_id: ClientId {
287                    client_id_prefix: 0x01,
288                    client_id: 0x02,
289                },
290                session_id: 0x0001,
291            },
292            protocol_version: 0x01,
293            interface_version: 0x01,
294            message_type: MessageType::Request,
295            return_code: ReturnCode::E_OK,
296            data: &[0xDE, 0xAD, 0xBE, 0xEF],
297        };
298        let mut buffer = [0u8; 20];
299        let mut packet = Packet::new_unchecked(&mut buffer);
300        repr.emit(&mut packet);
301        let expected: [u8; 20] = [
302            0x12, 0x34, 0x00, 0x01, // Message ID
303            0x00, 0x00, 0x00, 0x04, // Length
304            0x01, 0x02, 0x00, 0x01, // Request ID
305            0x01, // Protocol Version
306            0x01, // Interface Version
307            0x00, // Message Type
308            0x00, // Return Code
309            0xDE, 0xAD, 0xBE, 0xEF, // Payload
310        ];
311        assert_eq!(&buffer, &expected);
312    }
313
314    fn round_trip_test(repr: Repr) {
315        let mut buffer = [0u8; 1024];
316        {
317            let mut packet = Packet::new_unchecked(&mut buffer);
318            repr.emit(&mut packet);
319        }
320        let packet = Packet::new_checked(&buffer).unwrap();
321        let parsed_repr = Repr::parse(&packet).unwrap();
322        assert_eq!(parsed_repr, repr);
323    }
324
325    fn round_trip_test_with_bytes(repr: Repr, expected_bytes: &[u8]) {
326        let mut buffer = [0u8; 1024]; // Use a large enough fixed-size buffer
327        {
328            let mut packet = Packet::new_unchecked(&mut buffer[..expected_bytes.len()]);
329            repr.emit(&mut packet);
330        }
331
332        assert_eq!(&buffer[..expected_bytes.len()], expected_bytes);
333
334        let packet = Packet::new_checked(&buffer[..expected_bytes.len()]).unwrap();
335        let parsed_repr = Repr::parse(&packet).unwrap();
336        assert_eq!(repr, parsed_repr);
337    }
338
339    #[test]
340    fn test_repr_round_trip_request() {
341        let repr = Repr {
342            message_id: MessageId {
343                service_id: 0x1234,
344                method_id: 0x0001,
345            },
346            length: 4,
347            request_id: RequestId {
348                client_id: ClientId {
349                    client_id_prefix: 0x01,
350                    client_id: 0x02,
351                },
352                session_id: 0x0001,
353            },
354            protocol_version: 0x01,
355            interface_version: 0x01,
356            message_type: MessageType::Request,
357            return_code: ReturnCode::E_OK,
358            data: &[0xDE, 0xAD, 0xBE, 0xEF],
359        };
360        round_trip_test(repr);
361        round_trip_test_with_bytes(
362            repr,
363            &[
364                0x12, 0x34, // Service ID
365                0x00, 0x01, // Method ID
366                0x00, 0x00, 0x00, 0x04, // Length
367                0x01, 0x02, 0x00, 0x01, // Request ID
368                0x01, // Protocol version
369                0x01, // Interface version
370                0x00, // MessageType
371                0x00, // ReturnCode
372                0xDE, 0xAD, 0xBE, 0xEF, // Data
373            ],
374        );
375    }
376
377    #[test]
378    fn test_repr_round_trip_request_no_return() {
379        let repr = Repr {
380            message_id: MessageId {
381                service_id: 0x1234,
382                method_id: 0x0001,
383            },
384            length: 2,
385            request_id: RequestId {
386                client_id: ClientId {
387                    client_id_prefix: 0x01,
388                    client_id: 0x02,
389                },
390                session_id: 0x0001,
391            },
392            protocol_version: 0x01,
393            interface_version: 0x01,
394            message_type: MessageType::RequestNoReturn,
395            return_code: ReturnCode::E_OK,
396            data: &[0xAA, 0xBB],
397        };
398        round_trip_test(repr);
399    }
400
401    #[test]
402    fn test_repr_round_trip_notification() {
403        let repr = Repr {
404            message_id: MessageId {
405                service_id: 0x5678,
406                method_id: 0x8001,
407            },
408            length: 0,
409            request_id: RequestId {
410                client_id: ClientId {
411                    client_id_prefix: 0xFF,
412                    client_id: 0xFF,
413                },
414                session_id: 0x0001,
415            },
416            protocol_version: 0x01,
417            interface_version: 0x01,
418            message_type: MessageType::Notification,
419            return_code: ReturnCode::E_OK,
420            data: &[],
421        };
422        round_trip_test(repr);
423    }
424
425    #[test]
426    fn test_repr_round_trip_response() {
427        let repr = Repr {
428            message_id: MessageId {
429                service_id: 0x1234,
430                method_id: 0x0001,
431            },
432            length: 8,
433            request_id: RequestId {
434                client_id: ClientId {
435                    client_id_prefix: 0x01,
436                    client_id: 0x02,
437                },
438                session_id: 0x0001,
439            },
440            protocol_version: 0x01,
441            interface_version: 0x01,
442            message_type: MessageType::Response,
443            return_code: ReturnCode::E_OK,
444            data: &[0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77],
445        };
446        round_trip_test(repr);
447    }
448
449    #[test]
450    fn test_repr_round_trip_error() {
451        let repr = Repr {
452            message_id: MessageId {
453                service_id: 0x1234,
454                method_id: 0x0001,
455            },
456            length: 0,
457            request_id: RequestId {
458                client_id: ClientId {
459                    client_id_prefix: 0x01,
460                    client_id: 0x02,
461                },
462                session_id: 0x0001,
463            },
464            protocol_version: 0x01,
465            interface_version: 0x01,
466            message_type: MessageType::Error,
467            return_code: ReturnCode::E_NOT_OK,
468            data: &[],
469        };
470        round_trip_test(repr);
471    }
472
473    #[test]
474    fn test_repr_round_trip_tp_request() {
475        let repr = Repr {
476            message_id: MessageId {
477                service_id: 0xABCD,
478                method_id: 0x0042,
479            },
480            length: 1,
481            request_id: RequestId {
482                client_id: ClientId {
483                    client_id_prefix: 0x10,
484                    client_id: 0x20,
485                },
486                session_id: 0x1234,
487            },
488            protocol_version: 0x01,
489            interface_version: 0x02,
490            message_type: MessageType::TPRequest,
491            return_code: ReturnCode::E_OK,
492            data: &[0xFF],
493        };
494        round_trip_test(repr);
495    }
496
497    #[test]
498    fn test_repr_round_trip_tp_request_no_return() {
499        let repr = Repr {
500            message_id: MessageId {
501                service_id: 0x0001,
502                method_id: 0x0002,
503            },
504            length: 3,
505            request_id: RequestId {
506                client_id: ClientId {
507                    client_id_prefix: 0x00,
508                    client_id: 0x01,
509                },
510                session_id: 0x0002,
511            },
512            protocol_version: 0x01,
513            interface_version: 0x01,
514            message_type: MessageType::TPRequestNoReturn,
515            return_code: ReturnCode::E_OK,
516            data: &[0x01, 0x02, 0x03],
517        };
518        round_trip_test(repr);
519    }
520
521    #[test]
522    fn test_repr_round_trip_tp_notification() {
523        let repr = Repr {
524            message_id: MessageId {
525                service_id: 0x9999,
526                method_id: 0x8888,
527            },
528            length: 2,
529            request_id: RequestId {
530                client_id: ClientId {
531                    client_id_prefix: 0x00,
532                    client_id: 0x00,
533                },
534                session_id: 0x0000,
535            },
536            protocol_version: 0x01,
537            interface_version: 0x01,
538            message_type: MessageType::TPNotification,
539            return_code: ReturnCode::E_OK,
540            data: &[0xCA, 0xFE],
541        };
542        round_trip_test(repr);
543    }
544
545    #[test]
546    fn test_repr_round_trip_tp_response() {
547        let repr = Repr {
548            message_id: MessageId {
549                service_id: 0x4321,
550                method_id: 0x8765,
551            },
552            length: 5,
553            request_id: RequestId {
554                client_id: ClientId {
555                    client_id_prefix: 0xAA,
556                    client_id: 0xBB,
557                },
558                session_id: 0xCCDD,
559            },
560            protocol_version: 0x01,
561            interface_version: 0x05,
562            message_type: MessageType::TPResponse,
563            return_code: ReturnCode::E_OK,
564            data: &[0x10, 0x20, 0x30, 0x40, 0x50],
565        };
566        round_trip_test(repr);
567    }
568
569    #[test]
570    fn test_repr_round_trip_tp_error() {
571        let repr = Repr {
572            message_id: MessageId {
573                service_id: 0xFFFF,
574                method_id: 0xFFFF,
575            },
576            length: 0,
577            request_id: RequestId {
578                client_id: ClientId {
579                    client_id_prefix: 0xFF,
580                    client_id: 0xFE,
581                },
582                session_id: 0xFFFE,
583            },
584            protocol_version: 0x01,
585            interface_version: 0x01,
586            message_type: MessageType::TPError,
587            return_code: ReturnCode::E_TIMEOUT,
588            data: &[],
589        };
590        round_trip_test(repr);
591    }
592
593    // Return code tests
594    #[test]
595    fn test_repr_round_trip_unknown_service() {
596        let repr = Repr {
597            message_id: MessageId {
598                service_id: 0x1234,
599                method_id: 0x0001,
600            },
601            length: 0,
602            request_id: RequestId {
603                client_id: ClientId {
604                    client_id_prefix: 0x01,
605                    client_id: 0x02,
606                },
607                session_id: 0x0001,
608            },
609            protocol_version: 0x01,
610            interface_version: 0x01,
611            message_type: MessageType::Error,
612            return_code: ReturnCode::E_UNKNOWN_SERVICE,
613            data: &[],
614        };
615        round_trip_test(repr);
616    }
617
618    #[test]
619    fn test_repr_round_trip_unknown_method() {
620        let repr = Repr {
621            message_id: MessageId {
622                service_id: 0x1234,
623                method_id: 0x9999,
624            },
625            length: 0,
626            request_id: RequestId {
627                client_id: ClientId {
628                    client_id_prefix: 0x01,
629                    client_id: 0x02,
630                },
631                session_id: 0x0001,
632            },
633            protocol_version: 0x01,
634            interface_version: 0x01,
635            message_type: MessageType::Error,
636            return_code: ReturnCode::E_UNKNOWN_METHOD,
637            data: &[],
638        };
639        round_trip_test(repr);
640    }
641
642    #[test]
643    fn test_repr_round_trip_not_ready() {
644        let repr = Repr {
645            message_id: MessageId {
646                service_id: 0x1234,
647                method_id: 0x0001,
648            },
649            length: 0,
650            request_id: RequestId {
651                client_id: ClientId {
652                    client_id_prefix: 0x01,
653                    client_id: 0x02,
654                },
655                session_id: 0x0001,
656            },
657            protocol_version: 0x01,
658            interface_version: 0x01,
659            message_type: MessageType::Error,
660            return_code: ReturnCode::E_NOT_READY,
661            data: &[],
662        };
663        round_trip_test(repr);
664    }
665
666    #[test]
667    fn test_repr_round_trip_wrong_protocol_version() {
668        let repr = Repr {
669            message_id: MessageId {
670                service_id: 0x1234,
671                method_id: 0x0001,
672            },
673            length: 0,
674            request_id: RequestId {
675                client_id: ClientId {
676                    client_id_prefix: 0x01,
677                    client_id: 0x02,
678                },
679                session_id: 0x0001,
680            },
681            protocol_version: 0x01,
682            interface_version: 0x01,
683            message_type: MessageType::Error,
684            return_code: ReturnCode::E_WRONG_PROTOCOL_VERSION,
685            data: &[],
686        };
687        round_trip_test(repr);
688    }
689
690    #[test]
691    fn test_repr_round_trip_wrong_interface_version() {
692        let repr = Repr {
693            message_id: MessageId {
694                service_id: 0x1234,
695                method_id: 0x0001,
696            },
697            length: 0,
698            request_id: RequestId {
699                client_id: ClientId {
700                    client_id_prefix: 0x01,
701                    client_id: 0x02,
702                },
703                session_id: 0x0001,
704            },
705            protocol_version: 0x01,
706            interface_version: 0x01,
707            message_type: MessageType::Error,
708            return_code: ReturnCode::E_WRONG_INTERFACE_VERSION,
709            data: &[],
710        };
711        round_trip_test(repr);
712    }
713
714    #[test]
715    fn test_repr_round_trip_malformed_message() {
716        let repr = Repr {
717            message_id: MessageId {
718                service_id: 0x1234,
719                method_id: 0x0001,
720            },
721            length: 0,
722            request_id: RequestId {
723                client_id: ClientId {
724                    client_id_prefix: 0x01,
725                    client_id: 0x02,
726                },
727                session_id: 0x0001,
728            },
729            protocol_version: 0x01,
730            interface_version: 0x01,
731            message_type: MessageType::Error,
732            return_code: ReturnCode::E_MALFORMED_MESSAGE,
733            data: &[],
734        };
735        round_trip_test(repr);
736    }
737
738    #[test]
739    fn test_repr_round_trip_wrong_message_type() {
740        let repr = Repr {
741            message_id: MessageId {
742                service_id: 0x1234,
743                method_id: 0x0001,
744            },
745            length: 0,
746            request_id: RequestId {
747                client_id: ClientId {
748                    client_id_prefix: 0x01,
749                    client_id: 0x02,
750                },
751                session_id: 0x0001,
752            },
753            protocol_version: 0x01,
754            interface_version: 0x01,
755            message_type: MessageType::Error,
756            return_code: ReturnCode::E_WRONG_MESSAGE_TYPE,
757            data: &[],
758        };
759        round_trip_test(repr);
760    }
761
762    #[test]
763    fn test_repr_round_trip_e2e_errors() {
764        // Test E2E_REPEATED
765        let repr = Repr {
766            message_id: MessageId {
767                service_id: 0x1234,
768                method_id: 0x0001,
769            },
770            length: 0,
771            request_id: RequestId {
772                client_id: ClientId {
773                    client_id_prefix: 0x01,
774                    client_id: 0x02,
775                },
776                session_id: 0x0001,
777            },
778            protocol_version: 0x01,
779            interface_version: 0x01,
780            message_type: MessageType::Error,
781            return_code: ReturnCode::E_E2E_REPEATED,
782            data: &[],
783        };
784        round_trip_test(repr);
785
786        // Test E2E_WRONG_SEQUENCE
787        let repr = Repr {
788            return_code: ReturnCode::E_E2E_WRONG_SEQUENCE,
789            ..repr
790        };
791        round_trip_test(repr);
792
793        // Test E2E
794        let repr = Repr {
795            return_code: ReturnCode::E_E2E,
796            ..repr
797        };
798        round_trip_test(repr);
799
800        // Test E2E_NOT_AVAILABLE
801        let repr = Repr {
802            return_code: ReturnCode::E_E2E_NOT_AVAILABLE,
803            ..repr
804        };
805        round_trip_test(repr);
806
807        // Test E2E_NO_NEW_DATA
808        let repr = Repr {
809            return_code: ReturnCode::E_E2E_NO_NEW_DATA,
810            ..repr
811        };
812        round_trip_test(repr);
813    }
814
815    #[test]
816    fn test_repr_round_trip_reserved_someip_error() {
817        // Test reserved SOME/IP error range (0x10-0x1F)
818        let repr = Repr {
819            message_id: MessageId {
820                service_id: 0x1234,
821                method_id: 0x0001,
822            },
823            length: 0,
824            request_id: RequestId {
825                client_id: ClientId {
826                    client_id_prefix: 0x01,
827                    client_id: 0x02,
828                },
829                session_id: 0x0001,
830            },
831            protocol_version: 0x01,
832            interface_version: 0x01,
833            message_type: MessageType::Error,
834            return_code: ReturnCode::from_u8(0x10).unwrap(),
835            data: &[],
836        };
837        round_trip_test(repr);
838
839        let repr = Repr {
840            return_code: ReturnCode::from_u8(0x1F).unwrap(),
841            ..repr
842        };
843        round_trip_test(repr);
844    }
845
846    #[test]
847    fn test_repr_round_trip_service_method_error() {
848        // Test service/method specific error range (0x20-0x5E)
849        let repr = Repr {
850            message_id: MessageId {
851                service_id: 0x1234,
852                method_id: 0x0001,
853            },
854            length: 0,
855            request_id: RequestId {
856                client_id: ClientId {
857                    client_id_prefix: 0x01,
858                    client_id: 0x02,
859                },
860                session_id: 0x0001,
861            },
862            protocol_version: 0x01,
863            interface_version: 0x01,
864            message_type: MessageType::Error,
865            return_code: ReturnCode::from_u8(0x20).unwrap(),
866            data: &[],
867        };
868        round_trip_test(repr);
869
870        let repr = Repr {
871            return_code: ReturnCode::from_u8(0x42).unwrap(),
872            ..repr
873        };
874        round_trip_test(repr);
875
876        let repr = Repr {
877            return_code: ReturnCode::from_u8(0x5E).unwrap(),
878            ..repr
879        };
880        round_trip_test(repr);
881    }
882
883    #[test]
884    fn test_return_code_public_api() {
885        // Test named variants
886        let ok = ReturnCode::E_OK;
887        assert!(ok.is_ok());
888        assert!(!ok.is_reserved_someip());
889        assert!(!ok.is_reserved_service_method());
890        assert_eq!(ok.as_u8(), 0x00);
891
892        // Test reserved SOME/IP range
893        let reserved_someip = ReturnCode::ReservedSomeIP(0x15);
894        assert!(!reserved_someip.is_ok());
895        assert!(reserved_someip.is_reserved_someip());
896        assert!(!reserved_someip.is_reserved_service_method());
897        assert_eq!(reserved_someip.as_u8(), 0x15);
898
899        // Test reserved service/method range
900        let reserved_service = ReturnCode::ReservedServiceMethod(0x42);
901        assert!(!reserved_service.is_ok());
902        assert!(!reserved_service.is_reserved_someip());
903        assert!(reserved_service.is_reserved_service_method());
904        assert_eq!(reserved_service.as_u8(), 0x42);
905
906        // Test pattern matching
907        match ReturnCode::from_u8(0x10).unwrap() {
908            ReturnCode::ReservedSomeIP(code) => assert_eq!(code, 0x10),
909            _ => panic!("Expected ReservedSomeIP variant"),
910        }
911
912        match ReturnCode::from_u8(0x20).unwrap() {
913            ReturnCode::ReservedServiceMethod(code) => assert_eq!(code, 0x20),
914            _ => panic!("Expected ReservedServiceMethod variant"),
915        }
916
917        // Test conversions - Display trait exists but we're in no_std so skip format! tests
918        // The Display impl is tested implicitly when used with Repr
919    }
920}