alipan 0.0.19

alipan sdk for rust
Documentation
use reqwest::StatusCode;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "backtrace")]
use std::backtrace::Backtrace;
use std::fmt::{Debug, Display, Formatter};

pub type Error = AlipanError;
pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub struct AlipanError {
    #[cfg(feature = "backtrace")]
    pub backtrace: Backtrace,
    pub inner: ErrorInfo,
}

impl AlipanError {
    pub fn new(info: ErrorInfo) -> Self {
        AlipanError {
            #[cfg(feature = "backtrace")]
            backtrace: Backtrace::capture(),
            inner: info,
        }
    }
    pub fn msg(msg: impl Into<String>) -> Self {
        AlipanError::new(ErrorInfo::Msg(msg.into()))
    }

    pub fn require_param_missing(param: impl Into<String>) -> Self {
        AlipanError::new(ErrorInfo::RequireParamMissing(param.into()))
    }

    pub fn server(code: StatusCode, content: &str) -> Self {
        let decoded: serde_json::Result<ServerError> = serde_json::from_str(content);
        if let Ok(server_error) = decoded {
            AlipanError::new(ErrorInfo::ServerError(server_error))
        } else {
            AlipanError::new(ErrorInfo::Msg(format!(
                "server error: code: {}, content: {}",
                code.as_u16(),
                content,
            )))
        }
    }
}

impl Display for AlipanError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        Debug::fmt(self, f)
    }
}

impl std::error::Error for AlipanError {}

#[derive(Debug)]
pub enum ErrorInfo {
    ReqwestError(reqwest::Error),
    SerdeJsonError(serde_json::Error),
    SerdeJsonErrorPath(serde_path_to_error::Error<serde_json::Error>),
    UrlParseError(url::ParseError),
    ServerError(ServerError),
    Io(std::io::Error),
    // todo: split into more specific error types
    Msg(String),
    RequireParamMissing(String),
    Anyhow(anyhow::Error),
}

impl Display for ErrorInfo {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        Debug::fmt(self, f)
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct ServerError {
    pub code: String,
    pub message: String,
    #[serde(rename = "requestId")]
    pub request_id: String,
}

impl From<reqwest::Error> for AlipanError {
    fn from(e: reqwest::Error) -> Self {
        AlipanError::new(ErrorInfo::ReqwestError(e))
    }
}

impl From<serde_json::Error> for AlipanError {
    fn from(e: serde_json::Error) -> Self {
        AlipanError::new(ErrorInfo::SerdeJsonError(e))
    }
}

impl From<serde_path_to_error::Error<serde_json::Error>> for AlipanError {
    fn from(e: serde_path_to_error::Error<serde_json::Error>) -> Self {
        AlipanError::new(ErrorInfo::SerdeJsonErrorPath(e))
    }
}

impl From<url::ParseError> for AlipanError {
    fn from(e: url::ParseError) -> Self {
        AlipanError::new(ErrorInfo::UrlParseError(e))
    }
}

impl From<ServerError> for AlipanError {
    fn from(e: ServerError) -> Self {
        AlipanError::new(ErrorInfo::ServerError(e))
    }
}

impl From<std::io::Error> for AlipanError {
    fn from(e: std::io::Error) -> Self {
        AlipanError::new(ErrorInfo::Io(e))
    }
}

impl From<anyhow::Error> for AlipanError {
    fn from(e: anyhow::Error) -> Self {
        AlipanError::new(ErrorInfo::Anyhow(e))
    }
}