x_core/
errors.rs

1// Copyright (c) Aptos
2// SPDX-License-Identifier: Apache-2.0
3
4use camino::{Utf8Path, Utf8PathBuf};
5use hex::FromHexError;
6use serde::{de, ser};
7use std::{borrow::Cow, error, fmt, io, process::ExitStatus, result, str::Utf8Error};
8
9/// Type alias for the return type for `run` methods.
10pub type Result<T, E = SystemError> = result::Result<T, E>;
11
12/// A system error that happened while running a lint.
13#[derive(Debug)]
14#[non_exhaustive]
15pub enum SystemError {
16    CwdNotInProjectRoot {
17        current_dir: Utf8PathBuf,
18        project_root: &'static Utf8Path,
19    },
20    Exec {
21        cmd: &'static str,
22        status: ExitStatus,
23    },
24    GitRoot(Cow<'static, str>),
25    FromHex {
26        context: Cow<'static, str>,
27        err: FromHexError,
28    },
29    Guppy {
30        context: Cow<'static, str>,
31        err: guppy::Error,
32    },
33    Io {
34        context: Cow<'static, str>,
35        err: io::Error,
36    },
37    NonUtf8Path {
38        path: Vec<u8>,
39        err: Utf8Error,
40    },
41    Serde {
42        context: Cow<'static, str>,
43        err: Box<dyn error::Error + Send + Sync>,
44    },
45}
46
47impl SystemError {
48    pub fn io(context: impl Into<Cow<'static, str>>, err: io::Error) -> Self {
49        SystemError::Io {
50            context: context.into(),
51            err,
52        }
53    }
54
55    pub fn guppy(context: impl Into<Cow<'static, str>>, err: guppy::Error) -> Self {
56        SystemError::Guppy {
57            context: context.into(),
58            err,
59        }
60    }
61
62    pub fn git_root(msg: impl Into<Cow<'static, str>>) -> Self {
63        SystemError::GitRoot(msg.into())
64    }
65
66    pub fn from_hex(context: impl Into<Cow<'static, str>>, err: FromHexError) -> Self {
67        SystemError::FromHex {
68            context: context.into(),
69            err,
70        }
71    }
72
73    pub fn de(
74        context: impl Into<Cow<'static, str>>,
75        err: impl de::Error + Send + Sync + 'static,
76    ) -> Self {
77        SystemError::Serde {
78            context: context.into(),
79            err: Box::new(err),
80        }
81    }
82
83    pub fn ser(
84        context: impl Into<Cow<'static, str>>,
85        err: impl ser::Error + Send + Sync + 'static,
86    ) -> Self {
87        SystemError::Serde {
88            context: context.into(),
89            err: Box::new(err),
90        }
91    }
92}
93
94impl fmt::Display for SystemError {
95    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96        match self {
97            SystemError::CwdNotInProjectRoot {
98                current_dir,
99                project_root,
100            } => write!(
101                f,
102                "current dir {} not in project root {}",
103                current_dir, project_root,
104            ),
105            SystemError::Exec { cmd, status } => match status.code() {
106                Some(code) => write!(f, "'{}' failed with exit code {}", cmd, code),
107                None => write!(f, "'{}' terminated by signal", cmd),
108            },
109            SystemError::GitRoot(s) => write!(f, "git root error: {}", s),
110            SystemError::NonUtf8Path { path, .. } => {
111                write!(f, "non-UTF-8 path \"{}\"", String::from_utf8_lossy(path))
112            }
113            SystemError::FromHex { context, .. }
114            | SystemError::Io { context, .. }
115            | SystemError::Serde { context, .. }
116            | SystemError::Guppy { context, .. } => write!(f, "while {}", context),
117        }
118    }
119}
120
121impl error::Error for SystemError {
122    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
123        match self {
124            SystemError::CwdNotInProjectRoot { .. }
125            | SystemError::Exec { .. }
126            | SystemError::GitRoot(_) => None,
127            SystemError::FromHex { err, .. } => Some(err),
128            SystemError::Io { err, .. } => Some(err),
129            SystemError::Guppy { err, .. } => Some(err),
130            SystemError::NonUtf8Path { err, .. } => Some(err),
131            SystemError::Serde { err, .. } => Some(err.as_ref()),
132        }
133    }
134}