mini_rxtx/
decoder.rs

1use byteorder::ByteOrder;
2
3pub enum Decoded<T> {
4    Msg(T),
5    FrameNotYetComplete,
6    Error(crate::Error),
7}
8
9#[cfg(feature = "std")]
10use log::trace;
11
12/// A struct for decoding bytes.
13///
14/// This is similar to `Decoder` but uses `std` to allocate a buffer.
15///
16/// This is not part of the `MiniTxRx` struct itself because we do not want to
17/// require access to resources when decoding bytes.
18#[cfg(feature = "std")]
19pub struct StdDecoder {
20    buf: Vec<u8>,
21    state: FramedReaderState,
22}
23
24#[cfg(feature = "std")]
25impl StdDecoder {
26    pub fn new(sz: usize) -> Self {
27        Self {
28            buf: vec![0; sz],
29            state: FramedReaderState::Empty,
30        }
31    }
32
33    pub fn consume<T>(&mut self, byte: u8) -> Decoded<T>
34    where
35        for<'de> T: serde::de::Deserialize<'de>,
36    {
37        let (new_state, decoded) = consume_inner(&mut self.state, &mut self.buf, byte);
38        self.state = new_state;
39        decoded
40    }
41}
42
43/// A struct for decoding bytes.
44///
45/// This is not part of the `MiniTxRx` struct itself because we do not want to
46/// require access to resources when decoding bytes.
47pub struct Decoder<'a> {
48    buf: &'a mut [u8],
49    state: FramedReaderState,
50}
51
52impl<'a> Decoder<'a> {
53    pub fn new(buf: &'a mut [u8]) -> Self {
54        Self {
55            buf,
56            state: FramedReaderState::Empty,
57        }
58    }
59
60    pub fn consume<T>(&mut self, byte: u8) -> Decoded<T>
61    where
62        for<'de> T: serde::de::Deserialize<'de>,
63    {
64        let (new_state, decoded) = consume_inner(&mut self.state, &mut self.buf, byte);
65        self.state = new_state;
66        decoded
67    }
68}
69
70#[inline]
71fn consume_inner<T>(
72    self_state: &mut FramedReaderState,
73    self_buf: &mut [u8],
74    byte: u8,
75) -> (FramedReaderState, Decoded<T>)
76where
77    for<'de> T: serde::de::Deserialize<'de>,
78{
79    let (new_state, result) = match self_state {
80        FramedReaderState::Empty => (FramedReaderState::ReadingHeader(byte), Ok(None)),
81        FramedReaderState::ReadingHeader(byte0) => {
82            let buf: [u8; 2] = [*byte0, byte];
83            let len = ::byteorder::LittleEndian::read_u16(&buf);
84            if (len as usize) > self_buf.len() {
85                (FramedReaderState::Error, Err(crate::Error::TooLong))
86            } else {
87                if len == 0 {
88                    let result: &[u8] = b""; // 0 length slice of u8
89                    (FramedReaderState::Empty, Ok(Some(result)))
90                } else {
91                    #[cfg(feature = "std")]
92                    trace!("starting new message with length {}", len);
93                    let rms = ReadingMessageState { len: len, idx: 0 };
94                    (FramedReaderState::ReadingMessage(rms), Ok(None))
95                }
96            }
97        }
98        FramedReaderState::ReadingMessage(ref rms) => {
99            let (msg_len, mut idx) = (rms.len, rms.idx);
100            self_buf[idx as usize] = byte;
101            idx += 1;
102            if idx < msg_len {
103                #[cfg(feature = "std")]
104                trace!("got byte in message with length {}", msg_len);
105                let rms = ReadingMessageState { len: msg_len, idx };
106                (FramedReaderState::ReadingMessage(rms), Ok(None))
107            } else if idx == msg_len {
108                #[cfg(feature = "std")]
109                trace!("completed message with length {}", msg_len);
110                let result = &self_buf[0..(idx as usize)];
111                (FramedReaderState::Empty, Ok(Some(result)))
112            } else {
113                // Frame langer than expected.
114                // Theoretically it is impossible to get here, so we panic.
115                panic!("frame larger than expected");
116            }
117        }
118        FramedReaderState::Error => (FramedReaderState::Error, Err(crate::Error::PreviousError)),
119    };
120    let decoded = match result {
121        Ok(Some(buf)) => match ssmarshal::deserialize(buf) {
122            Ok((msg, _nbytes)) => Decoded::Msg(msg),
123            Err(e) => Decoded::Error(e.into()),
124        },
125        Ok(None) => Decoded::FrameNotYetComplete,
126        Err(e) => Decoded::Error(e),
127    };
128    (new_state, decoded)
129}
130
131struct ReadingMessageState {
132    len: u16, // the length when full
133    idx: u16, // the current length
134}
135
136enum FramedReaderState {
137    Empty,
138    ReadingHeader(u8),
139    ReadingMessage(ReadingMessageState),
140    Error,
141}