pamoja_mavlink/error.rs
1//! The error model for the MAVLink wire layer.
2//!
3//! A single [`MavlinkError`] keeps framing, checksum, and signing faults uniform, the
4//! way [`pamoja-modbus`](https://docs.rs/pamoja-modbus) and
5//! [`pamoja-lorawan`](https://docs.rs/pamoja-lorawan) each carry their own protocol
6//! error type ahead of the transport layer.
7
8use core::fmt;
9
10/// A fault encountered while building, parsing, signing, or verifying a frame.
11///
12/// This enum is `#[non_exhaustive]`: new variants may be added without a breaking
13/// change, so a downstream `match` must include a wildcard arm.
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15#[non_exhaustive]
16pub enum MavlinkError {
17 /// The bytes are shorter than the smallest valid frame of their version.
18 FrameTooShort,
19
20 /// The first byte is neither the v1 (`0xFE`) nor the v2 (`0xFD`) start marker.
21 BadMagic(u8),
22
23 /// The buffer ended before the frame its length field promised was complete.
24 Truncated,
25
26 /// The trailing checksum did not match the one computed over the frame.
27 CrcMismatch {
28 /// The checksum computed over the received bytes.
29 expected: u16,
30 /// The checksum the frame carried.
31 found: u16,
32 },
33
34 /// A message id has no known `CRC_EXTRA`, so its checksum cannot be validated and
35 /// its payload cannot be decoded.
36 UnknownMessage(u32),
37
38 /// A payload, frame, or field array was larger than the protocol or buffer allows.
39 PayloadTooLong,
40
41 /// A signature was required but the frame was not signed.
42 Unsigned,
43
44 /// The frame's signature did not match the one computed with the key.
45 BadSignature,
46
47 /// The frame's signing timestamp was older than the link's replay window allows.
48 ReplayedTimestamp,
49
50 /// A typed message was decoded from a payload of the wrong size or shape.
51 BadPayload,
52
53 /// The message has no field of the requested name.
54 UnknownField,
55
56 /// A field type name is not one MAVLink defines.
57 UnknownFieldType,
58
59 /// A message shape names the same field twice.
60 DuplicateField,
61
62 /// A field was read or written as a kind its type is not.
63 FieldTypeMismatch,
64
65 /// An array element index is past the end of the field.
66 FieldIndexOutOfRange,
67
68 /// A value does not fit the field's type.
69 ValueOutOfRange,
70
71 /// The link reached end of input before a frame could be read.
72 Closed,
73}
74
75impl fmt::Display for MavlinkError {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 match self {
78 Self::FrameTooShort => f.write_str("frame is shorter than a valid frame"),
79 Self::BadMagic(byte) => write!(f, "unrecognized start marker: {byte:#04x}"),
80 Self::Truncated => f.write_str("frame is shorter than its length field promises"),
81 Self::CrcMismatch { expected, found } => {
82 write!(
83 f,
84 "checksum mismatch: expected {expected:#06x}, found {found:#06x}"
85 )
86 }
87 Self::UnknownMessage(id) => write!(f, "no CRC_EXTRA known for message id {id}"),
88 Self::PayloadTooLong => f.write_str("payload exceeds the maximum frame size"),
89 Self::Unsigned => f.write_str("frame is not signed"),
90 Self::BadSignature => f.write_str("signature does not verify"),
91 Self::ReplayedTimestamp => f.write_str("signing timestamp is too old"),
92 Self::BadPayload => f.write_str("payload does not match the message layout"),
93 Self::UnknownField => f.write_str("message has no field of that name"),
94 Self::UnknownFieldType => f.write_str("unrecognized MAVLink field type"),
95 Self::DuplicateField => f.write_str("message names the same field twice"),
96 Self::FieldTypeMismatch => f.write_str("field is not of the requested kind"),
97 Self::FieldIndexOutOfRange => f.write_str("array index is past the end of the field"),
98 Self::ValueOutOfRange => f.write_str("value does not fit the field type"),
99 Self::Closed => f.write_str("link reached end of input"),
100 }
101 }
102}
103
104#[cfg(feature = "std")]
105impl std::error::Error for MavlinkError {}
106
107/// A specialized [`core::result::Result`] whose error type is [`MavlinkError`].
108pub type Result<T> = core::result::Result<T, MavlinkError>;