Skip to content

Commit

Permalink
Move hardcoded groups to be created by build
Browse files Browse the repository at this point in the history
Signed-off-by: Patrick José Pereira <[email protected]>
  • Loading branch information
patrickelectric committed Dec 25, 2023
1 parent 8c0f4c7 commit 363cce8
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 98 deletions.
117 changes: 112 additions & 5 deletions build/binder.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,129 @@
use convert_case::{Case, Casing};
use proc_macro2::TokenStream;
use std::io::Write;

use quote;

pub fn generate<W: Write>(modules: Vec<String>, out: &mut W) {
dbg!(&modules);
let modules_tokens = modules.into_iter().map(|module| {
let file_name = module.clone() + ".rs";
let modules_tokens = modules
.clone()
.into_iter()
.map(|module| {
let file_name = module.clone() + ".rs";
let module_ident = quote::format_ident!("{module}");

quote! {
pub mod #module_ident {
include!(#file_name);
}
}
})
.collect::<Vec<TokenStream>>();

let enum_tokens = modules
.clone()
.into_iter()
.map(|module| {
let pascal_case_ident = quote::format_ident!("{}", module.to_case(Case::Pascal));
let module_ident = quote::format_ident!("{module}");

quote! {
#pascal_case_ident(#module_ident::Messages),
}
})
.collect::<Vec<TokenStream>>();

let deserialize_tokens_vec = modules.clone().into_iter().map(|module| {
let pascal_case_ident = quote::format_ident!("{}", module.to_case(Case::Pascal));
let module_ident = quote::format_ident!("{module}");
quote! {
if let Ok(message) =
#module_ident::Messages::deserialize(protocol_message.message_id, &protocol_message.payload)
{
return Ok(Messages::#pascal_case_ident(message));
}
}
}).collect::<Vec<TokenStream>>();

let deserialize_tokens = modules.into_iter().map(|module| {
let pascal_case_ident = quote::format_ident!("{}", module.to_case(Case::Pascal));
let module_ident = quote::format_ident!("{module}");
quote! {
pub mod #module_ident {
include!(#file_name);
if let Ok(message) = #module_ident::Messages::deserialize(message.message_id, &message.payload) {
return Ok(Messages::#pascal_case_ident(message));
}
}
}).collect::<Vec<TokenStream>>();

let enum_ident = quote! {
pub enum Messages {
#(#enum_tokens)*
}
};

let try_from_ident = quote! {
impl TryFrom<&ProtocolMessage> for Messages {
type Error = String; // TODO: define error types for each kind of failure

fn try_from(message: &ProtocolMessage) -> Result<Self, Self::Error> {
if !message.has_valid_crc() {
return Err(format!(
"Missmatch crc, expected: 0x{:04x}, received: 0x{:04x}",
message.calculate_crc(),
message.checksum
));
}

#(#deserialize_tokens)*

Err("Unknown message".into())
}
}
});

impl TryFrom<&Vec<u8>> for Messages {
type Error = String; // TODO: define error types for each kind of failure

fn try_from(buffer: &Vec<u8>) -> Result<Self, Self::Error> {
// Parse start1 and start2
if !((buffer[0] == HEADER[0]) && (buffer[1] == HEADER[1])) {
return Err(format!("Message should start with \"BR\" ASCII sequence, received: [{0}({:0x}), {1}({:0x})]", buffer[0], buffer[1]));
}

let payload_length = u16::from_le_bytes([buffer[2], buffer[3]]);
let protocol_message = ProtocolMessage {
payload_length,
message_id: u16::from_le_bytes([buffer[4], buffer[5]]),
src_device_id: buffer[6],
dst_device_id: buffer[7],
payload: buffer[8..(8 + payload_length) as usize].into(),
checksum: u16::from_le_bytes([
buffer[(8 + payload_length) as usize],
buffer[(8 + payload_length + 1) as usize],
]),
};

if !protocol_message.has_valid_crc() {
return Err(format!(
"Missmatch crc, expected: 0x{:04x}, received: 0x{:04x}",
protocol_message.calculate_crc(),
protocol_message.checksum
));
}

#(#deserialize_tokens_vec)*

Err("Unknown message".into())
}
}
};

let tokens = quote! {
#(#modules_tokens)*

#enum_ident

#try_from_ident
};

writeln!(out, "{tokens}").unwrap();
Expand Down
93 changes: 0 additions & 93 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,101 +9,8 @@ use std::convert::TryFrom;
pub mod decoder;
pub mod message;

impl TryFrom<&Vec<u8>> for Messages {
type Error = String; // TODO: define error types for each kind of failure

fn try_from(buffer: &Vec<u8>) -> Result<Self, Self::Error> {
// Parse start1 and start2
if !((buffer[0] == HEADER[0]) && (buffer[1] == HEADER[1])) {
return Err(format!("Message should start with \"BR\" ASCII sequence, received: [{0}({:0x}), {1}({:0x})]", buffer[0], buffer[1]));
}

let payload_length = u16::from_le_bytes([buffer[2], buffer[3]]);
let protocol_message = ProtocolMessage {
payload_length,
message_id: u16::from_le_bytes([buffer[4], buffer[5]]),
src_device_id: buffer[6],
dst_device_id: buffer[7],
payload: buffer[8..(8 + payload_length) as usize].into(),
checksum: u16::from_le_bytes([
buffer[(8 + payload_length) as usize],
buffer[(8 + payload_length + 1) as usize],
]),
};

if !protocol_message.has_valid_crc() {
return Err(format!(
"Missmatch crc, expected: 0x{:04x}, received: 0x{:04x}",
protocol_message.calculate_crc(),
protocol_message.checksum
));
}

// Try to parse with each module
if let Ok(message) =
bluebps::Messages::deserialize(protocol_message.message_id, &protocol_message.payload)
{
return Ok(Messages::Bluebps(message));
}
if let Ok(message) =
common::Messages::deserialize(protocol_message.message_id, &protocol_message.payload)
{
return Ok(Messages::Common(message));
}
if let Ok(message) =
ping1d::Messages::deserialize(protocol_message.message_id, &protocol_message.payload)
{
return Ok(Messages::Ping1d(message));
}
if let Ok(message) =
ping360::Messages::deserialize(protocol_message.message_id, &protocol_message.payload)
{
return Ok(Messages::Ping360(message));
}

Err("Unknown message".into())
}
}

pub enum Messages {
Bluebps(bluebps::Messages),
Common(common::Messages),
Ping1d(ping1d::Messages),
Ping360(ping360::Messages),
}

pub fn calculate_crc(pack_without_payload: &[u8]) -> u16 {
return pack_without_payload
.iter()
.fold(0 as u16, |s, &v| s.wrapping_add(v as u16));
}

impl TryFrom<&ProtocolMessage> for Messages {
type Error = String; // TODO: define error types for each kind of failure

fn try_from(message: &ProtocolMessage) -> Result<Self, Self::Error> {
if !message.has_valid_crc() {
return Err(format!(
"Missmatch crc, expected: 0x{:04x}, received: 0x{:04x}",
message.calculate_crc(),
message.checksum
));
}

// Try to parse with each module
if let Ok(message) = bluebps::Messages::deserialize(message.message_id, &message.payload) {
return Ok(Messages::Bluebps(message));
}
if let Ok(message) = common::Messages::deserialize(message.message_id, &message.payload) {
return Ok(Messages::Common(message));
}
if let Ok(message) = ping1d::Messages::deserialize(message.message_id, &message.payload) {
return Ok(Messages::Ping1d(message));
}
if let Ok(message) = ping360::Messages::deserialize(message.message_id, &message.payload) {
return Ok(Messages::Ping360(message));
}

Err("Unknown message".into())
}
}

0 comments on commit 363cce8

Please sign in to comment.