1use std::error;
2use std::fmt::{self, Display, Formatter};
3
4use http::StatusCode;
5use serde::Deserialize;
6
7#[derive(Debug)]
8pub enum Error<SE, BE> {
9 Deserializing(serde_json::Error),
10 Service(SE),
11 Body(BE),
12 Twitter(TwitterErrors),
13 Unexpected,
14}
15
16#[derive(Debug)]
17pub struct TwitterErrors {
18 pub status: StatusCode,
19 pub errors: Vec<ErrorCode>,
20 pub rate_limit: Option<crate::RateLimit>,
21}
22
23#[derive(Debug, Deserialize)]
24pub struct ErrorCode {
25 pub code: u32,
26 pub message: String,
27}
28
29impl<SE: error::Error + 'static, BE: error::Error + 'static> error::Error for Error<SE, BE> {
30 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
31 match *self {
32 Error::Deserializing(ref e) => Some(e),
33 Error::Service(ref e) => Some(e),
34 Error::Body(ref e) => Some(e),
35 Error::Twitter(ref e) => Some(e),
36 Error::Unexpected => None,
37 }
38 }
39}
40
41impl<SE: Display, BE: Display> Display for Error<SE, BE> {
42 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
43 match *self {
44 Error::Deserializing(_) => f.write_str("Failed to deserialize the response body."),
45 Error::Service(_) => f.write_str("HTTP error"),
46 Error::Body(_) => f.write_str("Error while reading the response body"),
47 Error::Twitter(_) => f.write_str("Twitter returned error(s)"),
48 Error::Unexpected => f.write_str("Unexpected error occured."),
49 }
50 }
51}
52
53impl TwitterErrors {
54 pub fn codes(&self) -> impl Iterator<Item = u32> + '_ {
55 self.errors.iter().map(|e| e.code)
56 }
57}
58
59impl Display for TwitterErrors {
60 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
61 write!(f, "status: {}", self.status)?;
62
63 let mut errors = self.errors.iter();
64 if let Some(e) = errors.next() {
65 write!(f, "; errors: {}", e)?;
66 for e in errors {
67 write!(f, ", {}", e)?;
68 }
69 }
70
71 Ok(())
72 }
73}
74
75impl error::Error for TwitterErrors {}
76
77impl ErrorCode {
78 pub const YOU_ARENT_ALLOWED_TO_ADD_MEMBERS_TO_THIS_LIST: u32 = 104;
79 pub const CANNOT_FIND_SPECIFIED_USER: u32 = 108;
80 pub const NO_STATUS_FOUND_WITH_THAT_ID: u32 = 144;
81 pub const YOU_HAVE_ALREADY_RETWEETED_THIS_TWEET: u32 = 327;
82}
83
84impl Display for ErrorCode {
85 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
86 write!(f, "{} {}", self.code, self.message)
87 }
88}