1//! Declare tor relay specific errors.
23use std::fmt::{self, Display};
45use thiserror::Error;
6use tor_error::{ErrorKind, HasKind};
78/// Main high-level error type for the Arti Tor relay.
9///
10/// If you need to handle different types of errors differently, use the
11/// [`kind`](`tor_error::HasKind::kind`) trait method to check what kind of
12/// error it is.
13///
14/// Note that although this type implements that standard
15/// [`Error`](trait@std::error::Error) trait, the output of that trait's methods are
16/// not covered by semantic versioning. Specifically: you should not rely on
17/// the specific output of `Display`, `Debug`, or `Error::source()` when run on
18/// this type; it may change between patch versions without notification.
19#[derive(Error, Clone, Debug)]
20pub(crate) struct Error {
21/// The actual error.
22#[source]
23detail: Box<ErrorDetail>,
24}
2526impl From<ErrorDetail> for Error {
27fn from(detail: ErrorDetail) -> Error {
28 Error {
29 detail: detail.into(),
30 }
31 }
32}
3334/// Represents errors that can occur while doing Tor operations.
35///
36/// This enumeration is the inner view of an Error.
37///
38/// Instead of looking at the type, you should try to use the [`kind`](`tor_error::HasKind::kind`)
39/// trait method to distinguish among different kinds of Error.
40#[cfg_attr(test, derive(strum::EnumDiscriminants))]
41#[cfg_attr(test, strum_discriminants(vis(pub(crate))))]
42#[derive(Error, Clone, Debug)]
43#[non_exhaustive]
44pub(crate) enum ErrorDetail {
45/// A programming problem, either in our code or the code calling it.
46#[error("Programming problem")]
47Bug(#[from] tor_error::Bug),
48/// Building configuration failed.
49#[error("Problem with configuration")]
50Configuration(#[from] tor_config::ConfigBuildError),
51/// Error from the KeyMgr crate.
52#[error("KeyMgr error")]
53KeyMgr(#[from] tor_keymgr::Error),
54}
5556impl Error {
57/// Consume this error and return the underlying error detail object.
58// TODO RELAY: remove
59#[allow(unused)]
60pub(crate) fn into_detail(self) -> ErrorDetail {
61*self.detail
62 }
63}
6465impl Display for Error {
66fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67write!(f, "tor: {}: {}", self.detail.kind(), &self.detail)
68 }
69}
7071impl tor_error::HasKind for Error {
72fn kind(&self) -> ErrorKind {
73self.detail.kind()
74 }
75}
7677impl tor_error::HasKind for ErrorDetail {
78fn kind(&self) -> ErrorKind {
79match self {
80 ErrorDetail::Bug(e) => e.kind(),
81 ErrorDetail::Configuration(e) => e.kind(),
82 ErrorDetail::KeyMgr(e) => e.kind(),
83 }
84 }
85}
8687#[cfg(test)]
88mod test {
89// @@ begin test lint list maintained by maint/add_warning @@
90#![allow(clippy::bool_assert_comparison)]
91 #![allow(clippy::clone_on_copy)]
92 #![allow(clippy::dbg_macro)]
93 #![allow(clippy::mixed_attributes_style)]
94 #![allow(clippy::print_stderr)]
95 #![allow(clippy::print_stdout)]
96 #![allow(clippy::single_char_pattern)]
97 #![allow(clippy::unwrap_used)]
98 #![allow(clippy::unchecked_duration_subtraction)]
99 #![allow(clippy::useless_vec)]
100 #![allow(clippy::needless_pass_by_value)]
101//! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
102use super::*;
103104/// This code makes sure that our errors implement all the traits we want.
105#[test]
106fn traits_ok() {
107// I had intended to use `assert_impl`, but that crate can't check whether
108 // a type is 'static.
109fn assert<
110 T: Send + Sync + Clone + std::fmt::Debug + Display + std::error::Error + 'static,
111 >() {
112 }
113fn check() {
114 assert::<Error>();
115 assert::<ErrorDetail>();
116 }
117 check(); // doesn't do anything, but avoids "unused function" warnings.
118}
119}