use loonfs_api::{ErrorCode, ErrorDetails, ErrorKind};
use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum ClientError {
#[error("failed to read config: {0}")]
ConfigIo(String),
#[error("failed to decode config: {0}")]
ConfigDecode(String),
#[error("missing `{field}`")]
MissingConfigField { field: &'static str },
#[error("invalid `{field}`: {reason}")]
ConfigValidation { field: &'static str, reason: String },
#[error("invalid namespace path `{0}`")]
InvalidNamespacePath(String),
#[error("invalid commit_id `{0}`")]
InvalidCommitId(String),
#[error("invalid checkpoint_id `{0}`")]
InvalidCheckpointId(String),
#[error("http error: {0}")]
Http(String),
#[error("server returned {status} {code}: {message}")]
Api {
status: u16,
code: String,
feature: Option<String>,
message: String,
request_id: Option<String>,
details: Option<Box<ErrorDetails>>,
},
#[error("i/o error: {0}")]
Io(String),
#[error("json error: {0}")]
Json(String),
}
impl ClientError {
pub fn code(&self) -> Option<ErrorCode> {
match self {
ClientError::Api { code, .. } => ErrorCode::parse(code),
_ => None,
}
}
pub fn kind(&self) -> Option<ErrorKind> {
match self {
ClientError::Api { status, code, .. } => match ErrorCode::parse(code) {
Some(code) => Some(code.kind()),
None => kind_for_status_class(*status),
},
_ => None,
}
}
}
pub(crate) fn kind_for_status_class(status: u16) -> Option<ErrorKind> {
match status {
503 => Some(ErrorKind::Unavailable),
400..=499 => Some(ErrorKind::InvalidRequest),
500..=599 => Some(ErrorKind::Internal),
_ => None,
}
}