Derive Macro mavspec_rust_derive::Message

source ·
#[derive(Message)]
{
    // Attributes available to this derive:
    #[message_id]
    #[crc_extra]
    #[extension]
    #[base_type]
    #[repr_type]
    #[bitmask]
}
Expand description

Derive MAVLink message from struct.

§Usage

Basic usage:

use mavspec::rust::derive::Message;

#[derive(Clone, Debug, Message)]
#[message_id(255)] // Specify message ID
struct CustomMessage {
    scalar_u8: u8,
    array_u8_4: [u8; 4],
    #[extension] // This marks an extension fields
    ext_array_u32_4: [u32; 4],
}

It is possible to override CRC_EXTRA byte using #[crc_extra(32)] attribute:

use mavspec::rust::derive::Message;

#[derive(Clone, Debug, Message)]
#[message_id(255)] // Specify message ID
#[crc_extra(32)]   // Set `CRC_EXTRA` byte
struct CustomMessage {
    scalar_u8: u8,
    array_u8_4: [u8; 4],
}

assert_eq!(CustomMessage::crc_extra(), 32);

Auto-calculated CRC_EXTRA is not supported for arrays with lengths specified by constants. The following won’t compile:

use mavspec::rust::derive::Message;

const FOUR: usize = 4;

#[derive(Clone, Debug, Message)]
#[message_id(255)]
struct CustomMessage {
    scalar_u8: u8,
    array_u8_4: [u8; FOUR], // Can't calculate `CRC_EXTRA`
}

§Enums

It is possible to use custom enums as message fields types with #[derive(Enum)]. Each enum should have a numeric representation and implement Default trait.

Fields with custom types should be attributed with base_type attribute (i.e. #[base_type(u16)]) that specifies actual base type of a field. For arrays base type is a type of their elements.

It is possible to use larger base types with smaller enum representation types. In such case you have to specify the representation type of an enum with repr_type attribute (i.e. #[repr_type(u8)]).

It is forbidden to use larger representation types with smaller base types.

use mavspec::rust::derive::{Enum, Message};

#[repr(u8)] // Define enum representation
#[derive(Clone, Copy, Debug, Default, Enum)]
enum Variants {
    #[default]
    OptionA = 0,
    OptionB = 1,
    OptionC = 2,
}

#[derive(Clone, Debug, Message)]
#[message_id(255)]
struct CustomMessage {
    #[base_type(u8)]
    scalar_u8: Variants,

    #[base_type(u8)]
    array_u8_4: [Variants; 4],

    #[base_type(u16)]
    #[repr_type(u8)]
    large_scalar_u16: Variants,

    #[base_type(u16)]
    #[repr_type(u8)]
    large_array_u16_4: [Variants; 4],
}

§Bitmasks

For bitmasks you can use native bitflags flags. In such case you have to attribute corresponding fields with #[bitmask] attribute. In the same spirit as for enums you have to set base_type type and repr_type attributes.

use mavspec::rust::derive::Message;
use bitflags::bitflags;

bitflags! {
    #[derive(Clone, Copy, Debug, Default)]
    struct Flags: u8 {
        const FLAG_8 = 1;
        const FLAG_7 = 1 << 1;
        const FLAG_6 = 1 << 2;
        const FLAG_5 = 1 << 3;
        const FLAG_4 = 1 << 4;
        const FLAG_3 = 1 << 5;
        const FLAG_2 = 1 << 6;
        const FLAG_1 = 1 << 7;
    }
}

#[derive(Clone, Debug, Message)]
#[message_id(255)]
struct CustomMessage {
    #[bitmask]
    #[base_type(u8)]
    scalar_u8: Flags,

    #[bitmask]
    #[base_type(u8)]
    array_u8_4: [Flags; 4],

    #[bitmask]
    #[base_type(u16)]
    #[repr_type(u8)]
    large_scalar_u16: Flags,

    #[bitmask]
    #[base_type(u16)]
    #[repr_type(u8)]
    large_array_u16_4: [Flags; 4],
}