summaryrefslogtreecommitdiffstats
path: root/src/utils/error.rs
blob: 8f8da789441c0b9a8b7153c223cd29ad870a2af2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use beef::Cow;
use std::result;
use thiserror::Error;

#[cfg(target_os = "linux")]
use procfs::ProcError;

/// A type alias for handling errors related to Bottom.
pub type Result<T> = result::Result<T, BottomError>;

/// An error that can occur while Bottom runs.
#[derive(Debug, Error)]
pub enum BottomError {
    /// An error when there is an IO exception.
    #[error("IO exception, {0}")]
    InvalidIo(String),
    /// An error when the heim library encounters a problem.
    #[error("Error caused by Heim, {0}")]
    InvalidHeim(String),
    /// An error when the Crossterm library encounters a problem.
    #[error("Error caused by Crossterm, {0}")]
    CrosstermError(String),
    /// An error to represent generic errors.
    #[error("Generic error, {0}")]
    GenericError(String),
    /// An error to represent errors with fern.
    #[error("Fern error, {0}")]
    FernError(String),
    /// An error to represent errors with the config.
    #[error("Configuration file error, {0}")]
    ConfigError(String),
    /// An error to represent errors with converting between data types.
    #[error("Conversion error, {0}")]
    ConversionError(String),
    /// An error to represent errors with querying.
    #[error("Query error, {0}")]
    QueryError(Cow<'static, str>),
    /// An error that just signifies something minor went wrong; no message.
    #[error("Minor error.")]
    MinorError,
    /// An error to represent errors with procfs
    #[cfg(target_os = "linux")]
    #[error("Procfs error, {0}")]
    ProcfsError(String),
}

impl From<std::io::Error> for BottomError {
    fn from(err: std::io::Error) -> Self {
        BottomError::InvalidIo(err.to_string())
    }
}

impl From<heim::Error> for BottomError {
    fn from(err: heim::Error) -> Self {
        BottomError::InvalidHeim(err.to_string())
    }
}

impl From<crossterm::ErrorKind> for BottomError {
    fn from(err: crossterm::ErrorKind) -> Self {
        BottomError::CrosstermError(err.to_string())
    }
}

impl From<std::num::ParseIntError> for BottomError {
    fn from(err: std::num::ParseIntError) -> Self {
        BottomError::ConfigError(err.to_string())
    }
}

impl From<std::string::String> for BottomError {
    fn from(err: std::string::String) -> Self {
        BottomError::GenericError(err)
    }
}

impl From<toml::de::Error> for BottomError {
    fn from(err: toml::de::Error) -> Self {
        BottomError::ConfigError(err.to_string())
    }
}

#[cfg(feature = "fern")]
impl From<fern::InitError> for BottomError {
    fn from(err: fern::InitError) -> Self {
        BottomError::FernError(err.to_string())
    }
}

impl From<std::str::Utf8Error> for BottomError {
    fn from(err: std::str::Utf8Error) -> Self {
        BottomError::ConversionError(err.to_string())
    }
}

impl From<std::string::FromUtf8Error> for BottomError {
    fn from(err: std::string::FromUtf8Error) -> Self {
        BottomError::ConversionError(err.to_string())
    }
}

impl From<regex::Error> for BottomError {
    fn from(err: regex::Error) -> Self {
        // We only really want the last part of it... so we'll do it the ugly way:
        let err_str = err.to_string();
        let error = err_str.split('\n').map(|s| s.trim()).collect::<Vec<_>>();

        BottomError::QueryError(
            format!(
                "Regex error: {}",
                error.last().unwrap_or(&"".to_string().as_str())
            )
            .into(),
        )
    }
}

#[cfg(target_os = "linux")]
impl From<ProcError> for BottomError {
    fn from(err: ProcError) -> Self {
        match err {
            ProcError::PermissionDenied(p) => {
                BottomError::ProcfsError(format!("Permission denied for {:?}", p))
            }
            ProcError::NotFound(p) => BottomError::ProcfsError(format!("{:?} not found", p)),
            ProcError::Incomplete(p) => BottomError::ProcfsError(format!("{:?} incomplete", p)),
            ProcError::Io(e, p) => {
                BottomError::ProcfsError(format!("io error: {:?} for {:?}", e, p))
            }
            ProcError::Other(s) => BottomError::ProcfsError(format!("Other procfs error: {}", s)),
            ProcError::InternalError(e) => {
                BottomError::ProcfsError(format!("procfs internal error: {:?}", e))
            }
        }
    }
}