use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub enum OrcidError {
InvalidOrcidId(String),
NetworkError(reqwest::Error),
JsonError(serde_json::Error),
ApiError {
orcid_id: String,
error_code: String,
developer_message: String,
},
BadApiResponse(serde_json::Value),
}
impl fmt::Display for OrcidError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
OrcidError::InvalidOrcidId(id) => {
write!(f, "{} is not a valid ORCID ID", id)
}
OrcidError::NetworkError(e) => {
write!(f, "Network request failed: {}", e)
}
OrcidError::JsonError(e) => {
write!(f, "Failed to parse JSON: {}", e)
}
OrcidError::ApiError {
orcid_id,
error_code,
developer_message,
} => {
write!(
f,
"API error for ORCID {}: {} - {}",
orcid_id, error_code, developer_message
)
}
OrcidError::BadApiResponse(json) => {
write!(f, "Unexpected API response: {}", json)
}
}
}
}
impl Error for OrcidError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
OrcidError::NetworkError(e) => Some(e),
OrcidError::JsonError(e) => Some(e),
_ => None,
}
}
}
impl From<reqwest::Error> for OrcidError {
fn from(err: reqwest::Error) -> Self {
OrcidError::NetworkError(err)
}
}
impl From<serde_json::Error> for OrcidError {
fn from(err: serde_json::Error) -> Self {
OrcidError::JsonError(err)
}
}
pub type Result<T> = std::result::Result<T, OrcidError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_invalid_orcid_id_display() {
let error = OrcidError::InvalidOrcidId("1234-5678".to_string());
assert_eq!(error.to_string(), "1234-5678 is not a valid ORCID ID");
}
#[test]
fn test_api_error_display() {
let error = OrcidError::ApiError {
orcid_id: "0000-0001-2345-6789".to_string(),
error_code: "404".to_string(),
developer_message: "ORCID not found".to_string(),
};
assert_eq!(
error.to_string(),
"API error for ORCID 0000-0001-2345-6789: 404 - ORCID not found"
);
}
#[test]
fn test_bad_api_response_display() {
let json = serde_json::json!({ "unexpected": "payload" });
let error = OrcidError::BadApiResponse(json);
assert!(error.to_string().contains("Unexpected API response"));
assert!(error.to_string().contains("unexpected"));
}
#[test]
fn test_error_debug() {
let error = OrcidError::InvalidOrcidId("1234".to_string());
let debug_str = format!("{:?}", error);
assert!(debug_str.contains("InvalidOrcidId"));
assert!(debug_str.contains("1234"));
}
#[test]
fn test_from_reqwest_error() {
fn _takes_reqwest_error(e: reqwest::Error) -> OrcidError {
OrcidError::from(e)
}
}
#[test]
fn test_from_json_error() {
let json_err = serde_json::from_str::<String>("invalid json").unwrap_err();
let orcid_err: OrcidError = json_err.into();
match orcid_err {
OrcidError::JsonError(_) => (),
_ => panic!("Expected JsonError variant"),
}
}
}