use crate::errors::PriceLevelError;
use crate::price_level::level::PriceLevel;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
use std::sync::Arc;
#[derive(Debug)]
pub struct OrderBookEntry {
pub level: Arc<PriceLevel>,
pub index: usize,
}
impl OrderBookEntry {
#[allow(dead_code)]
#[must_use]
pub fn new(level: Arc<PriceLevel>, index: usize) -> Self {
Self { level, index }
}
#[must_use]
pub fn price(&self) -> u128 {
self.level.price()
}
#[must_use]
pub fn visible_quantity(&self) -> u64 {
self.level.visible_quantity()
}
pub fn total_quantity(&self) -> Result<u64, PriceLevelError> {
self.level.total_quantity()
}
#[allow(dead_code)]
#[must_use]
pub fn order_count(&self) -> usize {
self.level.order_count()
}
}
impl PartialEq for OrderBookEntry {
fn eq(&self, other: &Self) -> bool {
self.price() == other.price()
}
}
impl Eq for OrderBookEntry {}
impl PartialOrd for OrderBookEntry {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for OrderBookEntry {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.price().cmp(&other.price())
}
}
impl Serialize for OrderBookEntry {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct("OrderBookEntry", 3)?;
state.serialize_field("price", &self.price())?;
state.serialize_field("visible_quantity", &self.visible_quantity())?;
let total_quantity = self.total_quantity().map_err(serde::ser::Error::custom)?;
state.serialize_field("total_quantity", &total_quantity)?;
state.serialize_field("index", &self.index)?;
state.end()
}
}
impl<'de> Deserialize<'de> for OrderBookEntry {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
#[derive(Deserialize)]
struct Wrapper {
price: u128,
index: usize,
}
let wrapper = Wrapper::deserialize(deserializer)?;
let level = Arc::new(PriceLevel::new(wrapper.price));
Ok(OrderBookEntry {
level,
index: wrapper.index,
})
}
}
impl fmt::Display for OrderBookEntry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let total_quantity = self.total_quantity().map_err(|_| fmt::Error)?;
write!(
f,
"OrderBookEntry:price={};visible_quantity={};total_quantity={};index={}",
self.price(),
self.visible_quantity(),
total_quantity,
self.index
)
}
}
impl FromStr for OrderBookEntry {
type Err = PriceLevelError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = s.split(':').collect();
if parts.len() != 2 || parts[0] != "OrderBookEntry" {
return Err(PriceLevelError::InvalidFormat);
}
let mut fields = std::collections::HashMap::new();
for field_pair in parts[1].split(';') {
let kv: Vec<&str> = field_pair.split('=').collect();
if kv.len() == 2 {
fields.insert(kv[0], kv[1]);
}
}
let get_field = |field: &str| -> Result<&str, PriceLevelError> {
match fields.get(field) {
Some(result) => Ok(*result),
None => Err(PriceLevelError::MissingField(field.to_string())),
}
};
let parse_u128 = |field: &str, value: &str| -> Result<u128, PriceLevelError> {
value
.parse::<u128>()
.map_err(|_| PriceLevelError::InvalidFieldValue {
field: field.to_string(),
value: value.to_string(),
})
};
let parse_usize = |field: &str, value: &str| -> Result<usize, PriceLevelError> {
value
.parse::<usize>()
.map_err(|_| PriceLevelError::InvalidFieldValue {
field: field.to_string(),
value: value.to_string(),
})
};
let price_str = get_field("price")?;
let price = parse_u128("price", price_str)?;
let index_str = get_field("index")?;
let index = parse_usize("index", index_str)?;
let level = Arc::new(PriceLevel::new(price));
Ok(OrderBookEntry { level, index })
}
}