Skip to content

Instantly share code, notes, and snippets.

@jaredmcqueen
Last active September 30, 2023 02:46
Show Gist options
  • Save jaredmcqueen/c8a56c6a919bf15a214fd865744fdc70 to your computer and use it in GitHub Desktop.
Save jaredmcqueen/c8a56c6a919bf15a214fd865744fdc70 to your computer and use it in GitHub Desktop.
serde serializing and deserializing using enums and structs
// cargo.toml:
// serde = { version = "1", features = ["derive"] }
// serde_json = "1"
use serde::{Deserialize, Serialize};
#[derive(Serialize, Debug)]
#[serde(tag = "action")]
pub enum ClientMessage {
#[serde(rename = "auth")]
Auth(AuthMessage),
#[serde(rename = "subscribe")]
Subscribe(SubscriptionMessage),
#[serde(rename = "unsubscribe")]
Unsubscribe(SubscriptionMessage),
}
#[derive(Debug, Serialize, Clone)]
pub struct AuthMessage {
pub key: String,
pub secret: String,
}
#[derive(Debug, Serialize, Clone)]
pub struct SubscriptionMessage {
#[serde(skip_serializing_if = "Option::is_none")]
pub trades: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quotes: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bars: Option<Vec<String>>,
}
#[derive(Deserialize, Debug)]
#[serde(tag = "T")]
pub enum WebSocketEvent {
#[serde(rename = "success")]
Success(SuccessMessage),
#[serde(rename = "error")]
Error(ErrorEvent),
#[serde(rename = "subscription")]
Subscription(SubscriptionEvent),
#[serde(rename = "t")]
Trade(TradeEvent),
#[serde(rename = "q")]
Quote(QuoteEvent),
#[serde(rename = "b")]
Bar(BarEvent),
#[serde(rename = "d")]
DailyBar(BarEvent),
#[serde(rename = "u")]
UpdatedBar(BarEvent),
}
#[derive(Debug, Deserialize, Clone)]
pub struct SubscriptionEvent {
#[serde(rename = "trades")]
pub trades: Vec<String>,
#[serde(rename = "quotes")]
pub quotes: Vec<String>,
#[serde(rename = "bars")]
pub bars: Vec<String>,
#[serde(rename = "updatedBars")]
pub updated_bars: Vec<String>,
#[serde(rename = "dailyBars")]
pub daily_bars: Vec<String>,
#[serde(rename = "statuses")]
pub statuses: Vec<String>,
#[serde(rename = "lulds")]
pub lulds: Vec<String>,
#[serde(rename = "corrections")]
pub corrections: Vec<String>,
#[serde(rename = "cancelErrors")]
pub cancel_errors: Vec<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct SuccessMessage {
#[serde(rename = "msg")]
pub message: String,
}
#[derive(Debug, Deserialize, Clone)]
pub struct ErrorEvent {
#[serde(rename = "msg")]
pub message: String,
#[serde(rename = "code")]
pub code: u16,
}
#[derive(Debug, Deserialize, Clone)]
pub struct TradeEvent {
#[serde(rename = "S")]
pub symbol: String,
#[serde(rename = "i")]
pub trade_id: u64,
#[serde(rename = "x")]
pub exchange_code: String,
#[serde(rename = "p")]
pub trade_price: f64,
#[serde(rename = "s")]
pub trade_size: u64,
#[serde(rename = "t")]
pub timestamp: String,
#[serde(rename = "c")]
pub trade_condition: Vec<String>,
#[serde(rename = "z")]
pub tape: String,
}
#[derive(Debug, Deserialize, Clone)]
pub struct QuoteEvent {
#[serde(rename = "S")]
pub symbol: String,
#[serde(rename = "ax")]
pub ask_exchange_code: String,
#[serde(rename = "ap")]
pub ask_price: f64,
#[serde(rename = "as")]
pub ask_size: u64,
#[serde(rename = "bx")]
pub bid_exchange_code: String,
#[serde(rename = "bp")]
pub bid_price: f64,
#[serde(rename = "bs")]
pub bid_size: u64,
#[serde(rename = "c")]
pub quote_condition: Vec<String>,
#[serde(rename = "t")]
pub timestamp: String,
#[serde(rename = "z")]
pub tape: String,
}
#[derive(Debug, Deserialize, Clone)]
pub struct BarEvent {
#[serde(rename = "S")]
pub symbol: String,
#[serde(rename = "o")]
pub open: f64,
#[serde(rename = "h")]
pub high: f64,
#[serde(rename = "l")]
pub low: f64,
#[serde(rename = "c")]
pub close: f64,
#[serde(rename = "v")]
pub volume: u64,
#[serde(rename = "t")]
pub timestamp: String,
}
fn main() {
let connected = r#"{"T":"success","msg":"connected"}"#;
let error = r#"{"T":"error","code":400,"msg":"connected"}"#;
let trade = r#"{"T":"t","i":96921,"S":"AAPL","x":"D","p":126.55,"s":1,"t":"2021-02-22T15:51:44.208Z","c":["@","I"],"z":"C"}"#;
let quote = r#"{"T":"q","S":"AMD","bx":"U","bp":87.66,"bs":1,"ax":"Q","ap":87.68,"as":4,"t":"2021-02-22T15:51:45.335689322Z","c":["R"],"z":"C"}"#;
let bar = r#"{"T":"b","S":"SPY","o":388.985,"h":389.13,"l":388.975,"c":389.12,"v":49378,"t":"2021-02-22T19:15:00Z"}"#;
let daily_bar = r#"{"T":"d","S":"SPY","o":388.985,"h":389.13,"l":388.975,"c":389.12,"v":49378,"t":"2021-02-22T19:15:00Z"}"#;
let updated_bar = r#"{"T":"u","S":"SPY","o":388.985,"h":389.13,"l":388.975,"c":389.12,"v":49378,"t":"2021-02-22T19:15:00Z"}"#;
let subscription = r#"{"T":"subscription","trades":["AAPL"],"quotes":["AMD","CLDR"],"bars":["*"],"updatedBars":[],"dailyBars":["VOO"],"statuses":["*"],"lulds":[],"corrections":["AAPL"],"cancelErrors":["AAPL"]}"#;
let events = vec![
connected,
error,
trade,
quote,
bar,
daily_bar,
updated_bar,
subscription,
];
for event_type in events {
let event: WebSocketEvent = serde_json::from_str(event_type).unwrap();
dbg!(event);
}
let auth_message = ClientMessage::Auth(AuthMessage {
key: "my-key".into(),
secret: "my-secret".into(),
});
let subscribe = ClientMessage::Subscribe(SubscriptionMessage {
trades: Some(vec!["AAPL".into()]),
quotes: Some(vec!["MSFT".into(), "TSLA".into()]),
bars: None,
});
let unsubscribe = ClientMessage::Unsubscribe(SubscriptionMessage {
trades: Some(vec!["AAPL".into()]),
quotes: Some(vec!["MSFT".into(), "TSLA".into()]),
bars: None,
});
let client_messages = vec![auth_message, subscribe, unsubscribe];
for message in client_messages {
let json = serde_json::to_string(&message).expect("error bro");
dbg!(json);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment