lesspass_client/
error.rs

1//
2// lesspass-client error.rs
3// Copyright (C) 2021-2025 Óscar García Amor <ogarcia@connectical.com>
4// Distributed under terms of the GNU GPLv3 license.
5//
6
7use std::fmt;
8
9/// A `Result` alias where the `Err` case is `lesspass_client::Error`.
10pub type Result<T> = std::result::Result<T, Error>;
11
12#[derive(Debug)]
13pub(crate) enum Kind {
14    Reqwest,
15    UrlParse
16}
17
18pub struct Error {
19    kind: Kind,
20    message: String,
21    status: Option<reqwest::StatusCode>
22}
23
24impl Error {
25     /// Returns true if the error is from Reqwest
26     pub fn is_reqwest(&self) -> bool {
27         matches!(self.kind, Kind::Reqwest)
28     }
29
30     /// Returns true if the error is from UrlParse
31     pub fn is_url_parse(&self) -> bool {
32         matches!(self.kind, Kind::UrlParse)
33     }
34
35     /// Returns message as is
36     pub fn message(&self) -> String {
37         self.message.clone()
38     }
39
40     /// Returns the status code as u16
41     pub fn status(&self) -> Option<u16> {
42         self.status.map(|e| e.as_u16())
43     }
44
45     /// Returns the status code as is
46     pub fn status_code(&self) -> Option<reqwest::StatusCode> {
47         self.status
48     }
49}
50
51impl fmt::Display for Error {
52    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53        match self.kind {
54            Kind::Reqwest => f.write_str("reqwest error")?,
55            Kind::UrlParse => f.write_str("URL parse error")?,
56        };
57        write!(f, ", {}", self.message)
58    }
59}
60
61impl fmt::Debug for Error {
62    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63        write!(
64            f,
65            "Error {{ kind: {:?}, message: {}, status: {:?} }}",
66            self.kind, self.message, self.status
67        )
68    }
69}
70
71// Implement std::convert::From for Error from reqwest::Error
72impl From<reqwest::Error> for Error {
73    fn from(error: reqwest::Error) -> Self {
74        Error {
75            kind: Kind::Reqwest,
76            message: error.to_string(),
77            status: error.status()
78        }
79    }
80}
81
82// Implement std::convert::From for Error from url::ParseError
83impl From<url::ParseError> for Error {
84    fn from(error: url::ParseError) -> Self {
85        Error {
86            kind: Kind::UrlParse,
87            message: error.to_string(),
88            status: None
89        }
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    #[test]
98    fn error() {
99        // A reqwest error
100        let error = Error {
101            kind: Kind::Reqwest,
102            message: "a reqwest error".to_string(),
103            status: Some(reqwest::StatusCode::from_u16(500).unwrap())
104        };
105        assert_eq!("Error { kind: Reqwest, message: a reqwest error, status: Some(500) }", format!("{error:?}"));
106        assert_eq!("reqwest error, a reqwest error", error.to_string());
107        assert_eq!("a reqwest error", error.message());
108        assert_eq!(Some(500), error.status());
109        assert_eq!(Some(reqwest::StatusCode::INTERNAL_SERVER_ERROR), error.status_code());
110        assert!(error.is_reqwest());
111        // A URL parse error
112        let error = Error {
113            kind: Kind::UrlParse,
114            message: "an URL parse error".to_string(),
115            status: None
116        };
117        assert_eq!("Error { kind: UrlParse, message: an URL parse error, status: None }", format!("{error:?}"));
118        assert_eq!("URL parse error, an URL parse error", error.to_string());
119        assert_eq!("an URL parse error", error.message());
120        assert_eq!(None, error.status());
121        assert!(error.is_url_parse());
122    }
123}