use std::{error::Error, fmt}; use crate::HYPER3D_PROVIDER; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Hyper3dStatusHint { BadRequest, ServiceUnavailable, BadGateway, GatewayTimeout, } #[derive(Clone, Debug)] pub enum Hyper3dError { InvalidConfig { provider: &'static str, reason: Option<&'static str>, message: String, }, InvalidRequest { provider: &'static str, field: Option<&'static str>, message: String, allowed: Option>, }, Request { provider: &'static str, message: String, endpoint: Option, timeout: bool, connect: bool, request: bool, body: bool, status_code: Option, source: Option, }, Upstream { provider: &'static str, message: String, upstream_status: u16, raw_excerpt: String, }, ResponseParse { provider: &'static str, message: String, raw_excerpt: String, }, MissingField { provider: &'static str, message: String, }, } impl Hyper3dError { pub fn provider(&self) -> &'static str { match self { Self::InvalidConfig { provider, .. } | Self::InvalidRequest { provider, .. } | Self::Request { provider, .. } | Self::Upstream { provider, .. } | Self::ResponseParse { provider, .. } | Self::MissingField { provider, .. } => provider, } } pub fn message(&self) -> &str { match self { Self::InvalidConfig { message, .. } | Self::InvalidRequest { message, .. } | Self::Request { message, .. } | Self::Upstream { message, .. } | Self::ResponseParse { message, .. } | Self::MissingField { message, .. } => message, } } pub fn status_hint(&self) -> Hyper3dStatusHint { match self { Self::InvalidConfig { .. } => Hyper3dStatusHint::ServiceUnavailable, Self::InvalidRequest { .. } => Hyper3dStatusHint::BadRequest, Self::Request { timeout, .. } if *timeout => Hyper3dStatusHint::GatewayTimeout, Self::Request { .. } | Self::Upstream { .. } | Self::ResponseParse { .. } | Self::MissingField { .. } => Hyper3dStatusHint::BadGateway, } } pub fn invalid_config(reason: &'static str, message: impl Into) -> Self { Self::InvalidConfig { provider: HYPER3D_PROVIDER, reason: Some(reason), message: message.into(), } } pub(crate) fn invalid_request(field: Option<&'static str>, message: impl Into) -> Self { Self::InvalidRequest { provider: HYPER3D_PROVIDER, field, message: message.into(), allowed: None, } } pub(crate) fn invalid_request_allowed( field: &'static str, message: impl Into, allowed: &[&str], ) -> Self { Self::InvalidRequest { provider: HYPER3D_PROVIDER, field: Some(field), message: message.into(), allowed: Some(allowed.iter().map(|value| value.to_string()).collect()), } } pub(crate) fn request( message: impl Into, endpoint: Option, timeout: bool, connect: bool, request: bool, body: bool, status_code: Option, source: Option, ) -> Self { Self::Request { provider: HYPER3D_PROVIDER, message: message.into(), endpoint, timeout, connect, request, body, status_code, source, } } pub(crate) fn upstream( message: impl Into, upstream_status: u16, raw_excerpt: impl Into, ) -> Self { Self::Upstream { provider: HYPER3D_PROVIDER, message: message.into(), upstream_status, raw_excerpt: raw_excerpt.into(), } } pub(crate) fn response_parse( message: impl Into, raw_excerpt: impl Into, ) -> Self { Self::ResponseParse { provider: HYPER3D_PROVIDER, message: message.into(), raw_excerpt: raw_excerpt.into(), } } pub(crate) fn missing_field(message: impl Into) -> Self { Self::MissingField { provider: HYPER3D_PROVIDER, message: message.into(), } } } impl fmt::Display for Hyper3dError { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(self.message()) } } impl Error for Hyper3dError {}