Com protocol
This commit is contained in:
+115
-2
@@ -1,11 +1,23 @@
|
|||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{Fields, ItemStruct, parse_macro_input};
|
use syn::{Fields, ItemEnum, ItemStruct, parse_macro_input};
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn p_com(_: TokenStream, item: TokenStream) -> TokenStream {
|
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;
|
let name = &input.ident;
|
||||||
|
|
||||||
match &mut input.fields {
|
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;
|
use pulse_macros::p_com;
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
struct WatchListItem {
|
pub struct WatchListItem {
|
||||||
symbol: String,
|
symbol: String,
|
||||||
price: f64,
|
price: f64,
|
||||||
trend: f64,
|
trend: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
struct ActivePosition {
|
pub struct ActivePosition {
|
||||||
symbol: String,
|
symbol: String,
|
||||||
profit: f64,
|
profit: f64,
|
||||||
amount: f64,
|
amount: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
enum MarketTrend {
|
pub enum MarketTrend {
|
||||||
Bullish,
|
Bullish,
|
||||||
Bearish,
|
Bearish,
|
||||||
Neutral,
|
Neutral,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
enum Volatility {
|
pub enum Volatility {
|
||||||
Low,
|
Low,
|
||||||
Medium,
|
Medium,
|
||||||
High,
|
High,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
struct MarketOverview {
|
pub struct MarketOverview {
|
||||||
trend: MarketTrend,
|
trend: MarketTrend,
|
||||||
volatility: Volatility,
|
volatility: Volatility,
|
||||||
pressure: f64,
|
pressure: f64,
|
||||||
@@ -38,7 +38,7 @@ struct MarketOverview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
enum Feed {
|
pub enum Feed {
|
||||||
Connected,
|
Connected,
|
||||||
Disconnected,
|
Disconnected,
|
||||||
Connecting,
|
Connecting,
|
||||||
@@ -46,7 +46,7 @@ enum Feed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
struct Status {
|
pub struct Status {
|
||||||
feed: Feed,
|
feed: Feed,
|
||||||
exchange: String,
|
exchange: String,
|
||||||
dex: String,
|
dex: String,
|
||||||
@@ -54,13 +54,13 @@ struct Status {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
enum SignalKind {
|
pub enum SignalKind {
|
||||||
Buy,
|
Buy,
|
||||||
Sell,
|
Sell,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
enum SignalParameter {
|
pub enum SignalParameter {
|
||||||
Lim,
|
Lim,
|
||||||
Stl,
|
Stl,
|
||||||
Tap,
|
Tap,
|
||||||
@@ -68,7 +68,7 @@ enum SignalParameter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
struct Signal {
|
pub struct Signal {
|
||||||
kind: SignalKind,
|
kind: SignalKind,
|
||||||
symbol: String,
|
symbol: String,
|
||||||
param: SignalParameter,
|
param: SignalParameter,
|
||||||
@@ -76,7 +76,7 @@ struct Signal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
enum LogKind {
|
pub enum LogKind {
|
||||||
Info,
|
Info,
|
||||||
Warn,
|
Warn,
|
||||||
Err,
|
Err,
|
||||||
@@ -84,27 +84,27 @@ enum LogKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
struct EventLog {
|
pub struct EventLog {
|
||||||
kind: LogKind,
|
kind: LogKind,
|
||||||
name: String,
|
name: String,
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
enum AlertLevel {
|
pub enum AlertLevel {
|
||||||
High,
|
High,
|
||||||
Medium,
|
Medium,
|
||||||
Low,
|
Low,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
struct Alert {
|
pub struct Alert {
|
||||||
level: AlertLevel,
|
level: AlertLevel,
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[p_com]
|
#[p_com]
|
||||||
enum InspectTarget {
|
pub enum InspectTarget {
|
||||||
None,
|
None,
|
||||||
Symbol(WatchListItem),
|
Symbol(WatchListItem),
|
||||||
Position(ActivePosition),
|
Position(ActivePosition),
|
||||||
|
|||||||
Reference in New Issue
Block a user