1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! Invalid messages. This message type should be created out of two errors:
//! The SbpMsgParseError, & the CrcError. They correspond to two cases
//! 1) the Frame is invalid because either it either has an invalid CRC or
//! it is missing some metadata like msg_type or similar.
//! 2) The message is invalid because the payload is not large enough and cannot be
//! parsed into a message. This is the SbpMsgParseError.

use bytes::{Buf, BufMut};

use crate::{de::CrcError, messages::SbpMsgParseError, wire_format::WireFormat, SbpMessage};

/// Invalid messages occur when either the frame or message payload doesn't have enough bytes or
/// the CRC does not match the messages payload. If the message is well formed with a message
/// id and CRC and payload that all are consistent, but its message type is unknown, it should be
/// parsed into a Unknown message.
///
/// There is something unique about Invalid messages that the payload is actually the entire frame.
/// This is because it is possible to be able to create invalid messages from invalid frames, that
/// may not even contain a message payload.
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Invalid {
    /// The message id of the message.
    #[cfg_attr(feature = "serde", serde(default, skip_serializing))]
    pub msg_id: Option<u16>,
    /// The message sender_id.
    #[cfg_attr(feature = "serde", serde(default, skip_serializing, alias = "sender"))]
    pub sender_id: Option<u16>,
    /// The crc that was in the frame
    #[cfg_attr(feature = "serde", serde(default, skip_serializing))]
    pub crc: Option<u16>,
    #[cfg_attr(feature = "serde", serde(default, skip))]
    pub invalid_frame: Vec<u8>,
}

impl SbpMessage for Invalid {
    fn message_name(&self) -> &'static str {
        "INVALID"
    }

    fn message_type(&self) -> Option<u16> {
        self.msg_id
    }

    fn sender_id(&self) -> Option<u16> {
        self.sender_id
    }

    fn set_sender_id(&mut self, new_id: u16) {
        self.sender_id = Some(new_id);
    }

    fn encoded_len(&self) -> usize {
        // note here we don't add the header and crc etc because the
        // invalid message holds the entire frame in
        // its payload
        WireFormat::len(self)
    }
    fn is_valid(&self) -> bool {
        // Invalid messages can never be valid
        false
    }
    fn into_valid_msg(self) -> Result<Self, Self> {
        // Invalid messages can never be valid
        Err(self)
    }
}

impl WireFormat for Invalid {
    /// because this is an invalid message, the length may disagree
    /// with what you would expect from parsing the frame itself
    fn len(&self) -> usize {
        self.invalid_frame.len()
    }

    fn write<B: BufMut>(&self, buf: &mut B) {
        self.invalid_frame.write(buf)
    }

    /// In general it is better to construct invalid messages
    /// from thrown errors, not to directly parse to them
    fn parse_unchecked<B: Buf>(buf: &mut B) -> Self {
        Invalid {
            msg_id: None,
            sender_id: None,
            crc: None,
            invalid_frame: WireFormat::parse_unchecked(buf),
        }
    }
}

impl From<SbpMsgParseError> for Invalid {
    fn from(
        SbpMsgParseError {
            msg_type,
            sender_id,
            invalid_payload: msg_payload,
        }: SbpMsgParseError,
    ) -> Self {
        // payload here is the whole frame
        let mut payload =
            Vec::with_capacity(msg_payload.len() + crate::HEADER_LEN + crate::CRC_LEN);
        crate::PREAMBLE.write(&mut payload);
        msg_type.write(&mut payload);
        sender_id.write(&mut payload);
        (msg_payload.len() as u8).write(&mut payload);
        msg_payload.write(&mut payload);
        let crc =
            crc16::State::<crc16::XMODEM>::calculate(payload.get(1..).expect("vec has capacity"));
        crc.write(&mut payload);

        Self {
            msg_id: Some(msg_type),
            sender_id: Some(sender_id),
            invalid_frame: payload,
            crc: Some(crc),
        }
    }
}

impl From<CrcError> for Invalid {
    fn from(
        CrcError {
            msg_type,
            sender_id,
            invalid_frame,
            crc,
        }: CrcError,
    ) -> Self {
        Self {
            msg_id: msg_type,
            sender_id,
            invalid_frame,
            crc,
        }
    }
}