Skip to main content

protobin/decode/
msg_decoder.rs

1use crate::{decode::*, wire::*, *};
2
3#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
4pub struct MsgDecoder<'a> {
5    pub wire_decoder: WireDecoder<'a>,
6}
7
8impl<'a> MsgDecoder<'a> {
9    pub fn new(data: &'a [u8]) -> MsgDecoder<'a> {
10        MsgDecoder {
11            wire_decoder: WireDecoder { data },
12        }
13    }
14
15    fn next_inner(&mut self) -> Result<MsgRecordRef<'a>, DecodeError> {
16        // read field number & tag
17        let tag = self.wire_decoder.read_var_uint32()?;
18        let field_number = FieldNumber(tag >> 3);
19        let wire_type = tag & 0b111;
20        let value = match wire_type {
21            // VARINT
22            0 => WireValueRef::VarInt(WireVarInt::from_raw(self.wire_decoder.read_var_uint64()?)),
23            // I64
24            1 => WireValueRef::I64(WireI64(self.wire_decoder.read_fixed64()?)),
25            // LEN
26            2 => {
27                let len: usize = self.wire_decoder.read_var_uint32()? as usize;
28                let data = self.wire_decoder.take_nbyte(len)?;
29                WireValueRef::Len(WireLenRef { data })
30            }
31            // SGROUP
32            3 => WireValueRef::SGroup,
33            // EGROUP
34            4 => WireValueRef::EGroup,
35            // I32
36            5 => WireValueRef::I32(WireI32(self.wire_decoder.read_fixed32()?)),
37            unknown => {
38                return Err(DecodeError::UnknownWireType(unknown));
39            }
40        };
41        Ok(MsgRecordRef {
42            field_number,
43            value,
44        })
45    }
46}
47
48impl<'a> Iterator for MsgDecoder<'a> {
49    type Item = Result<MsgRecordRef<'a>, DecodeError>;
50
51    /// Returns the next message record or TLV (Tag-Length-Value) until
52    /// an error is encountered or no more data is present.
53    ///
54    /// In case an error is encountered the error is returned and in the following
55    /// call `None`.
56    fn next(&mut self) -> Option<Result<MsgRecordRef<'a>, DecodeError>> {
57        if self.wire_decoder.data.is_empty() {
58            return None;
59        }
60        match self.next_inner() {
61            Err(err) => {
62                // invalidate the wire decoder so we don't trigger an error in
63                // an infinite loop
64                self.wire_decoder.data = &[];
65                Some(Err(err))
66            }
67            other => Some(other),
68        }
69    }
70}