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 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
//! # Errors
//!
//! These errors used in `mavio`.
//!
//! The top-level error is [`Error`]. Library API returns versions of this error possibly wrapping
//! other types of errors.
//!
//! We also re-export errors from [`mavspec::rust::spec`](https://docs.rs/mavspec/latest/mavspec/rust/spec/)
//! to provide a full specification of MAVLink-related errors.
#[cfg(feature = "std")]
use std::sync::Arc;
use crate::protocol::{IncompatFlags, MavLinkVersion, MessageId};
/// <sup>[`mavspec`](https://crates.io/crates/mavspec)</sup>
/// Errors related to MAVLink message specification.
///
/// Upon conversion into Mavio [`Error`], this error will be wrapped by [`Error::Spec`], except
/// [`SpecError::NotInDialect`], that will be converted into [`FrameError::NotInDialect`] and
/// wrapped by [`Error::Frame`].
///
/// ---
#[doc(inline)]
pub use mavspec::rust::spec::SpecError;
/// Common result type returned by `mavio` functions and methods.
pub type Result<T> = core::result::Result<T, Error>;
/// `mavio` top-level error.
///
/// Returned by most of the functions and methods across `mavio`. Other errors are either
/// converted to this error or wrapped by its variants.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
pub enum Error {
/// [`std::io::Error`] wrapper.
#[cfg(feature = "std")]
#[cfg_attr(feature = "std", error("I/O error: {0:?}"))]
Io(Arc<std::io::Error>),
/// `no_std` I/O error.
///
/// Wraps [`IoError`](crate::io::no_std::IoError).
#[cfg(not(feature = "std"))]
Io(crate::io::no_std::IoError),
/// Frame validation errors.
#[cfg_attr(feature = "std", error("frame decoding/encoding error: {0:?}"))]
Frame(FrameError),
/// MAVLink specification errors. A wrapper for [`SpecError`] re-exported from MAVSpec.
#[cfg_attr(feature = "std", error("frame decoding/encoding error: {0:?}"))]
Spec(SpecError),
}
/// Errors related to MAVLink frame validation.
///
/// This means, that frame is already present but hasn't passed certain criteria.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
pub enum FrameError {
/// Incorrect MAVLink version.
#[cfg_attr(feature = "std", error("invalid MAVLink version: {0:?}"))]
Version(VersionError),
/// Upon calculation, CRC does not match received [Frame::checksum](crate::Frame::checksum).
#[cfg_attr(feature = "std", error("checksum validation failed"))]
Checksum,
/// Upon validation, the [Frame::signature](crate::Frame::signature) found to be incorrect.
#[cfg_attr(feature = "std", error("signature validation failed"))]
Signature,
/// Upon validation, the [Frame::incompat_flags](crate::Frame::incompat_flags) do not match the
/// required flag set.
#[cfg_attr(feature = "std", error("invalid incompat flags: {0:?}"))]
Incompatible(IncompatFlagsError),
/// MAVLink message with specified ID is not in dialect.
#[cfg_attr(feature = "std", error("message with ID {0:?} is not in dialect"))]
NotInDialect(MessageId),
}
/// Invalid MAVLink version.
///
/// Can be converted to [`FrameError::Version`].
#[derive(Copy, Clone, Debug)]
pub struct VersionError {
/// Expected protocol version.
pub expected: MavLinkVersion,
/// Actual protocol version.
pub actual: MavLinkVersion,
}
/// Invalid frame checksum.
///
/// Can be converted to [`FrameError::Checksum`].
pub struct ChecksumError;
/// Invalid frame signature.
///
/// Can be converted to [`FrameError::Signature`].
pub struct SignatureError;
/// Invalid incompatibility flags.
///
/// Can be converted to [`FrameError::Incompatible`].
#[derive(Copy, Clone, Debug)]
pub struct IncompatFlagsError {
/// Expected flag set.
pub expected: IncompatFlags,
/// Actual flag set.
pub actual: IncompatFlags,
}
impl From<VersionError> for FrameError {
/// Converts [`VersionError`] into [`FrameError::Version`].
fn from(value: VersionError) -> Self {
Self::Version(value)
}
}
impl From<VersionError> for Error {
/// Converts [`VersionError`] into [`FrameError::Version`] variant of [`Error::Frame`].
fn from(value: VersionError) -> Self {
FrameError::from(value).into()
}
}
impl From<ChecksumError> for FrameError {
/// Converts [`ChecksumError`] into [`FrameError::Checksum`].
fn from(_: ChecksumError) -> Self {
Self::Checksum
}
}
impl From<ChecksumError> for Error {
/// Converts [`ChecksumError`] into [`FrameError::Checksum`] variant of [`Error::Frame`].
fn from(value: ChecksumError) -> Self {
FrameError::from(value).into()
}
}
impl From<SignatureError> for FrameError {
/// Converts [`SignatureError`] into [`FrameError::Signature`].
fn from(_: SignatureError) -> Self {
Self::Signature
}
}
impl From<SignatureError> for Error {
/// Converts [`SignatureError`] into [`FrameError::Signature`] variant of [`Error::Frame`].
fn from(value: SignatureError) -> Self {
FrameError::from(value).into()
}
}
impl From<IncompatFlagsError> for FrameError {
/// Converts [`IncompatFlagsError`] into [`FrameError::Incompatible`].
fn from(value: IncompatFlagsError) -> Self {
Self::Incompatible(value)
}
}
impl From<IncompatFlagsError> for Error {
/// Converts [`IncompatFlagsError`] into [`FrameError::Incompatible`] variant of [`Error::Frame`].
fn from(value: IncompatFlagsError) -> Self {
FrameError::from(value).into()
}
}
#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
/// Convert [`std::io::Error`] into [`Error::Io`].
///
/// Note that [`Error::Io`] wraps IO error with [`Arc`] to make [`Error`] compatible with [`Clone`] trait.
fn from(value: std::io::Error) -> Self {
Error::Io(Arc::new(value))
}
}
impl From<FrameError> for Error {
/// Converts [`FrameError`] into [`Error::Frame`].
fn from(value: FrameError) -> Self {
Self::Frame(value)
}
}
impl From<SpecError> for Error {
/// Converts [`SpecError`] into [`Error::Spec`].
///
/// There is a special case for [`SpecError::NotInDialect`], that will be converted to
/// [`FrameError::NotInDialect`] variant of [`Error::Frame`].
fn from(value: SpecError) -> Self {
if let SpecError::NotInDialect(id) = value {
Error::Frame(FrameError::NotInDialect(id))
} else {
Self::Spec(value)
}
}
}