use std::error;
use std::fmt::{self, Display, Formatter};
use http::StatusCode;
use serde::Deserialize;
#[derive(Debug)]
pub enum Error<SE, BE> {
Deserializing(serde_json::Error),
Service(SE),
Body(BE),
Twitter(TwitterErrors),
Unexpected,
}
#[derive(Debug)]
pub struct TwitterErrors {
pub status: StatusCode,
pub errors: Vec<ErrorCode>,
pub rate_limit: Option<crate::RateLimit>,
}
#[derive(Debug, Deserialize)]
pub struct ErrorCode {
pub code: u32,
pub message: String,
}
impl<SE: error::Error + 'static, BE: error::Error + 'static> error::Error for Error<SE, BE> {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
Error::Deserializing(ref e) => Some(e),
Error::Service(ref e) => Some(e),
Error::Body(ref e) => Some(e),
Error::Twitter(ref e) => Some(e),
Error::Unexpected => None,
}
}
}
impl<SE: Display, BE: Display> Display for Error<SE, BE> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match *self {
Error::Deserializing(_) => f.write_str("Failed to deserialize the response body."),
Error::Service(_) => f.write_str("HTTP error"),
Error::Body(_) => f.write_str("Error while reading the response body"),
Error::Twitter(_) => f.write_str("Twitter returned error(s)"),
Error::Unexpected => f.write_str("Unexpected error occured."),
}
}
}
impl TwitterErrors {
pub fn codes(&self) -> impl Iterator<Item = u32> + '_ {
self.errors.iter().map(|e| e.code)
}
}
impl Display for TwitterErrors {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "status: {}", self.status)?;
let mut errors = self.errors.iter();
if let Some(e) = errors.next() {
write!(f, "; errors: {}", e)?;
for e in errors {
write!(f, ", {}", e)?;
}
}
Ok(())
}
}
impl error::Error for TwitterErrors {}
impl ErrorCode {
pub const YOU_ARENT_ALLOWED_TO_ADD_MEMBERS_TO_THIS_LIST: u32 = 104;
pub const CANNOT_FIND_SPECIFIED_USER: u32 = 108;
pub const NO_STATUS_FOUND_WITH_THAT_ID: u32 = 144;
pub const YOU_HAVE_ALREADY_RETWEETED_THIS_TWEET: u32 = 327;
}
impl Display for ErrorCode {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{} {}", self.code, self.message)
}
}