use std::fmt;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, DetectorError>;
#[derive(Error, Debug)]
pub enum DetectorError {
#[error("Need more data for detection, minimum required: {0} bytes")]
NeedMoreData(usize),
#[error("Insufficient data: {0}")]
InsufficientData(String),
#[error("Data too large: {0}")]
DataTooLarge(String),
#[error("No protocol detected: {0}")]
NoProtocolDetected(String),
#[error("Protocol detection failed: {reason}")]
DetectionFailed {
reason: String,
},
#[error("Unsupported protocol: {protocol}")]
UnsupportedProtocol {
protocol: String,
},
#[error("Protocol upgrade failed: {from} -> {to}, reason: {reason}")]
UpgradeFailed {
from: String,
to: String,
reason: String,
},
#[error("Configuration error: {message}")]
ConfigError {
message: String,
},
#[error("I/O error: {0}")]
IoError(#[from] std::io::Error),
#[error("Network error: {message}")]
NetworkError {
message: String,
},
#[error("Operation timed out after {timeout_ms}ms")]
Timeout {
timeout_ms: u64,
},
#[error("Buffer error: {message}")]
BufferError {
message: String,
},
#[cfg(feature = "simd-accel")]
#[error("SIMD operation error: {message}")]
SimdError {
message: String,
},
#[error("Internal error: {message}")]
InternalError {
message: String,
},
}
impl DetectorError {
pub fn detection_failed<S: Into<String>>(reason: S) -> Self {
Self::DetectionFailed {
reason: reason.into(),
}
}
pub fn unsupported_protocol<S: Into<String>>(protocol: S) -> Self {
Self::UnsupportedProtocol {
protocol: protocol.into(),
}
}
pub fn upgrade_failed<S1, S2, S3>(from: S1, to: S2, reason: S3) -> Self
where
S1: Into<String>,
S2: Into<String>,
S3: Into<String>,
{
Self::UpgradeFailed {
from: from.into(),
to: to.into(),
reason: reason.into(),
}
}
pub fn config_error<S: Into<String>>(message: S) -> Self {
Self::ConfigError {
message: message.into(),
}
}
pub fn network_error<S: Into<String>>(message: S) -> Self {
Self::NetworkError {
message: message.into(),
}
}
pub fn timeout(timeout_ms: u64) -> Self {
Self::Timeout { timeout_ms }
}
pub fn buffer_error<S: Into<String>>(message: S) -> Self {
Self::BufferError {
message: message.into(),
}
}
#[cfg(feature = "simd-accel")]
pub fn simd_error<S: Into<String>>(message: S) -> Self {
Self::SimdError {
message: message.into(),
}
}
pub fn internal_error<S: Into<String>>(message: S) -> Self {
Self::InternalError {
message: message.into(),
}
}
pub fn is_recoverable(&self) -> bool {
matches!(
self,
Self::NeedMoreData(_)
| Self::DetectionFailed { .. }
| Self::Timeout { .. }
| Self::NetworkError { .. }
)
}
pub fn is_config_error(&self) -> bool {
matches!(
self,
Self::ConfigError { .. } | Self::UnsupportedProtocol { .. }
)
}
pub fn error_code(&self) -> u32 {
match self {
Self::NeedMoreData(_) => 1001,
Self::InsufficientData(_) => 1002,
Self::DataTooLarge(_) => 1003,
Self::NoProtocolDetected(_) => 1004,
Self::DetectionFailed { .. } => 1005,
Self::UnsupportedProtocol { .. } => 1006,
Self::UpgradeFailed { .. } => 1007,
Self::ConfigError { .. } => 1008,
Self::IoError(_) => 1009,
Self::NetworkError { .. } => 1010,
Self::Timeout { .. } => 1011,
Self::BufferError { .. } => 1012,
#[cfg(feature = "simd-accel")]
Self::SimdError { .. } => 1013,
Self::InternalError { .. } => 1999,
}
}
}
impl From<anyhow::Error> for DetectorError {
fn from(err: anyhow::Error) -> Self {
Self::internal_error(err.to_string())
}
}
impl From<serde_json::Error> for DetectorError {
fn from(err: serde_json::Error) -> Self {
Self::config_error(format!("JSON error: {}", err))
}
}