use std::fmt; use std::path::PathBuf; use crate::error::BabyError; #[derive(Debug)] pub enum ServerError { Unimplemented(&'static str), Unauthorised { scheme: &'static str, reason: String, }, InvalidRequest(String), PayloadTooLarge { cap_bytes: u64, actual_bytes: u64, }, Io { path: PathBuf, source: std::io::Error, }, Pipe(String), Backend(BabyError), Cancelled, } impl fmt::Display for ServerError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Unimplemented(what) => write!(f, "not yet implemented: {}", what), Self::Unauthorised { scheme, reason } => { write!(f, "unauthorised ({scheme}): {}", reason) } Self::InvalidRequest(msg) => write!(f, "invalid server request: {}", msg), Self::PayloadTooLarge { cap_bytes, actual_bytes, } => write!( f, "output exceeds cap: {} bytes > {} bytes cap", actual_bytes, cap_bytes ), Self::Io { path, source } => { write!(f, "io error at `{}`: {}", path.display(), source) } Self::Pipe(msg) => write!(f, "server pipe error: {}", msg), Self::Backend(err) => write!(f, "backend error: {}", err), Self::Cancelled => write!(f, "server stream was cancelled"), } } } impl std::error::Error for ServerError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Self::Io { source, .. } => Some(source), Self::Backend(err) => Some(err), _ => None, } } } impl From for ServerError { fn from(err: BabyError) -> Self { Self::Backend(err) } } impl From for ServerError { fn from(source: std::io::Error) -> Self { Self::Io { path: PathBuf::new(), source, } } } pub type ServerResult = std::result::Result;