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}