Com protocol
This commit is contained in:
+115
-2
@@ -1,11 +1,23 @@
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{Fields, ItemStruct, parse_macro_input};
|
||||
use syn::{Fields, ItemEnum, ItemStruct, parse_macro_input};
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn p_com(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let mut input = parse_macro_input!(item as ItemStruct);
|
||||
let input = parse_macro_input!(item as syn::Item);
|
||||
|
||||
match input {
|
||||
syn::Item::Struct(s) => expand_struct(s),
|
||||
syn::Item::Enum(e) => expand_enum(e),
|
||||
_ => {
|
||||
return syn::Error::new_spanned(input, "p_com only supports structs and enums")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_struct(mut input: ItemStruct) -> TokenStream {
|
||||
let name = &input.ident;
|
||||
|
||||
match &mut input.fields {
|
||||
@@ -59,3 +71,104 @@ pub fn p_com(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn expand_enum(input: ItemEnum) -> TokenStream {
|
||||
let name = &input.ident;
|
||||
|
||||
let to_com = input.variants.iter().enumerate().map(|(i, variant)| {
|
||||
let ident = &variant.ident;
|
||||
let tag = i as u8;
|
||||
|
||||
match &variant.fields {
|
||||
Fields::Unit => quote! {
|
||||
Self::#ident => {
|
||||
vec.push(#tag);
|
||||
}
|
||||
},
|
||||
|
||||
Fields::Unnamed(fields) if fields.unnamed.len() == 1 => quote! {
|
||||
Self::#ident(v) => {
|
||||
vec.push(#tag);
|
||||
vec.extend(v.to_com());
|
||||
}
|
||||
},
|
||||
|
||||
Fields::Named(fields) => {
|
||||
let names = fields.named.iter().map(|f| f.ident.as_ref().unwrap());
|
||||
|
||||
let names2 = fields.named.iter().map(|f| f.ident.as_ref().unwrap());
|
||||
|
||||
quote! {
|
||||
Self::#ident { #( #names ),* } => {
|
||||
vec.push(#tag);
|
||||
#( vec.extend(#names2.to_com()); )*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
panic!("tuple variants with >1 field are not supported");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let from_com = input.variants.iter().enumerate().map(|(i, variant)| {
|
||||
let ident = &variant.ident;
|
||||
let tag = i as u8;
|
||||
|
||||
match &variant.fields {
|
||||
Fields::Unit => quote! {
|
||||
#tag => Self::#ident,
|
||||
},
|
||||
|
||||
Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
|
||||
let ty = &fields.unnamed.first().unwrap().ty;
|
||||
|
||||
quote! {
|
||||
#tag => Self::#ident(<#ty>::from_com(com)),
|
||||
}
|
||||
}
|
||||
|
||||
Fields::Named(fields) => {
|
||||
let names = fields.named.iter().map(|f| f.ident.as_ref().unwrap());
|
||||
let tys = fields.named.iter().map(|f| &f.ty);
|
||||
|
||||
quote! {
|
||||
#tag => Self::#ident {
|
||||
#(
|
||||
#names: <#tys>::from_com(com),
|
||||
)*
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
_ => panic!("tuple variants with >1 field are not supported"),
|
||||
}
|
||||
});
|
||||
|
||||
TokenStream::from(quote! {
|
||||
#[derive(Debug, Clone)]
|
||||
#input
|
||||
|
||||
impl PulseCom for #name {
|
||||
fn to_com(&self) -> Vec<u8> {
|
||||
let mut vec = Vec::new();
|
||||
|
||||
match self {
|
||||
#( #to_com )*
|
||||
}
|
||||
|
||||
vec
|
||||
}
|
||||
|
||||
fn from_com(com: &mut Vec<u8>) -> Self {
|
||||
let kind = com.remove(0);
|
||||
|
||||
match kind {
|
||||
#( #from_com )*
|
||||
_ => panic!("invalid {} discriminant {}", stringify!(#name), kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+15
-15
@@ -1,35 +1,35 @@
|
||||
use pulse_macros::p_com;
|
||||
|
||||
#[p_com]
|
||||
struct WatchListItem {
|
||||
pub struct WatchListItem {
|
||||
symbol: String,
|
||||
price: f64,
|
||||
trend: f64,
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
struct ActivePosition {
|
||||
pub struct ActivePosition {
|
||||
symbol: String,
|
||||
profit: f64,
|
||||
amount: f64,
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
enum MarketTrend {
|
||||
pub enum MarketTrend {
|
||||
Bullish,
|
||||
Bearish,
|
||||
Neutral,
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
enum Volatility {
|
||||
pub enum Volatility {
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
struct MarketOverview {
|
||||
pub struct MarketOverview {
|
||||
trend: MarketTrend,
|
||||
volatility: Volatility,
|
||||
pressure: f64,
|
||||
@@ -38,7 +38,7 @@ struct MarketOverview {
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
enum Feed {
|
||||
pub enum Feed {
|
||||
Connected,
|
||||
Disconnected,
|
||||
Connecting,
|
||||
@@ -46,7 +46,7 @@ enum Feed {
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
struct Status {
|
||||
pub struct Status {
|
||||
feed: Feed,
|
||||
exchange: String,
|
||||
dex: String,
|
||||
@@ -54,13 +54,13 @@ struct Status {
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
enum SignalKind {
|
||||
pub enum SignalKind {
|
||||
Buy,
|
||||
Sell,
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
enum SignalParameter {
|
||||
pub enum SignalParameter {
|
||||
Lim,
|
||||
Stl,
|
||||
Tap,
|
||||
@@ -68,7 +68,7 @@ enum SignalParameter {
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
struct Signal {
|
||||
pub struct Signal {
|
||||
kind: SignalKind,
|
||||
symbol: String,
|
||||
param: SignalParameter,
|
||||
@@ -76,7 +76,7 @@ struct Signal {
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
enum LogKind {
|
||||
pub enum LogKind {
|
||||
Info,
|
||||
Warn,
|
||||
Err,
|
||||
@@ -84,27 +84,27 @@ enum LogKind {
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
struct EventLog {
|
||||
pub struct EventLog {
|
||||
kind: LogKind,
|
||||
name: String,
|
||||
message: String,
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
enum AlertLevel {
|
||||
pub enum AlertLevel {
|
||||
High,
|
||||
Medium,
|
||||
Low,
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
struct Alert {
|
||||
pub struct Alert {
|
||||
level: AlertLevel,
|
||||
message: String,
|
||||
}
|
||||
|
||||
#[p_com]
|
||||
enum InspectTarget {
|
||||
pub enum InspectTarget {
|
||||
None,
|
||||
Symbol(WatchListItem),
|
||||
Position(ActivePosition),
|
||||
|
||||
Reference in New Issue
Block a user