bluerobotics_ping/
codec.rs

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