use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StreamingError {
ChannelFull,
ChannelClosed,
Disconnected,
InvalidConfig(String),
SchemaMismatch {
expected: Vec<String>,
actual: Vec<String>,
},
Timeout,
Internal(String),
}
impl fmt::Display for StreamingError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ChannelFull => write!(f, "channel is full"),
Self::ChannelClosed => write!(f, "channel is closed"),
Self::Disconnected => write!(f, "channel is disconnected"),
Self::InvalidConfig(msg) => write!(f, "invalid configuration: {msg}"),
Self::SchemaMismatch { expected, actual } => {
write!(f, "schema mismatch: expected {expected:?}, got {actual:?}")
}
Self::Timeout => write!(f, "operation timed out"),
Self::Internal(msg) => write!(f, "internal error: {msg}"),
}
}
}
impl std::error::Error for StreamingError {}
#[derive(Debug)]
pub struct TryPushError<T> {
pub value: T,
pub error: StreamingError,
}
impl<T> TryPushError<T> {
#[must_use]
pub fn full(value: T) -> Self {
Self {
value,
error: StreamingError::ChannelFull,
}
}
#[must_use]
pub fn disconnected(value: T) -> Self {
Self {
value,
error: StreamingError::Disconnected,
}
}
#[must_use]
pub fn into_inner(self) -> T {
self.value
}
}
impl<T: fmt::Debug> fmt::Display for TryPushError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "try_push failed: {}", self.error)
}
}
impl<T: fmt::Debug> std::error::Error for TryPushError<T> {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RecvError {
Disconnected,
Timeout,
}
impl fmt::Display for RecvError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Disconnected => write!(f, "channel disconnected"),
Self::Timeout => write!(f, "recv timed out"),
}
}
}
impl std::error::Error for RecvError {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_streaming_error_display() {
assert_eq!(StreamingError::ChannelFull.to_string(), "channel is full");
assert_eq!(
StreamingError::ChannelClosed.to_string(),
"channel is closed"
);
assert_eq!(
StreamingError::Disconnected.to_string(),
"channel is disconnected"
);
assert_eq!(
StreamingError::InvalidConfig("bad".to_string()).to_string(),
"invalid configuration: bad"
);
assert_eq!(StreamingError::Timeout.to_string(), "operation timed out");
}
#[test]
fn test_try_push_error() {
let err = TryPushError::full(42);
assert_eq!(err.into_inner(), 42);
}
#[test]
fn test_recv_error_display() {
assert_eq!(RecvError::Disconnected.to_string(), "channel disconnected");
assert_eq!(RecvError::Timeout.to_string(), "recv timed out");
}
#[test]
fn test_schema_mismatch_display() {
let err = StreamingError::SchemaMismatch {
expected: vec!["a".to_string(), "b".to_string()],
actual: vec!["x".to_string(), "y".to_string()],
};
assert!(err.to_string().contains("schema mismatch"));
}
}