bluerobotics_ping/
codec.rs

1use crate::{decoder::Decoder as PingDecoder, error::PingError, message::ProtocolMessage};
2use bytes::{Buf, BytesMut};
3use tokio_util::codec::{Decoder, Encoder};
4
5pub struct PingCodec {
6    decoder: PingDecoder,
7}
8
9impl PingCodec {
10    pub fn new() -> Self {
11        PingCodec {
12            decoder: PingDecoder::new(),
13        }
14    }
15}
16
17impl Decoder for PingCodec {
18    type Item = ProtocolMessage;
19    type Error = PingError;
20
21    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
22        let decoder = &mut self.decoder;
23        let mut consumed = 0;
24
25        loop {
26            let Some(byte) = src.get(consumed) else {
27                return Ok(None);
28            };
29
30            match decoder.parse_byte(*byte) {
31                crate::decoder::DecoderResult::InProgress => {
32                    consumed += 1;
33                    if consumed == src.len() {
34                        src.advance(consumed)
35                    }
36                }
37                crate::decoder::DecoderResult::Success(msg) => {
38                    src.advance(consumed + 1);
39                    return Ok(Some(msg));
40                }
41                crate::decoder::DecoderResult::Error(e) => {
42                    src.advance(consumed + 1);
43                    return Err(PingError::ParseError(e));
44                }
45            }
46        }
47    }
48}
49
50impl Encoder<ProtocolMessage> for PingCodec {
51    type Error = PingError;
52
53    fn encode(&mut self, item: ProtocolMessage, dst: &mut BytesMut) -> Result<(), Self::Error> {
54        dst.extend_from_slice(&item.serialized());
55        Ok(())
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62    use crate::common;
63
64    #[test]
65    fn test_ping_codec() {
66        let mut codec = PingCodec::new();
67
68        // Define GeneralRequest Buffer
69        let buffer: Vec<u8> = vec![
70            0x42, 0x52, 0x02, 0x00, // payload length
71            0x06, 0x00, // message id
72            0x00, 0x00, // src and dst id
73            0x05, 0x00, // payload
74            0xa1, 0x00, // crc
75        ];
76        let mut bytes_mut = BytesMut::new();
77        bytes_mut.extend_from_slice(&buffer);
78
79        // Define equivalent ProtocolMessage
80        let request =
81            common::Messages::GeneralRequest(common::GeneralRequestStruct { requested_id: 5 });
82        let mut package = crate::message::ProtocolMessage::new();
83        package.set_message(&request);
84
85        // Decode the buffer
86        let decoded_message = codec.decode(&mut bytes_mut).unwrap().unwrap();
87
88        // Assert that the decoded message matches the expected PingMessage
89        assert_eq!(decoded_message, package);
90
91        // Re-test with a wrong CRC
92        let wrong_buffer: Vec<u8> = vec![
93            0x42, 0x52, 0x02, 0x00, // payload length
94            0x06, 0x00, // message id
95            0x00, 0x00, // src and dst id
96            0x05, 0x00, // payload
97            0xa1, 0x01, // wrong crc
98        ];
99        let mut wrong_bytes_mut = BytesMut::new();
100        wrong_bytes_mut.extend_from_slice(&wrong_buffer);
101
102        // Decode the buffer and test ParseError
103        let decoded_message = codec.decode(&mut wrong_bytes_mut);
104
105        assert!(matches!(decoded_message, Err(PingError::ParseError(_))));
106
107        let mut encoded = BytesMut::new();
108        codec.encode(package.clone(), &mut encoded).unwrap();
109
110        // Assert that the encoded bytes match the original buffer
111        assert_eq!(encoded.to_vec(), buffer);
112    }
113}