use std::fmt;
use std::process;
#[derive(Debug)]
pub struct CtlError {
pub kind: ErrorKind,
pub message: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorKind {
Usage = 1,
Api = 2,
Validation = 3,
}
impl ErrorKind {
pub fn code(self) -> i32 {
self as i32
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Usage => f.write_str("usage"),
Self::Api => f.write_str("api"),
Self::Validation => f.write_str("validation"),
}
}
}
impl CtlError {
pub fn usage(msg: impl Into<String>) -> Self {
Self {
kind: ErrorKind::Usage,
message: msg.into(),
}
}
pub fn api(msg: impl Into<String>) -> Self {
Self {
kind: ErrorKind::Api,
message: msg.into(),
}
}
pub fn validation(msg: impl Into<String>) -> Self {
Self {
kind: ErrorKind::Validation,
message: msg.into(),
}
}
pub fn exit(&self) -> ! {
eprintln!("cellctl: {}: {}", self.kind, self.message);
process::exit(self.kind.code())
}
}
impl fmt::Display for CtlError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.kind, self.message)
}
}
impl std::error::Error for CtlError {}
impl From<anyhow::Error> for CtlError {
fn from(e: anyhow::Error) -> Self {
Self::api(e.to_string())
}
}
impl From<reqwest::Error> for CtlError {
fn from(e: reqwest::Error) -> Self {
Self::api(format!("http: {e}"))
}
}
impl From<std::io::Error> for CtlError {
fn from(e: std::io::Error) -> Self {
Self::usage(format!("io: {e}"))
}
}
impl From<serde_yaml::Error> for CtlError {
fn from(e: serde_yaml::Error) -> Self {
Self::validation(format!("yaml: {e}"))
}
}
impl From<serde_json::Error> for CtlError {
fn from(e: serde_json::Error) -> Self {
Self::api(format!("json: {e}"))
}
}
pub type CtlResult<T> = Result<T, CtlError>;