use std::fmt;
use std::net::SocketAddr;
#[derive(Debug)]
#[non_exhaustive]
pub(crate) struct ServeError {
repr: ServeErrorRepr,
}
#[derive(Debug)]
enum ServeErrorRepr {
MissingToken,
AllowedHosts { addr: SocketAddr },
Bind {
addr: SocketAddr,
source: std::io::Error,
},
Http { source: std::io::Error },
Stdio {
source: Box<dyn std::error::Error + Send + Sync>,
},
}
impl ServeError {
pub(crate) fn missing_token() -> ServeError {
ServeError {
repr: ServeErrorRepr::MissingToken,
}
}
pub(crate) fn allowed_hosts(addr: SocketAddr) -> ServeError {
ServeError {
repr: ServeErrorRepr::AllowedHosts { addr },
}
}
pub(crate) fn bind(addr: SocketAddr, source: std::io::Error) -> ServeError {
ServeError {
repr: ServeErrorRepr::Bind { addr, source },
}
}
pub(crate) fn http(source: std::io::Error) -> ServeError {
ServeError {
repr: ServeErrorRepr::Http { source },
}
}
pub(crate) fn stdio(source: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> ServeError {
ServeError {
repr: ServeErrorRepr::Stdio {
source: source.into(),
},
}
}
}
impl fmt::Display for ServeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.repr {
ServeErrorRepr::MissingToken => {
f.write_str("[server].token is required to serve over http")
}
ServeErrorRepr::AllowedHosts { addr } => write!(
f,
"[server].bind {addr} is not loopback, so [server].allowed_hosts must enumerate the authorities clients reach it by"
),
ServeErrorRepr::Bind { addr, .. } => write!(f, "bind {addr}"),
ServeErrorRepr::Http { .. } => f.write_str("serve http"),
ServeErrorRepr::Stdio { .. } => f.write_str("serve stdio"),
}
}
}
impl std::error::Error for ServeError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match &self.repr {
ServeErrorRepr::Bind { source, .. } | ServeErrorRepr::Http { source } => Some(source),
ServeErrorRepr::Stdio { source } => Some(source.as_ref()),
ServeErrorRepr::MissingToken | ServeErrorRepr::AllowedHosts { .. } => None,
}
}
}
#[cfg(test)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub(crate) enum ServeErrorKind {
MissingToken,
AllowedHosts,
Bind,
Http,
Stdio,
}
#[cfg(test)]
impl ServeError {
#[must_use]
pub(crate) fn kind(&self) -> ServeErrorKind {
match &self.repr {
ServeErrorRepr::MissingToken => ServeErrorKind::MissingToken,
ServeErrorRepr::AllowedHosts { .. } => ServeErrorKind::AllowedHosts,
ServeErrorRepr::Bind { .. } => ServeErrorKind::Bind,
ServeErrorRepr::Http { .. } => ServeErrorKind::Http,
ServeErrorRepr::Stdio { .. } => ServeErrorKind::Stdio,
}
}
}