doip_codec/
lib.rs

1#![warn(missing_docs)]
2
3//! # Diagnostics over Internet Protocol Codec Crate
4//!
5//! The purpose of this crate is to provide an easy way to encode and decode
6//! DoIP Messages defined in the `doip-definitions` crate.
7//!
8//! ## Example Usage
9//! ```no_run
10//! use futures::{SinkExt, StreamExt};
11//! use tokio::net::TcpStream;
12//! use tokio_util::codec::Framed;
13//! use doip_definitions::{
14//!     header::DoipVersion,
15//!     message::{DoipMessage, VehicleIdentificationRequest},
16//! };
17//! use doip_codec::DoipCodec;
18//!
19//! #[tokio::main]
20//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
21//!   // Connect to a DoIP server
22//!   let stream = TcpStream::connect("127.0.0.1:13400").await?;
23//!
24//!   // Wrap the stream with the DoipCodec
25//!   let mut framed = Framed::new(stream, DoipCodec);
26//!
27//!   // Send a DoIP message
28//!   let request = DoipMessage::new(
29//!       DoipVersion::Iso13400_2012,
30//!       Box::new(VehicleIdentificationRequest {}),
31//!   ); // Example payload
32//!
33//!   framed.send(request).await?;
34//!
35//!   // Receive a DoIP message
36//!   if let Some(response) = framed.next().await {
37//!       match response {
38//!           Ok(msg) => println!("Received message: {:?}", msg),
39//!           Err(e) => eprintln!("Failed to decode message: {}", e),
40//!       }
41//!   }
42//!
43//!   Ok(())
44//! }
45//! ```
46//!
47
48mod decoder;
49mod encoder;
50mod error;
51pub use crate::error::*;
52
53/// A simple Decoder and Encoder implementation for Diagnostics over Internet
54/// Protocol.
55///
56/// Can be used independently via `encode` and `decode` methods, however is best
57/// utilised during.
58#[derive(Debug)]
59pub struct DoipCodec;
60
61#[cfg(test)]
62mod tests {
63    use doip_definitions::{
64        header::DoipVersion,
65        message::{DoipMessage, VehicleIdentificationRequest},
66    };
67    use tokio_util::codec::{FramedRead, FramedWrite};
68
69    use crate::DoipCodec;
70
71    #[tokio::test]
72    async fn test_framed_write() {
73        use futures::sink::SinkExt;
74
75        let buffer = Vec::new();
76
77        let item_1 = DoipMessage::new(
78            DoipVersion::Iso13400_2012,
79            Box::new(VehicleIdentificationRequest {}),
80        );
81
82        let item_2 = DoipMessage::new(
83            DoipVersion::Iso13400_2012,
84            Box::new(VehicleIdentificationRequest {}),
85        );
86        let encoder = DoipCodec;
87
88        let mut writer = FramedWrite::new(buffer, encoder);
89
90        writer.send(item_1).await.unwrap();
91        writer.send(item_2).await.unwrap();
92
93        let buffer = writer.get_ref();
94
95        assert_eq!(
96            buffer.as_slice(),
97            [
98                0x02, 0xfd, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0x00, 0x01, 0x00, 0x00,
99                0x00, 0x00
100            ]
101        );
102    }
103
104    #[tokio::test]
105    async fn test_framed_read() {
106        use futures::StreamExt;
107
108        let bytes = vec![
109            0x02, 0xfd, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0x00, 0x01, 0x00, 0x00,
110            0x00, 0x00,
111        ];
112        let decoder = DoipCodec;
113
114        let mut reader = FramedRead::new(bytes.as_slice(), decoder);
115
116        let frame_1 = reader.next().await.unwrap().unwrap();
117        let frame_2 = reader.next().await.unwrap().unwrap();
118
119        assert!(reader.next().await.is_none());
120
121        assert_eq!(
122            frame_1.header,
123            DoipMessage::new(
124                DoipVersion::Iso13400_2012,
125                Box::new(VehicleIdentificationRequest {}),
126            )
127            .header
128        );
129
130        assert_eq!(
131            frame_2.header,
132            DoipMessage::new(
133                DoipVersion::Iso13400_2012,
134                Box::new(VehicleIdentificationRequest {}),
135            )
136            .header
137        );
138    }
139}