use thiserror::Error;
#[derive(Error, Debug, Clone)]
pub enum WssError {
#[error("Connection Failed")]
WssConnection,
}
#[derive(Error, Debug)]
pub enum ExchangeError {
#[error("WebSocket connection error: {0}")]
WebSocketError(Box<tokio_tungstenite::tungstenite::Error>),
#[error("URL parsing error: {0}")]
UrlParseError(#[from] url::ParseError),
#[error("JSON deserialization error: {0}")]
JsonError(#[from] serde_json::Error),
#[error("Channel send error")]
ChannelSendError,
#[error("An IO error occurred: {0}")]
IoError(#[from] std::io::Error),
}
impl From<tokio_tungstenite::tungstenite::Error> for ExchangeError {
fn from(error: tokio_tungstenite::tungstenite::Error) -> Self {
ExchangeError::WebSocketError(Box::new(error))
}
}
#[derive(Error, Debug, Clone)]
pub enum LevelError {
#[error("Level not found")]
LevelNotFound,
#[error("Level info not available")]
LevelInfoNotAvailable,
#[error("Level deletion not successful")]
LevelDeletionFailed,
#[error("Level modification not successful")]
LevelModificationFailed,
#[error("Level insertion not successful")]
LevelInsertionFailed,
}
#[derive(Error, Debug)]
pub enum OrderError {
#[error("Order not found")]
OrderNotFound,
#[error("Order info not available")]
OrderInfoNotAvailable,
#[error("Order deletion not successful")]
OrderDeletionFailed,
#[error("Order modification not successful")]
OrderModificationFailed,
#[error("Order insertion not successful")]
OrderInsertionFailed,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OrderbookError {
NotInitialized,
SequenceGap { expected: u64, received: u64 },
SymbolMismatch { expected: String, received: String },
ParseError(String),
ContentsError(String),
}
impl std::fmt::Display for OrderbookError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NotInitialized => {
write!(f, "Orderbook not initialized, waiting for snapshot")
}
Self::SequenceGap { expected, received } => {
write!(
f,
"Sequence gap: expected {}, received {}",
expected, received
)
}
Self::SymbolMismatch { expected, received } => {
write!(
f,
"Symbol mismatch: expected {}, received {}",
expected, received
)
}
Self::ParseError(msg) => write!(f, "Parse error: {}", msg),
Self::ContentsError(msg) => write!(f, "Orderbook contents error: {}", msg),
}
}
}
impl std::error::Error for OrderbookError {}
#[derive(Debug)]
pub enum PersistError {
Io(std::io::Error),
Json(serde_json::Error),
#[cfg(feature = "parquet")]
Parquet(parquet::errors::ParquetError),
Parse(String),
#[cfg(feature = "parquet")]
Arrow(arrow::error::ArrowError),
UnsupportedFormat(String),
}
impl std::fmt::Display for PersistError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Io(e) => write!(f, "IO error: {}", e),
Self::Json(e) => write!(f, "JSON error: {}", e),
#[cfg(feature = "parquet")]
Self::Parquet(e) => write!(f, "Parquet error: {}", e),
#[cfg(feature = "parquet")]
Self::Arrow(e) => write!(f, "Arrow error: {}", e),
Self::UnsupportedFormat(s) => write!(f, "Unsupported format: {}", s),
PersistError::Parse(e) => write!(f, "Parse error: {}", e),
}
}
}
impl std::error::Error for PersistError {}
impl From<std::io::Error> for PersistError {
fn from(e: std::io::Error) -> Self {
Self::Io(e)
}
}
impl From<serde_json::Error> for PersistError {
fn from(e: serde_json::Error) -> Self {
Self::Json(e)
}
}
#[cfg(feature = "parquet")]
impl From<parquet::errors::ParquetError> for PersistError {
fn from(e: parquet::errors::ParquetError) -> Self {
Self::Parquet(e)
}
}
#[cfg(feature = "parquet")]
impl From<arrow::error::ArrowError> for PersistError {
fn from(e: arrow::error::ArrowError) -> Self {
Self::Arrow(e)
}
}
#[derive(Error, Debug)]
pub enum LoaderError {
#[error("Empty data: no timestamps to process")]
EmptyData,
#[error("I/O error: {0}")]
IoError(String),
}
#[derive(Error, Debug)]
pub enum TemporalError {
#[error("Empty data: no timestamps to process")]
EmptyData,
#[error("Non-monotonic timestamps at index {index}: prev={prev}, curr={curr}")]
NonMonotonic { index: usize, prev: u64, curr: u64 },
#[error("Gap detected at index {index}: gap={gap_ns}ns > threshold={threshold_ns}ns")]
GapDetected {
index: usize,
gap_ns: u64,
threshold_ns: u64,
},
#[error("Insufficient data: {0}")]
InsufficientData(String),
}