use std::fmt;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ErrorKind {
Io,
NotAgs4,
BadDictionary,
Emit,
InvalidArgument,
Other,
}
impl ErrorKind {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
ErrorKind::Io => "io",
ErrorKind::NotAgs4 => "not_ags4",
ErrorKind::BadDictionary => "bad_dict",
ErrorKind::Emit => "emit",
ErrorKind::InvalidArgument => "invalid_argument",
ErrorKind::Other => "error",
}
}
#[must_use]
pub fn exit_code(self) -> i32 {
match self {
ErrorKind::Io => 2,
ErrorKind::NotAgs4 | ErrorKind::BadDictionary | ErrorKind::InvalidArgument => 3,
ErrorKind::Emit => 4,
ErrorKind::Other => 1,
}
}
}
pub struct Error {
kind: ErrorKind,
message: String,
source: Option<Source>,
}
struct Source(String);
impl fmt::Debug for Source {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl fmt::Display for Source {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl std::error::Error for Source {}
impl Error {
pub(crate) fn new(kind: ErrorKind, message: impl Into<String>) -> Error {
Error {
kind,
message: message.into(),
source: None,
}
}
pub(crate) fn with_source(
kind: ErrorKind,
message: impl Into<String>,
source: impl fmt::Display,
) -> Error {
Error {
kind,
message: message.into(),
source: Some(Source(source.to_string())),
}
}
#[must_use]
pub fn kind(&self) -> ErrorKind {
self.kind
}
#[must_use]
pub fn kind_str(&self) -> &'static str {
self.kind.as_str()
}
#[must_use]
pub fn exit_code(&self) -> i32 {
self.kind.exit_code()
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.message)
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Error")
.field("kind", &self.kind)
.field("message", &self.message)
.field("source", &self.source)
.finish()
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.source
.as_ref()
.map(|s| s as &(dyn std::error::Error + 'static))
}
}