use crate::title::Title;
use serde_json::Value;
use std::error::Error;
use std::fmt;
#[derive(Debug)]
#[non_exhaustive]
pub enum MediaWikiError {
Serde(serde_json::Error),
Reqwest(reqwest::Error),
ReqwestHeader(reqwest::header::InvalidHeaderValue),
String(String),
Url(url::ParseError),
Fmt(fmt::Error),
Time(std::time::SystemTimeError),
Login(String),
BadTitle(Title),
BadResponse(Value),
Missing(Title),
EditError(Value),
UnexpectedResultFormat(String),
}
impl Error for MediaWikiError {}
impl fmt::Display for MediaWikiError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Serde(e) => f.write_str(&e.to_string()),
Self::Reqwest(e) => f.write_str(&e.to_string()),
Self::ReqwestHeader(e) => f.write_str(&e.to_string()),
Self::String(s) => f.write_str(s),
Self::Url(e) => f.write_str(&e.to_string()),
Self::Fmt(e) => f.write_str(&e.to_string()),
Self::Time(e) => f.write_str(&e.to_string()),
Self::Login(s) => f.write_str(s),
Self::BadTitle(title) => write!(f, "invalid title for this Page: {:?}", title),
Self::BadResponse(response) => write!(
f,
"bad API response while fetching revision content: {:?}",
response
),
Self::Missing(title) => write!(f, "page missing: {:?}", title),
Self::EditError(response) => write!(f, "edit resulted in error: {:?}", response),
Self::UnexpectedResultFormat(error) => write!(f, "result format error: {}", error),
}
}
}
impl From<serde_json::Error> for MediaWikiError {
fn from(e: serde_json::Error) -> Self {
Self::Serde(e)
}
}
impl From<reqwest::Error> for MediaWikiError {
fn from(e: reqwest::Error) -> Self {
Self::Reqwest(e)
}
}
impl From<reqwest::header::InvalidHeaderValue> for MediaWikiError {
fn from(e: reqwest::header::InvalidHeaderValue) -> Self {
Self::ReqwestHeader(e)
}
}
impl From<reqwest::header::ToStrError> for MediaWikiError {
fn from(e: reqwest::header::ToStrError) -> Self {
Self::String(e.to_string())
}
}
impl From<String> for MediaWikiError {
fn from(e: String) -> Self {
Self::String(e)
}
}
impl From<&str> for MediaWikiError {
fn from(e: &str) -> Self {
Self::String(e.to_string())
}
}
impl From<url::ParseError> for MediaWikiError {
fn from(e: url::ParseError) -> Self {
Self::Url(e)
}
}
impl From<fmt::Error> for MediaWikiError {
fn from(e: fmt::Error) -> Self {
Self::Fmt(e)
}
}
impl From<std::time::SystemTimeError> for MediaWikiError {
fn from(e: std::time::SystemTimeError) -> Self {
Self::Time(e)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_string() {
let err = MediaWikiError::from("test error".to_string());
assert!(matches!(err, MediaWikiError::String(s) if s == "test error"));
}
#[test]
fn from_str() {
let err = MediaWikiError::from("test error");
assert!(matches!(err, MediaWikiError::String(s) if s == "test error"));
}
#[test]
fn display_string_error() {
let err = MediaWikiError::String("something went wrong".to_string());
assert_eq!(format!("{}", err), "something went wrong");
}
#[test]
fn display_missing() {
let title = Title::new("Test Page", 0);
let err = MediaWikiError::Missing(title);
let msg = format!("{}", err);
assert!(msg.contains("missing"));
}
#[test]
fn display_login() {
let err = MediaWikiError::Login("bad credentials".to_string());
assert_eq!(format!("{}", err), "bad credentials");
}
#[test]
fn from_url_parse_error() {
let url_err = url::Url::parse("not a url :::").unwrap_err();
let err = MediaWikiError::from(url_err);
assert!(matches!(err, MediaWikiError::Url(_)));
}
#[test]
fn from_serde_error() {
let serde_err = serde_json::from_str::<Value>("not json{{{").unwrap_err();
let err = MediaWikiError::from(serde_err);
assert!(matches!(err, MediaWikiError::Serde(_)));
}
#[test]
fn error_trait_implemented() {
let err = MediaWikiError::String("test".to_string());
let _: &dyn Error = &err;
}
}