mavspec_rust_spec 0.6.7

Core interfaces for MAVSpec's Rust code generation toolchain.
Documentation
//! # MAVLink message

use crate::consts::MESSAGE_ID_V1_MAX;
use crate::payload::IntoPayload;
use crate::types::{CrcExtra, MavLinkVersion, MessageId};

/// Generic MAVLink message specification.
///
/// [`MessageInfo`] implements this trait.
///
/// Messages generated by [MAVSpec](https://gitlab.com/mavka/libs/mavspec) also implement this trait.
pub trait MessageSpec {
    /// MAVLink message ID.
    ///
    /// In `MAVLink 2` message ID is a 24-bit unsigned integer stored as [`u32`].
    ///
    /// `MAVLink 1` supports only 8-bit message ID.
    ///
    /// # Links
    ///
    ///  - [MAVLink 2](https://mavlink.io/en/guide/mavlink_2.html)
    ///  - [MAVLink serialization](https://mavlink.io/en/guide/serialization.html)
    fn id(&self) -> MessageId;

    /// Minimum supported MAVLink protocol version.
    ///
    /// Messages supporting both `MAVLink 1` and `MAVLink 2` will return [`MavLinkVersion::V1`].
    ///
    /// Messages which make sense only in `MAVLink 2` will return [`MavLinkVersion::V2`],
    fn min_supported_mavlink_version(&self) -> MavLinkVersion;

    /// Message `EXTRA_CRC` calculated from message XML definition.
    ///
    /// CRC for message name and key message fields to detect incompatible changes in
    /// message definition.
    ///
    /// See: [CRC_EXTRA calculation](https://mavlink.io/en/guide/serialization.html#crc_extra) in
    /// MAVLink docs.
    fn crc_extra(&self) -> CrcExtra;
}

/// Generic MAVLink message specification with constant functions.
///
/// Each message should implement this trait. This is required for building correct dialects.
pub trait MessageSpecStatic {
    /// Returns specification for this message.
    fn spec() -> MessageInfo;

    /// Message `ID`.
    fn message_id() -> MessageId;

    /// Message `CRC_EXTRA`.
    fn crc_extra() -> CrcExtra;

    /// Minimum supported MAVLink version for this message.
    fn min_supported_mavlink_version() -> MavLinkVersion;
}

/// MAVLink message implementation.
///
/// Concrete MAVLink message that knows its specs through [`MessageSpec`] and allows to decode itself into
/// [`Payload`](crate::payload::Payload) via [`IntoPayload`].
pub trait Message: MessageSpec + IntoPayload {}

/// Generic information about MAVLink message.
///
/// Used in dialects to provide information required for message verification and processing.
#[derive(Copy, Clone, Debug)]
pub struct MessageInfo {
    id: MessageId,
    min_supported_mavlink_version: MavLinkVersion,
    crc_extra: CrcExtra,
}

impl MessageSpec for MessageInfo {
    #[inline(always)]
    fn id(&self) -> MessageId {
        self.id()
    }

    #[inline(always)]
    fn min_supported_mavlink_version(&self) -> MavLinkVersion {
        self.min_supported_mavlink_version()
    }

    #[inline(always)]
    fn crc_extra(&self) -> CrcExtra {
        self.crc_extra()
    }
}

impl MessageInfo {
    /// Default constructor.
    ///
    /// Sets `min_supported_mavlink_version` to [`MavLinkVersion::V2`] if message `id` greater
    /// than [`u8::MAX`]. The latter means it can't be fitted into `MAVLink 1` packet. Otherwise,
    /// sets to [`MavLinkVersion::V1`].
    pub const fn new(id: MessageId, crc_extra: CrcExtra) -> Self {
        // Force `MAVLink 2` as minimum protocol version if `id` can't be represented as `u8`
        let min_supported_mavlink_version = if id > MESSAGE_ID_V1_MAX {
            MavLinkVersion::V2
        } else {
            MavLinkVersion::V1
        };

        Self {
            id,
            min_supported_mavlink_version,
            crc_extra,
        }
    }

    /// MAVLink message ID.
    ///
    /// See: [`MessageSpec::id`].
    #[inline]
    pub fn id(&self) -> MessageId {
        self.id
    }

    /// Minimum supported MAVLink protocol version.
    ///
    /// See: [`MessageSpec::min_supported_mavlink_version`].
    #[inline]
    pub fn min_supported_mavlink_version(&self) -> MavLinkVersion {
        self.min_supported_mavlink_version
    }

    /// Message `EXTRA_CRC` calculated from message XML definition.
    ///
    /// See: [`MessageSpec::crc_extra`].
    #[inline]
    pub fn crc_extra(&self) -> CrcExtra {
        self.crc_extra
    }
}