use crate::presentation::serialization::string_as_float_opt;
use lightstreamer_rs::subscription::ItemUpdate;
use pretty_simple_display::{DebugPretty, DisplaySimple};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[repr(u8)]
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
#[serde(rename_all = "UPPERCASE")]
pub enum DealingFlag {
#[default]
Closed,
Call,
Deal,
Edit,
ClosingsOnly,
DealNoEdit,
Auction,
AuctionNoEdit,
Suspend,
}
#[derive(DebugPretty, Clone, DisplaySimple, Serialize, Deserialize, Default)]
pub struct PriceData {
pub item_name: String,
pub item_pos: i32,
pub fields: PriceFields,
pub changed_fields: PriceFields,
pub is_snapshot: bool,
}
#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize, Default)]
pub struct PriceFields {
#[serde(rename = "MID_OPEN")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub mid_open: Option<f64>,
#[serde(rename = "HIGH")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub high: Option<f64>,
#[serde(rename = "LOW")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub low: Option<f64>,
#[serde(rename = "BID")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid: Option<f64>,
#[serde(rename = "OFFER")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub offer: Option<f64>,
#[serde(rename = "CHANGE")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub change: Option<f64>,
#[serde(rename = "CHANGE_PCT")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub change_pct: Option<f64>,
#[serde(rename = "MARKET_DELAY")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub market_delay: Option<f64>,
#[serde(rename = "MARKET_STATE")]
#[serde(skip_serializing_if = "Option::is_none")]
pub market_state: Option<String>,
#[serde(rename = "UPDATE_TIME")]
#[serde(skip_serializing_if = "Option::is_none")]
pub update_time: Option<String>,
#[serde(rename = "BIDQUOTEID")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_quote_id: Option<String>,
#[serde(rename = "ASKQUOTEID")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_quote_id: Option<String>,
#[serde(rename = "BIDPRICE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_price1: Option<f64>,
#[serde(rename = "BIDPRICE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_price2: Option<f64>,
#[serde(rename = "BIDPRICE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_price3: Option<f64>,
#[serde(rename = "BIDPRICE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_price4: Option<f64>,
#[serde(rename = "BIDPRICE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_price5: Option<f64>,
#[serde(rename = "ASKPRICE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_price1: Option<f64>,
#[serde(rename = "ASKPRICE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_price2: Option<f64>,
#[serde(rename = "ASKPRICE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_price3: Option<f64>,
#[serde(rename = "ASKPRICE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_price4: Option<f64>,
#[serde(rename = "ASKPRICE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_price5: Option<f64>,
#[serde(rename = "BIDSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_size1: Option<f64>,
#[serde(rename = "BIDSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_size2: Option<f64>,
#[serde(rename = "BIDSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_size3: Option<f64>,
#[serde(rename = "BIDSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_size4: Option<f64>,
#[serde(rename = "BIDSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub bid_size5: Option<f64>,
#[serde(rename = "ASKSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_size1: Option<f64>,
#[serde(rename = "ASKSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_size2: Option<f64>,
#[serde(rename = "ASKSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_size3: Option<f64>,
#[serde(rename = "ASKSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_size4: Option<f64>,
#[serde(rename = "ASKSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub ask_size5: Option<f64>,
#[serde(rename = "CURRENCY0")]
#[serde(skip_serializing_if = "Option::is_none")]
pub currency0: Option<String>,
#[serde(rename = "CURRENCY1")]
#[serde(skip_serializing_if = "Option::is_none")]
pub currency1: Option<String>,
#[serde(rename = "CURRENCY2")]
#[serde(skip_serializing_if = "Option::is_none")]
pub currency2: Option<String>,
#[serde(rename = "CURRENCY3")]
#[serde(skip_serializing_if = "Option::is_none")]
pub currency3: Option<String>,
#[serde(rename = "CURRENCY4")]
#[serde(skip_serializing_if = "Option::is_none")]
pub currency4: Option<String>,
#[serde(rename = "CURRENCY5")]
#[serde(skip_serializing_if = "Option::is_none")]
pub currency5: Option<String>,
#[serde(rename = "C1BIDSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c1_bid_size_1: Option<f64>,
#[serde(rename = "C1BIDSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c1_bid_size_2: Option<f64>,
#[serde(rename = "C1BIDSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c1_bid_size_3: Option<f64>,
#[serde(rename = "C1BIDSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c1_bid_size_4: Option<f64>,
#[serde(rename = "C1BIDSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c1_bid_size_5: Option<f64>,
#[serde(rename = "C2BIDSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c2_bid_size_1: Option<f64>,
#[serde(rename = "C2BIDSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c2_bid_size_2: Option<f64>,
#[serde(rename = "C2BIDSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c2_bid_size_3: Option<f64>,
#[serde(rename = "C2BIDSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c2_bid_size_4: Option<f64>,
#[serde(rename = "C2BIDSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c2_bid_size_5: Option<f64>,
#[serde(rename = "C3BIDSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c3_bid_size_1: Option<f64>,
#[serde(rename = "C3BIDSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c3_bid_size_2: Option<f64>,
#[serde(rename = "C3BIDSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c3_bid_size_3: Option<f64>,
#[serde(rename = "C3BIDSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c3_bid_size_4: Option<f64>,
#[serde(rename = "C3BIDSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c3_bid_size_5: Option<f64>,
#[serde(rename = "C4BIDSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c4_bid_size_1: Option<f64>,
#[serde(rename = "C4BIDSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c4_bid_size_2: Option<f64>,
#[serde(rename = "C4BIDSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c4_bid_size_3: Option<f64>,
#[serde(rename = "C4BIDSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c4_bid_size_4: Option<f64>,
#[serde(rename = "C4BIDSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c4_bid_size_5: Option<f64>,
#[serde(rename = "C5BIDSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c5_bid_size_1: Option<f64>,
#[serde(rename = "C5BIDSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c5_bid_size_2: Option<f64>,
#[serde(rename = "C5BIDSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c5_bid_size_3: Option<f64>,
#[serde(rename = "C5BIDSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c5_bid_size_4: Option<f64>,
#[serde(rename = "C5BIDSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c5_bid_size_5: Option<f64>,
#[serde(rename = "C1ASKSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c1_ask_size_1: Option<f64>,
#[serde(rename = "C1ASKSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c1_ask_size_2: Option<f64>,
#[serde(rename = "C1ASKSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c1_ask_size_3: Option<f64>,
#[serde(rename = "C1ASKSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c1_ask_size_4: Option<f64>,
#[serde(rename = "C1ASKSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c1_ask_size_5: Option<f64>,
#[serde(rename = "C2ASKSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c2_ask_size_1: Option<f64>,
#[serde(rename = "C2ASKSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c2_ask_size_2: Option<f64>,
#[serde(rename = "C2ASKSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c2_ask_size_3: Option<f64>,
#[serde(rename = "C2ASKSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c2_ask_size_4: Option<f64>,
#[serde(rename = "C2ASKSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c2_ask_size_5: Option<f64>,
#[serde(rename = "C3ASKSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c3_ask_size_1: Option<f64>,
#[serde(rename = "C3ASKSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c3_ask_size_2: Option<f64>,
#[serde(rename = "C3ASKSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c3_ask_size_3: Option<f64>,
#[serde(rename = "C3ASKSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c3_ask_size_4: Option<f64>,
#[serde(rename = "C3ASKSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c3_ask_size_5: Option<f64>,
#[serde(rename = "C4ASKSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c4_ask_size_1: Option<f64>,
#[serde(rename = "C4ASKSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c4_ask_size_2: Option<f64>,
#[serde(rename = "C4ASKSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c4_ask_size_3: Option<f64>,
#[serde(rename = "C4ASKSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c4_ask_size_4: Option<f64>,
#[serde(rename = "C4ASKSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c4_ask_size_5: Option<f64>,
#[serde(rename = "C5ASKSIZE1")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c5_ask_size_1: Option<f64>,
#[serde(rename = "C5ASKSIZE2")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c5_ask_size_2: Option<f64>,
#[serde(rename = "C5ASKSIZE3")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c5_ask_size_3: Option<f64>,
#[serde(rename = "C5ASKSIZE4")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c5_ask_size_4: Option<f64>,
#[serde(rename = "C5ASKSIZE5")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub c5_ask_size_5: Option<f64>,
#[serde(rename = "TIMESTAMP")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<f64>,
#[serde(rename = "DLG_FLAG")]
#[serde(skip_serializing_if = "Option::is_none")]
pub dealing_flag: Option<DealingFlag>,
#[serde(rename = "NET_CHG")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub net_chg: Option<f64>,
#[serde(rename = "NET_CHG_PCT")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub net_chg_pct: Option<f64>,
#[serde(rename = "DELAY")]
#[serde(with = "string_as_float_opt")]
#[serde(skip_serializing_if = "Option::is_none")]
pub delay: Option<f64>,
}
impl PriceData {
pub fn from_item_update(item_update: &ItemUpdate) -> Result<Self, String> {
let item_name = item_update.item_name.clone().unwrap_or_default();
let item_pos = item_update.item_pos as i32;
let is_snapshot = item_update.is_snapshot;
let fields = Self::create_price_fields(&item_update.fields)?;
let mut changed_fields_map: HashMap<String, Option<String>> = HashMap::new();
for (key, value) in &item_update.changed_fields {
changed_fields_map.insert(key.clone(), Some(value.clone()));
}
let changed_fields = Self::create_price_fields(&changed_fields_map)?;
Ok(PriceData {
item_name,
item_pos,
fields,
changed_fields,
is_snapshot,
})
}
fn create_price_fields(
fields_map: &HashMap<String, Option<String>>,
) -> Result<PriceFields, String> {
let get_field = |key: &str| -> Option<String> { fields_map.get(key).cloned().flatten() };
let parse_float = |key: &str| -> Result<Option<f64>, String> {
match get_field(key) {
Some(val) if !val.is_empty() => val
.parse::<f64>()
.map(Some)
.map_err(|_| format!("Failed to parse {key} as float: {val}")),
_ => Ok(None),
}
};
let dealing_flag = match get_field("DLG_FLAG")
.as_deref()
.map(str::trim)
.filter(|s| !s.is_empty())
.map(|s| s.to_uppercase())
.as_deref()
{
Some("CLOSED") => Some(DealingFlag::Closed),
Some("CALL") => Some(DealingFlag::Call),
Some("DEAL") => Some(DealingFlag::Deal),
Some("EDIT") => Some(DealingFlag::Edit),
Some("CLOSINGSONLY") | Some("CLOSINGONLY") => Some(DealingFlag::ClosingsOnly),
Some("DEALNOEDIT") => Some(DealingFlag::DealNoEdit),
Some("AUCTION") => Some(DealingFlag::Auction),
Some("AUCTIONNOEDIT") => Some(DealingFlag::AuctionNoEdit),
Some("SUSPEND") => Some(DealingFlag::Suspend),
Some(unknown) => return Err(format!("Unknown dealing flag: {unknown}")),
None => None,
};
Ok(PriceFields {
mid_open: parse_float("MID_OPEN")?,
high: parse_float("HIGH")?,
low: parse_float("LOW")?,
bid: parse_float("BID")?,
offer: parse_float("OFFER")?,
change: parse_float("CHANGE")?,
change_pct: parse_float("CHANGE_PCT")?,
market_delay: parse_float("MARKET_DELAY")?,
market_state: get_field("MARKET_STATE"),
update_time: get_field("UPDATE_TIME"),
bid_quote_id: get_field("BIDQUOTEID"),
ask_quote_id: get_field("ASKQUOTEID"),
bid_price1: parse_float("BIDPRICE1")?,
bid_price2: parse_float("BIDPRICE2")?,
bid_price3: parse_float("BIDPRICE3")?,
bid_price4: parse_float("BIDPRICE4")?,
bid_price5: parse_float("BIDPRICE5")?,
ask_price1: parse_float("ASKPRICE1")?,
ask_price2: parse_float("ASKPRICE2")?,
ask_price3: parse_float("ASKPRICE3")?,
ask_price4: parse_float("ASKPRICE4")?,
ask_price5: parse_float("ASKPRICE5")?,
bid_size1: parse_float("BIDSIZE1")?,
bid_size2: parse_float("BIDSIZE2")?,
bid_size3: parse_float("BIDSIZE3")?,
bid_size4: parse_float("BIDSIZE4")?,
bid_size5: parse_float("BIDSIZE5")?,
ask_size1: parse_float("ASKSIZE1")?,
ask_size2: parse_float("ASKSIZE2")?,
ask_size3: parse_float("ASKSIZE3")?,
ask_size4: parse_float("ASKSIZE4")?,
ask_size5: parse_float("ASKSIZE5")?,
currency0: get_field("CURRENCY0"),
currency1: get_field("CURRENCY1"),
currency2: get_field("CURRENCY2"),
currency3: get_field("CURRENCY3"),
currency4: get_field("CURRENCY4"),
currency5: get_field("CURRENCY5"),
c1_bid_size_1: parse_float("C1BIDSIZE1")?,
c1_bid_size_2: parse_float("C1BIDSIZE2")?,
c1_bid_size_3: parse_float("C1BIDSIZE3")?,
c1_bid_size_4: parse_float("C1BIDSIZE4")?,
c1_bid_size_5: parse_float("C1BIDSIZE5")?,
c2_bid_size_1: parse_float("C2BIDSIZE1")?,
c2_bid_size_2: parse_float("C2BIDSIZE2")?,
c2_bid_size_3: parse_float("C2BIDSIZE3")?,
c2_bid_size_4: parse_float("C2BIDSIZE4")?,
c2_bid_size_5: parse_float("C2BIDSIZE5")?,
c3_bid_size_1: parse_float("C3BIDSIZE1")?,
c3_bid_size_2: parse_float("C3BIDSIZE2")?,
c3_bid_size_3: parse_float("C3BIDSIZE3")?,
c3_bid_size_4: parse_float("C3BIDSIZE4")?,
c3_bid_size_5: parse_float("C3BIDSIZE5")?,
c4_bid_size_1: parse_float("C4BIDSIZE1")?,
c4_bid_size_2: parse_float("C4BIDSIZE2")?,
c4_bid_size_3: parse_float("C4BIDSIZE3")?,
c4_bid_size_4: parse_float("C4BIDSIZE4")?,
c4_bid_size_5: parse_float("C4BIDSIZE5")?,
c5_bid_size_1: parse_float("C5BIDSIZE1")?,
c5_bid_size_2: parse_float("C5BIDSIZE2")?,
c5_bid_size_3: parse_float("C5BIDSIZE3")?,
c5_bid_size_4: parse_float("C5BIDSIZE4")?,
c5_bid_size_5: parse_float("C5BIDSIZE5")?,
c1_ask_size_1: parse_float("C1ASKSIZE1")?,
c1_ask_size_2: parse_float("C1ASKSIZE2")?,
c1_ask_size_3: parse_float("C1ASKSIZE3")?,
c1_ask_size_4: parse_float("C1ASKSIZE4")?,
c1_ask_size_5: parse_float("C1ASKSIZE5")?,
c2_ask_size_1: parse_float("C2ASKSIZE1")?,
c2_ask_size_2: parse_float("C2ASKSIZE2")?,
c2_ask_size_3: parse_float("C2ASKSIZE3")?,
c2_ask_size_4: parse_float("C2ASKSIZE4")?,
c2_ask_size_5: parse_float("C2ASKSIZE5")?,
c3_ask_size_1: parse_float("C3ASKSIZE1")?,
c3_ask_size_2: parse_float("C3ASKSIZE2")?,
c3_ask_size_3: parse_float("C3ASKSIZE3")?,
c3_ask_size_4: parse_float("C3ASKSIZE4")?,
c3_ask_size_5: parse_float("C3ASKSIZE5")?,
c4_ask_size_1: parse_float("C4ASKSIZE1")?,
c4_ask_size_2: parse_float("C4ASKSIZE2")?,
c4_ask_size_3: parse_float("C4ASKSIZE3")?,
c4_ask_size_4: parse_float("C4ASKSIZE4")?,
c4_ask_size_5: parse_float("C4ASKSIZE5")?,
c5_ask_size_1: parse_float("C5ASKSIZE1")?,
c5_ask_size_2: parse_float("C5ASKSIZE2")?,
c5_ask_size_3: parse_float("C5ASKSIZE3")?,
c5_ask_size_4: parse_float("C5ASKSIZE4")?,
c5_ask_size_5: parse_float("C5ASKSIZE5")?,
timestamp: parse_float("TIMESTAMP")?,
dealing_flag,
net_chg: parse_float("NET_CHG")?,
net_chg_pct: parse_float("NET_CHG_PCT")?,
delay: parse_float("DELAY")?,
})
}
}
impl From<&ItemUpdate> for PriceData {
fn from(item_update: &ItemUpdate) -> Self {
PriceData::from_item_update(item_update).unwrap_or_else(|e| {
tracing::warn!(error = %e, "failed to convert ItemUpdate to PriceData, returning default");
PriceData::default()
})
}
}