wmjtyd_libstock/data/
bbo.rs1use std::io::{BufRead, BufReader};
4
5use crypto_msg_parser::BboMsg;
6use rust_decimal::prelude::ToPrimitive;
7
8use super::{
9 fields::{
10 ExchangeTimestampRepr, ExchangeTypeRepr, MarketTypeRepr, MessageTypeRepr, ReadExt,
11 ReceivedTimestampRepr, StructureError, SymbolPairRepr,
12 },
13 hex::{HexDataError, NumToBytesExt},
14};
15
16pub fn encode_bbo(bbo: &BboMsg) -> BboResult<Vec<u8>> {
18 let mut bytes = Vec::<u8>::with_capacity(41);
20
21 bytes.extend_from_slice(&ExchangeTimestampRepr(bbo.timestamp).to_bytes());
23
24 bytes.extend_from_slice(&ReceivedTimestampRepr::try_new_from_now()?.to_bytes());
26
27 bytes.extend_from_slice(&ExchangeTypeRepr::try_from_str(&bbo.exchange)?.to_bytes());
29
30 bytes.extend_from_slice(&MarketTypeRepr(bbo.market_type).to_bytes());
32
33 bytes.extend_from_slice(&MessageTypeRepr(bbo.msg_type).to_bytes());
35
36 bytes.extend_from_slice(&SymbolPairRepr::from_pair(&bbo.pair).to_bytes());
38
39 bytes.extend_from_slice(&u32::encode_bytes(&bbo.ask_price.to_string())?);
41 bytes.extend_from_slice(&u32::encode_bytes(&bbo.ask_quantity_base.to_string())?);
42
43 bytes.extend_from_slice(&u32::encode_bytes(&bbo.bid_price.to_string())?);
45 bytes.extend_from_slice(&u32::encode_bytes(&bbo.bid_quantity_base.to_string())?);
46
47 Ok(bytes)
48}
49
50pub fn decode_bbo(payload: &[u8]) -> BboResult<BboMsg> {
52 let mut reader = BufReader::new(payload);
53
54 let exchange_timestamp = ExchangeTimestampRepr::try_from_reader(&mut reader)?.0;
56
57 reader.consume(8);
59
60 let exchange_type = ExchangeTypeRepr::try_from_reader(&mut reader)?.0;
62
63 let market_type = MarketTypeRepr::try_from_reader(&mut reader)?.0;
65
66 let msg_type = MessageTypeRepr::try_from_reader(&mut reader)?.0;
68
69 let SymbolPairRepr(symbol, pair) = SymbolPairRepr::try_from_reader(&mut reader)?;
71
72 let ask_price = {
74 let raw_bytes = reader.read_exact_array()?;
75 u32::decode_bytes(&raw_bytes)
76 .to_f64()
77 .ok_or_else(|| BboError::DecimalConvertF64Failed(raw_bytes.to_vec()))?
78 };
79
80 let ask_quantity_base = {
81 let raw_bytes = reader.read_exact_array()?;
82 u32::decode_bytes(&raw_bytes)
83 .to_f64()
84 .ok_or_else(|| BboError::DecimalConvertF64Failed(raw_bytes.to_vec()))?
85 };
86
87 let bid_price = {
89 let raw_bytes = reader.read_exact_array()?;
90 u32::decode_bytes(&raw_bytes)
91 .to_f64()
92 .ok_or_else(|| BboError::DecimalConvertF64Failed(raw_bytes.to_vec()))?
93 };
94
95 let bid_quantity_base = {
96 let raw_bytes = reader.read_exact_array()?;
97 u32::decode_bytes(&raw_bytes)
98 .to_f64()
99 .ok_or_else(|| BboError::DecimalConvertF64Failed(raw_bytes.to_vec()))?
100 };
101
102 Ok(BboMsg {
103 exchange: exchange_type.to_string(),
104 market_type,
105 msg_type,
106 pair: pair.to_string(),
107 symbol: symbol.to_string(),
108 timestamp: exchange_timestamp,
109 ask_price,
110 ask_quantity_base,
111 ask_quantity_quote: 0.0,
112 ask_quantity_contract: None,
113 bid_price,
114 bid_quantity_base,
115 bid_quantity_quote: 0.0,
116 bid_quantity_contract: None,
117 id: None,
118 json: String::new(),
119 })
120}
121
122#[derive(thiserror::Error, Debug)]
123pub enum BboError {
124 #[error("data/hex error: {0}")]
125 HexDataError(#[from] HexDataError),
126
127 #[error("structure error: {0}")]
128 StructureError(#[from] StructureError),
129
130 #[error("failed to convert the following bytes to f64: {0:?}")]
131 DecimalConvertF64Failed(Vec<u8>),
132}
133
134pub type BboResult<T> = Result<T, BboError>;