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
|
use bcrypt::BcryptError;
use diesel::result::Error as DieselErr;
use serde_json::Value;
use std::convert::From;
use std::error::Error as StdError;
use std::fmt;
#[derive(Debug)]
pub struct StravaApiError{
status: reqwest::StatusCode,
code: String,
field: String,
value: Value,
}
impl StravaApiError {
pub fn new(status: reqwest::StatusCode, value: Value) -> StravaApiError {
let first_error = &value["errors"][0];
let code = first_error["code"].as_str().unwrap_or("unknown").to_string();
let field = first_error["field"].as_str().unwrap_or("unknown").to_string();
StravaApiError { status, code, field, value }
}
}
impl fmt::Display for StravaApiError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "field '{}' has error '{}'", self.field, self.code)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn strava_api_error_unknown() {
let data = r#""insane input""#;
let json = serde_json::from_str(data).unwrap();
let error = Error::StravaApiError(StravaApiError::new(reqwest::StatusCode::UNAUTHORIZED, json));
assert_eq!("field 'unknown' has error 'unknown'",
format!("{}", error));
}
#[test]
fn strava_api_error_invalid() {
let data = r#"
{
"errors":[
{"code":"invalid",
"field":"access_token",
"resource":"Athlete"}
],
"message":"Authorization Error"
}"#;
let json = serde_json::from_str(data).unwrap();
let error = Error::StravaApiError(StravaApiError::new(reqwest::StatusCode::UNAUTHORIZED, json));
assert_eq!("field 'access_token' has error 'invalid'",
format!("{}", error));
}
}
#[derive(Debug)]
pub enum Error {
DieselError(DieselErr),
PasswordError(BcryptError),
CommunicationError(reqwest::Error),
ParseError(serde_json::error::Error),
StravaApiError(StravaApiError),
UnexpectedJson(Value),
AlreadyExists,
NotFound,
InternalError,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::DieselError(ref e) => e.fmt(f),
Error::PasswordError(ref e) => e.fmt(f),
Error::CommunicationError(ref e) => e.fmt(f),
Error::ParseError(ref e) => e.fmt(f),
Error::UnexpectedJson(_) => f.write_str("UnexpectedJson"),
Error::StravaApiError(ref e) => e.fmt(f),
Error::AlreadyExists => f.write_str("AlreadyExists"),
Error::NotFound => f.write_str("NotFound"),
Error::InternalError => f.write_str("InternalError"),
}
}
}
impl From<StravaApiError> for Error {
fn from(e: StravaApiError) -> Error {
Error::StravaApiError(e)
}
}
impl From<serde_json::error::Error> for Error {
fn from(e: serde_json::error::Error) -> Error {
Error::ParseError(e)
}
}
impl From<reqwest::Error> for Error {
fn from(e: reqwest::Error) -> Error {
Error::CommunicationError(e)
}
}
impl From<DieselErr> for Error {
fn from(e: DieselErr) -> Error {
match e {
DieselErr::NotFound => Error::NotFound,
e => Error::DieselError(e)
}
}
}
impl From<BcryptError> for Error {
fn from(e: BcryptError) -> Error {
Error::PasswordError(e)
}
}
impl StdError for Error {}
|