use std::fmt;
#[derive(Debug, Clone)]
pub struct FieldError {
pub path: String,
pub expected: String,
pub received: String,
pub message: String,
}
#[derive(Debug)]
pub struct BaseError {
pub short_message: String,
pub details: Option<String>,
pub cause: Option<Box<dyn std::error::Error + Send + Sync>>,
}
impl fmt::Display for BaseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(details) = &self.details {
write!(f, "{}\n\nDetails: {}", self.short_message, details)
} else {
write!(f, "{}", self.short_message)
}
}
}
impl std::error::Error for BaseError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.cause.as_ref().map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
}
}
#[derive(Debug)]
pub struct IncurError {
pub message: String,
pub code: String,
pub hint: Option<String>,
pub retryable: bool,
pub exit_code: Option<i32>,
pub cause: Option<Box<dyn std::error::Error + Send + Sync>>,
}
impl fmt::Display for IncurError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for IncurError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.cause.as_ref().map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
}
}
#[derive(Debug)]
pub struct ValidationError {
pub message: String,
pub field_errors: Vec<FieldError>,
pub cause: Option<Box<dyn std::error::Error + Send + Sync>>,
}
impl fmt::Display for ValidationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for ValidationError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.cause.as_ref().map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
}
}
#[derive(Debug)]
pub struct ParseError {
pub message: String,
pub cause: Option<Box<dyn std::error::Error + Send + Sync>>,
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for ParseError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.cause.as_ref().map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
}
}
#[derive(Debug)]
pub enum Error {
Incur(IncurError),
Validation(ValidationError),
Parse(ParseError),
Other(Box<dyn std::error::Error + Send + Sync>),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Incur(e) => write!(f, "{}", e),
Error::Validation(e) => write!(f, "{}", e),
Error::Parse(e) => write!(f, "{}", e),
Error::Other(e) => write!(f, "{}", e),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::Incur(e) => e.source(),
Error::Validation(e) => e.source(),
Error::Parse(e) => e.source(),
Error::Other(e) => e.source(),
}
}
}
impl From<IncurError> for Error {
fn from(e: IncurError) -> Self {
Error::Incur(e)
}
}
impl From<ValidationError> for Error {
fn from(e: ValidationError) -> Self {
Error::Validation(e)
}
}
impl From<ParseError> for Error {
fn from(e: ParseError) -> Self {
Error::Parse(e)
}
}
pub type Result<T> = std::result::Result<T, Error>;