use thiserror::Error;
#[derive(Debug, Error)]
pub enum StreamError {
#[error("Model error: {0}")]
Model(String),
#[error("Failed to parse delta: {0}")]
ParseDelta(String),
#[error("Failed to parse SSE event: {0}")]
ParseSse(String),
#[error("JSON error: {0}")]
Json(#[from] serde_json::Error),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Stream interrupted")]
Interrupted,
#[error("Timeout waiting for delta")]
Timeout,
#[error("Connection closed unexpectedly")]
ConnectionClosed,
#[error("Connection error: {0}")]
Connection(String),
#[error("Send error: {0}")]
Send(String),
#[error("Receive error: {0}")]
Receive(String),
#[error("Serialization error: {0}")]
Serialization(String),
#[error("Invalid state: {0}")]
InvalidState(String),
#[error("SSE buffer exceeded maximum size")]
BufferOverflow,
#[error("{0}")]
Other(String),
}
impl StreamError {
#[must_use]
pub fn is_recoverable(&self) -> bool {
matches!(self, Self::Timeout | Self::Interrupted)
}
pub fn from_err<E: std::fmt::Display>(err: E) -> Self {
Self::Other(err.to_string())
}
}
pub type StreamResult<T> = Result<T, StreamError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = StreamError::Timeout;
assert_eq!(err.to_string(), "Timeout waiting for delta");
}
#[test]
fn test_recoverable() {
assert!(StreamError::Timeout.is_recoverable());
assert!(StreamError::Interrupted.is_recoverable());
assert!(!StreamError::ConnectionClosed.is_recoverable());
}
}