pub mod error;
pub mod framing;
pub mod inbound;
pub mod outbound;
pub use error::WireError;
pub use framing::{decode_frame, encode_frame};
pub use inbound::{
CancelOrderWire, CancelReplaceWire, MassCancelWire, NewOrderWire, decode_cancel_order,
decode_cancel_replace, decode_mass_cancel, decode_new_order,
};
pub use outbound::{
BookUpdateWire, ExecReport, TradePrintWire, decode_book_update, decode_exec_report,
decode_trade_print, encode_book_update, encode_exec_report, encode_trade_print, status_to_wire,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
#[non_exhaustive]
pub enum MessageKind {
NewOrder = 0x01,
CancelOrder = 0x02,
CancelReplace = 0x03,
MassCancel = 0x04,
ExecReport = 0x81,
TradePrint = 0x82,
BookUpdate = 0x83,
}
impl MessageKind {
#[inline]
pub fn from_u8(byte: u8) -> Result<Self, WireError> {
match byte {
0x01 => Ok(Self::NewOrder),
0x02 => Ok(Self::CancelOrder),
0x03 => Ok(Self::CancelReplace),
0x04 => Ok(Self::MassCancel),
0x81 => Ok(Self::ExecReport),
0x82 => Ok(Self::TradePrint),
0x83 => Ok(Self::BookUpdate),
other => Err(WireError::UnknownKind(other)),
}
}
#[must_use]
#[inline]
pub const fn as_u8(self) -> u8 {
self as u8
}
#[must_use]
#[inline]
pub const fn is_inbound(self) -> bool {
(self as u8) < 0x80
}
#[must_use]
#[inline]
pub const fn is_outbound(self) -> bool {
(self as u8) >= 0x80
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_u8_round_trip() {
for kind in [
MessageKind::NewOrder,
MessageKind::CancelOrder,
MessageKind::CancelReplace,
MessageKind::MassCancel,
MessageKind::ExecReport,
MessageKind::TradePrint,
MessageKind::BookUpdate,
] {
let byte = kind.as_u8();
let resolved = MessageKind::from_u8(byte).expect("resolve known kind");
assert_eq!(resolved, kind);
}
}
#[test]
fn from_u8_rejects_unknown() {
assert_eq!(
MessageKind::from_u8(0x00),
Err(WireError::UnknownKind(0x00))
);
assert_eq!(
MessageKind::from_u8(0x05),
Err(WireError::UnknownKind(0x05))
);
assert_eq!(
MessageKind::from_u8(0xFF),
Err(WireError::UnknownKind(0xFF))
);
}
#[test]
fn direction_classification() {
assert!(MessageKind::NewOrder.is_inbound());
assert!(!MessageKind::NewOrder.is_outbound());
assert!(MessageKind::ExecReport.is_outbound());
assert!(!MessageKind::ExecReport.is_inbound());
}
}