doip_codec/
decoder.rs

1use doip_definitions::message::DoipMessage;
2use tokio_util::bytes::{Buf, BytesMut};
3
4use crate::{error::DecodeError, DoipCodec};
5
6pub const MAX: usize = 8 * 1024 * 1024;
7
8impl tokio_util::codec::Decoder for DoipCodec {
9    type Item = DoipMessage;
10    type Error = DecodeError;
11
12    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
13        if src.is_empty() {
14            return Ok(None);
15        };
16        if src.len() > MAX {
17            return Err(DecodeError::IoError(std::io::Error::new(
18                std::io::ErrorKind::InvalidData,
19                format!("Frame of length {} is too large.", src.len()),
20            )));
21        }
22
23        let data = src[..src.len()].to_vec();
24
25        match DoipMessage::parse_from_bytes(data) {
26            Ok(msg) => {
27                src.advance(msg.header.payload_length as usize + 8);
28                Ok(Some(msg))
29            }
30            Err(err) => Err(DecodeError::ParseError(err)),
31        }
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use crate::DoipCodec;
38    use doip_definitions::{
39        header::{DoipHeader, DoipVersion, PayloadType},
40        message::DoipMessage,
41    };
42    use tokio_util::{bytes::BytesMut, codec::Decoder};
43
44    #[test]
45    fn test_decode_single_message() {
46        let mut decoder = DoipCodec {};
47        let mut bytes = BytesMut::new();
48
49        let src = [0x02, 0xfd, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00];
50        bytes.extend_from_slice(&src);
51
52        let msg = decoder.decode(&mut bytes);
53        assert!(msg.is_ok(), "Expected to receive a result.");
54
55        assert!(
56            msg.as_ref().unwrap().is_some(),
57            "Expected to receive a defined message."
58        );
59
60        let res = msg.unwrap().unwrap();
61        let payload_type = (&*res.payload).payload_type();
62        let payload_len = (&*res.payload).to_bytes().len();
63
64        assert_eq!(
65            res.header,
66            DoipHeader {
67                protocol_version: DoipVersion::Iso13400_2012,
68                inverse_protocol_version: 0xfd,
69                payload_type: PayloadType::VehicleIdentificationRequest,
70                payload_length: 0
71            },
72            "Unexpected message: {:?}",
73            res
74        );
75
76        assert_eq!(
77            payload_type,
78            PayloadType::VehicleIdentificationRequest,
79            "Unexpected payload: {:?}",
80            payload_type
81        );
82
83        assert_eq!(payload_len, 0, "Unexpected payload: {:?}", payload_len);
84    }
85
86    #[test]
87    fn test_decode_single_message_short() {
88        let mut decoder = DoipCodec {};
89        let mut bytes = BytesMut::new();
90
91        let src = [0x02, 0xfd, 0x00, 0x01, 0x00, 0x00, 0x00];
92        bytes.extend_from_slice(&src);
93
94        let msg = decoder.decode(&mut bytes);
95
96        assert!(
97            msg.is_err(),
98            "Expected to receive an Err(ParseError::IndexFailure)."
99        );
100    }
101
102    #[test]
103    fn test_decode_many_message() {
104        let mut decoder = DoipCodec {};
105        let mut bytes = BytesMut::new();
106        let number_of_messages: usize = 30;
107
108        let src = [0x02, 0xfd, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00].repeat(number_of_messages);
109        bytes.extend_from_slice(&src);
110
111        let mut messages: Vec<DoipMessage> = vec![];
112
113        while bytes.len() >= 8 {
114            let msg = decoder.decode(&mut bytes).unwrap();
115
116            let _ = match msg {
117                Some(msg) => messages.push(msg),
118                None => continue,
119            };
120        }
121
122        assert_eq!(
123            messages.len(),
124            number_of_messages,
125            "Unexpected messages: {:?}",
126            messages
127        );
128    }
129}