Skip to content

Commit

Permalink
Add MessageData trait to allow serialize ***_DATA structs into MAVLin…
Browse files Browse the repository at this point in the history
…kV[1|2]MessageRaw
  • Loading branch information
qwerty19106 committed Mar 22, 2023
1 parent 240551b commit 2904a5f
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 110 deletions.
103 changes: 31 additions & 72 deletions build/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,28 +121,6 @@ impl MavProfile {
.collect()
}

/// A list of message IDs
fn emit_msg_ids(&self) -> Vec<TokenStream> {
self.messages
.values()
.map(|msg| {
let msg_id = msg.id;
quote!(#msg_id)
})
.collect()
}

/// CRC values needed for mavlink parsing
fn emit_msg_crc(&self) -> Vec<TokenStream> {
self.messages
.values()
.map(|msg| {
let ec = extra_crc(msg);
quote!(#ec)
})
.collect()
}

fn emit_rust(&self) -> TokenStream {
//TODO verify that id_width of u8 is OK even in mavlink v1
let id_width = format_ident!("u32");
Expand All @@ -152,17 +130,15 @@ impl MavProfile {
let enum_names = self.emit_enum_names();
let struct_names = self.emit_struct_names();
let enums = self.emit_enums();
let msg_ids = self.emit_msg_ids();
let msg_crc = self.emit_msg_crc();

let mav_message = self.emit_mav_message(&enum_names, &struct_names);
let mav_message_parse = self.emit_mav_message_parse(&enum_names, &struct_names, &msg_ids);
let mav_message_crc = self.emit_mav_message_crc(&id_width, &msg_ids, &msg_crc);
let mav_message_name = self.emit_mav_message_name(&enum_names);
let mav_message_id = self.emit_mav_message_id(&enum_names, &msg_ids);
let mav_message_id_from_name = self.emit_mav_message_id_from_name(&enum_names, &msg_ids);
let mav_message_parse = self.emit_mav_message_parse(&enum_names, &struct_names);
let mav_message_crc = self.emit_mav_message_crc(&id_width, &struct_names);
let mav_message_name = self.emit_mav_message_name(&enum_names, &struct_names);
let mav_message_id = self.emit_mav_message_id(&enum_names, &struct_names);
let mav_message_id_from_name = self.emit_mav_message_id_from_name(&struct_names);
let mav_message_default_from_id =
self.emit_mav_message_default_from_id(&enum_names, &msg_ids);
self.emit_mav_message_default_from_id(&enum_names, &struct_names);
let mav_message_serialize = self.emit_mav_message_serialize(&enum_names);

quote! {
Expand All @@ -181,7 +157,7 @@ impl MavProfile {
#[allow(unused_imports)]
use heapless::Vec;

use crate::{Message, error::*, bytes::Bytes, bytes_mut::BytesMut};
use crate::{Message, MessageData, error::*, bytes::Bytes, bytes_mut::BytesMut};

#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
Expand All @@ -205,11 +181,7 @@ impl MavProfile {
}
}

fn emit_mav_message(
&self,
enums: &Vec<TokenStream>,
structs: &Vec<TokenStream>,
) -> TokenStream {
fn emit_mav_message(&self, enums: &[TokenStream], structs: &[TokenStream]) -> TokenStream {
quote! {
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type"))]
Expand All @@ -223,14 +195,13 @@ impl MavProfile {
&self,
enums: &[TokenStream],
structs: &[TokenStream],
ids: &[TokenStream],
) -> TokenStream {
let id_width = format_ident!("u32");

quote! {
fn parse(version: MavlinkVersion, id: #id_width, payload: &[u8]) -> Result<Self, ParserError> {
match id {
#(#ids => #structs::deser(version, payload).map(Self::#enums),)*
#(#structs::ID => #structs::deser(version, payload).map(Self::#enums),)*
_ => {
Err(ParserError::UnknownMessage { id })
},
Expand All @@ -242,13 +213,12 @@ impl MavProfile {
fn emit_mav_message_crc(
&self,
id_width: &Ident,
ids: &[TokenStream],
crc: &[TokenStream],
structs: &[TokenStream],
) -> TokenStream {
quote! {
fn extra_crc(id: #id_width) -> u8 {
match id {
#(#ids => #crc,)*
#(#structs::ID => #structs::EXTRA_CRC,)*
_ => {
0
},
Expand All @@ -257,46 +227,32 @@ impl MavProfile {
}
}

fn emit_mav_message_name(&self, enums: &Vec<TokenStream>) -> TokenStream {
let enum_names = enums.iter().map(|enum_name| {
let name = enum_name.to_string();
quote!(#name)
});

fn emit_mav_message_name(&self, enums: &[TokenStream], structs: &[TokenStream]) -> TokenStream {
quote! {
fn message_name(&self) -> &'static str {
match self {
#(Self::#enums(..) => #enum_names,)*
#(Self::#enums(..) => #structs::NAME,)*
}
}
}
}

fn emit_mav_message_id(&self, enums: &Vec<TokenStream>, ids: &Vec<TokenStream>) -> TokenStream {
fn emit_mav_message_id(&self, enums: &[TokenStream], structs: &[TokenStream]) -> TokenStream {
let id_width = format_ident!("u32");
quote! {
fn message_id(&self) -> #id_width {
match self {
#(Self::#enums(..) => #ids,)*
#(Self::#enums(..) => #structs::ID,)*
}
}
}
}

fn emit_mav_message_id_from_name(
&self,
enums: &[TokenStream],
ids: &[TokenStream],
) -> TokenStream {
let enum_names = enums.iter().map(|enum_name| {
let name = enum_name.to_string();
quote!(#name)
});

fn emit_mav_message_id_from_name(&self, structs: &[TokenStream]) -> TokenStream {
quote! {
fn message_id_from_name(name: &str) -> Result<u32, &'static str> {
match name {
#(#enum_names => Ok(#ids),)*
#(#structs::NAME => Ok(#structs::ID),)*
_ => {
Err("Invalid message name.")
}
Expand All @@ -308,17 +264,12 @@ impl MavProfile {
fn emit_mav_message_default_from_id(
&self,
enums: &[TokenStream],
ids: &[TokenStream],
structs: &[TokenStream],
) -> TokenStream {
let data_name = enums.iter().map(|enum_name| {
let name = format_ident!("{}_DATA", enum_name.to_string());
quote!(#name)
});

quote! {
fn default_message_from_id(id: u32) -> Result<Self, &'static str> {
match id {
#(#ids => Ok(Self::#enums(#data_name::default())),)*
#(#structs::ID => Ok(Self::#enums(#structs::default())),)*
_ => {
Err("Invalid message id.")
}
Expand Down Expand Up @@ -584,6 +535,9 @@ impl MavMessage {

fn emit_rust(&self) -> TokenStream {
let msg_name = self.emit_struct_name();
let id = self.id;
let name = self.name.clone();
let extra_crc = extra_crc(self);
let (name_types, msg_encoded_len) = self.emit_name_types();

let deser_vars = self.emit_deserialize_vars();
Expand All @@ -603,14 +557,19 @@ impl MavMessage {
#(#name_types)*
}

impl #msg_name {
pub const ENCODED_LEN: usize = #msg_encoded_len;
impl MessageData for #msg_name {
type Message = MavMessage;

const ID: u32 = #id;
const NAME: &'static str = #name;
const EXTRA_CRC: u8 = #extra_crc;
const ENCODED_LEN: usize = #msg_encoded_len;

pub fn deser(_version: MavlinkVersion, _input: &[u8]) -> Result<Self, ParserError> {
fn deser(_version: MavlinkVersion, _input: &[u8]) -> Result<Self, ParserError> {
#deser_vars
}

pub fn ser(&self, version: MavlinkVersion, bytes: &mut [u8]) -> usize {
fn ser(&self, version: MavlinkVersion, bytes: &mut [u8]) -> usize {
#serialize_vars
}
}
Expand Down
Loading

0 comments on commit 2904a5f

Please sign in to comment.