use std::convert::Infallible;
use std::fmt::{Display, Formatter};
macro_rules! fmt {
($code:ident, $($arg:tt)*) => {
crate::error::Error::new(
crate::error::ErrorCode::$code,
format!($($arg)*))
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ErrorCode {
CouldNotResolveAddr,
InvalidApiCall,
SocketError,
InvalidUtf8,
InvalidName,
InvalidTimestamp,
AuthError,
TlsError,
HttpNotSupported,
ServerFlushError,
ConfigError,
ArrayError,
ProtocolVersionError,
InvalidDecimal,
}
#[derive(Debug, PartialEq)]
pub struct Error {
code: ErrorCode,
msg: String,
}
impl Error {
pub fn new<S: Into<String>>(code: ErrorCode, msg: S) -> Error {
Error {
code,
msg: msg.into(),
}
}
#[cfg(feature = "sync-sender-http")]
pub(crate) fn from_ureq_error(err: ureq::Error, url: &str) -> Error {
match err {
ureq::Error::StatusCode(code) => {
if code == 404 {
fmt!(
HttpNotSupported,
"Could not flush buffer: HTTP endpoint does not support ILP."
)
} else if [401, 403].contains(&code) {
fmt!(
AuthError,
"Could not flush buffer: HTTP endpoint authentication error [code: {}]",
code
)
} else {
fmt!(SocketError, "Could not flush buffer: {}: {}", url, err)
}
}
e => {
fmt!(SocketError, "Could not flush buffer: {}: {}", url, e)
}
}
}
pub fn code(&self) -> ErrorCode {
self.code
}
pub fn msg(&self) -> &str {
&self.msg
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.msg)
}
}
impl std::error::Error for Error {}
impl From<Infallible> for Error {
fn from(_: Infallible) -> Self {
unreachable!()
}
}
pub type Result<T> = std::result::Result<T, Error>;
pub(crate) use fmt;