use soap_client::SoapError;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ApiError {
#[error("Network error: {0}")]
NetworkError(String),
#[error("Parse error: {0}")]
ParseError(String),
#[error("SOAP fault: error code {0}")]
SoapFault(u16),
#[error("Invalid parameter: {0}")]
InvalidParameter(String),
#[error("Subscription error: {0}")]
SubscriptionError(String),
#[error("Device error: {0}")]
DeviceError(String),
}
impl ApiError {
pub fn subscription_expired() -> Self {
Self::SubscriptionError("Subscription expired".to_string())
}
}
pub type Result<T> = std::result::Result<T, ApiError>;
impl From<SoapError> for ApiError {
fn from(error: SoapError) -> Self {
match error {
SoapError::Network(msg) => ApiError::NetworkError(msg),
SoapError::Parse(msg) => ApiError::ParseError(msg),
SoapError::Fault(code) => ApiError::SoapFault(code),
}
}
}
impl From<crate::operation::ValidationError> for ApiError {
fn from(validation_error: crate::operation::ValidationError) -> Self {
match validation_error {
crate::operation::ValidationError::InvalidValue {
parameter,
value,
reason,
} => ApiError::InvalidParameter(format!(
"Invalid value '{value}' for parameter '{parameter}': {reason}"
)),
crate::operation::ValidationError::RangeError {
parameter,
value,
min,
max,
} => ApiError::InvalidParameter(format!(
"Parameter '{parameter}' value {value} is out of range [{min}, {max}]"
)),
crate::operation::ValidationError::Custom { parameter, message } => {
ApiError::InvalidParameter(format!("Parameter '{parameter}': {message}"))
}
crate::operation::ValidationError::MissingParameter { parameter } => {
ApiError::InvalidParameter(format!("Required parameter '{parameter}' is missing"))
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_subscription_expired() {
let error = ApiError::subscription_expired();
assert!(matches!(error, ApiError::SubscriptionError(_)));
let error_str = format!("{error}");
assert!(error_str.contains("expired"));
}
#[test]
fn test_soap_error_conversion() {
let soap_error = SoapError::Network("connection timeout".to_string());
let api_error: ApiError = soap_error.into();
assert!(matches!(api_error, ApiError::NetworkError(_)));
let soap_error = SoapError::Parse("invalid XML".to_string());
let api_error: ApiError = soap_error.into();
assert!(matches!(api_error, ApiError::ParseError(_)));
let soap_error = SoapError::Fault(500);
let api_error: ApiError = soap_error.into();
assert!(matches!(api_error, ApiError::SoapFault(500)));
}
#[test]
fn test_error_display() {
let network_err = ApiError::NetworkError("connection failed".to_string());
assert_eq!(format!("{network_err}"), "Network error: connection failed");
let parse_err = ApiError::ParseError("invalid XML".to_string());
assert_eq!(format!("{parse_err}"), "Parse error: invalid XML");
let soap_fault = ApiError::SoapFault(500);
assert_eq!(format!("{soap_fault}"), "SOAP fault: error code 500");
}
}