use std::{convert::From, env::VarError, fmt, fmt::Display, num::ParseIntError};
use tonic::{
Status as TonicStatus, metadata::errors::InvalidMetadataValue, transport::Error as TonicError,
};
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
TransportError,
GrpcError(GrpcError),
ParseIntError,
VarError,
SerializationError,
InvalidEndpoint(String),
ConnectTimeout,
InvalidMetadata,
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}
pub(crate) fn sanitize_endpoint_for_diagnostics(input: &str) -> String {
let trimmed = input.trim();
if trimmed.is_empty() {
return "<empty>".to_string();
}
let (scheme, rest) = match trimmed.split_once("://") {
Some((s, r)) => (Some(s), r),
None => (None, trimmed),
};
let authority = rest.split(['/', '?', '#']).next().unwrap_or(rest);
let host_port = authority.rsplit('@').next().unwrap_or(authority).trim();
if host_port.is_empty() {
"<invalid>".to_string()
} else if let Some(scheme) = scheme {
format!("{scheme}://{host_port}")
} else {
host_port.to_string()
}
}
impl std::error::Error for Error {}
impl From<ParseIntError> for Error {
fn from(_error: ParseIntError) -> Self {
Error::ParseIntError
}
}
impl From<VarError> for Error {
fn from(_error: VarError) -> Self {
Error::VarError
}
}
impl From<TonicError> for Error {
fn from(_error: TonicError) -> Self {
Error::TransportError
}
}
impl From<TonicStatus> for Error {
fn from(error: TonicStatus) -> Self {
Error::GrpcError(GrpcError { _status: error })
}
}
impl From<InvalidMetadataValue> for Error {
fn from(_error: InvalidMetadataValue) -> Self {
Error::InvalidMetadata
}
}
#[derive(Debug)]
pub struct GrpcError {
_status: TonicStatus,
}
impl Display for GrpcError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}