1use std::error::Error as ErrorTrait;
2use std::fmt;
3
4macro_rules! error_kind {
5 ($($name:ident, $message:literal),*) => {
6 #[derive(Debug)]
8 #[non_exhaustive]
9 pub enum ErrorKind {
10 $(
11 $name,
12 )*
13 }
14
15 impl fmt::Display for ErrorKind {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 match self {
18 $(
19 Self::$name => write!(f, $message),
20 )*
21 }
22 }
23 }
24 };
25}
26
27error_kind!(NoRepository, "no repository found");
28
29impl ErrorTrait for ErrorKind {}
30
31#[derive(Debug)]
32pub struct Error {
33 kind: ErrorKind,
34 source: Option<Box<dyn ErrorTrait>>,
35}
36
37impl Error {
38 pub fn new(kind: ErrorKind) -> Self {
39 Self { kind, source: None }
40 }
41
42 pub fn with_source(kind: ErrorKind, source: impl ErrorTrait + 'static) -> Self {
43 Self {
44 kind,
45 source: Some(Box::new(source)),
46 }
47 }
48
49 pub fn kind(&self) -> &ErrorKind {
50 &self.kind
51 }
52}
53
54impl fmt::Display for Error {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 write!(f, "{}", &self.kind)
57 }
58}
59
60impl ErrorTrait for Error {
61 fn source(&self) -> Option<&(dyn ErrorTrait + 'static)> {
62 self.source.as_ref().map(|s| s.as_ref())
63 }
64}