use pricelevel::Side;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PriceLevelChangedEvent {
pub side: Side,
pub price: u128,
pub quantity: u64,
#[serde(default)]
pub engine_seq: u64,
}
pub type PriceLevelChangedListener = Arc<dyn Fn(PriceLevelChangedEvent) + Send + Sync>;
#[cfg(test)]
mod tests {
use super::*;
fn sample_event(engine_seq: u64) -> PriceLevelChangedEvent {
PriceLevelChangedEvent {
side: Side::Buy,
price: 50_000,
quantity: 250,
engine_seq,
}
}
#[test]
fn test_engine_seq_default_zero_via_struct_literal() {
let event = PriceLevelChangedEvent {
side: Side::Sell,
price: 1,
quantity: 1,
engine_seq: 0,
};
assert_eq!(event.engine_seq, 0);
}
#[test]
fn test_json_roundtrip_preserves_engine_seq() {
let event = sample_event(123);
let bytes = serde_json::to_vec(&event).expect("serialize event");
let decoded: PriceLevelChangedEvent =
serde_json::from_slice(&bytes).expect("deserialize event");
assert_eq!(decoded, event);
assert_eq!(decoded.engine_seq, 123);
}
#[test]
fn test_json_missing_engine_seq_defaults_zero() {
let json = r#"{"side":"Buy","price":42,"quantity":10}"#;
let decoded: PriceLevelChangedEvent =
serde_json::from_str(json).expect("deserialize legacy event");
assert_eq!(
decoded.engine_seq, 0,
"missing engine_seq must default to 0 via #[serde(default)]"
);
assert_eq!(decoded.price, 42);
assert_eq!(decoded.quantity, 10);
}
#[cfg(feature = "bincode")]
#[test]
fn test_bincode_roundtrip_preserves_engine_seq() {
use bincode::config::standard;
use bincode::serde::{decode_from_slice, encode_to_vec};
let event = sample_event(9_000);
let bytes = encode_to_vec(&event, standard()).expect("bincode encode");
let (decoded, consumed): (PriceLevelChangedEvent, usize) =
decode_from_slice(&bytes, standard()).expect("bincode decode");
assert_eq!(consumed, bytes.len(), "no trailing bytes expected");
assert_eq!(decoded, event);
assert_eq!(decoded.engine_seq, 9_000);
}
}