use crate::error::{AmiError, Result};
impl AmiError {
pub fn resource_not_found(resource_type: &str, resource_id: &str) -> Self {
AmiError::ResourceNotFound {
resource: format!("{}: {}", resource_type, resource_id),
}
}
pub fn permission_denied(action: &str, resource: &str) -> Self {
AmiError::PermissionDenied {
reason: format!("Cannot {} on {}", action, resource),
}
}
pub fn access_denied(message: impl Into<String>) -> Self {
AmiError::AccessDenied {
message: message.into(),
}
}
pub fn invalid_parameter(message: impl Into<String>) -> Self {
AmiError::InvalidParameter {
message: message.into(),
}
}
pub fn resource_exists(resource: impl Into<String>) -> Self {
AmiError::ResourceExists {
resource: resource.into(),
}
}
pub fn resource_limit_exceeded(resource_type: &str, limit: usize) -> Self {
AmiError::ResourceLimitExceeded {
resource_type: resource_type.to_string(),
limit,
}
}
pub fn operation_not_supported(operation: impl Into<String>) -> Self {
AmiError::OperationNotSupported {
operation: operation.into(),
}
}
}
#[allow(clippy::result_large_err)]
pub trait OptionExt<T> {
fn or_not_found(self, resource_type: &str, resource_id: &str) -> Result<T>;
}
impl<T> OptionExt<T> for Option<T> {
fn or_not_found(self, resource_type: &str, resource_id: &str) -> Result<T> {
self.ok_or_else(|| AmiError::resource_not_found(resource_type, resource_id))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_resource_not_found() {
let error = AmiError::resource_not_found("User", "alice");
assert!(matches!(error, AmiError::ResourceNotFound { .. }));
assert!(error.to_string().contains("User: alice"));
}
#[test]
fn test_permission_denied() {
let error = AmiError::permission_denied("delete", "User: alice");
assert!(matches!(error, AmiError::PermissionDenied { .. }));
assert!(error.to_string().contains("Cannot delete"));
}
#[test]
fn test_or_not_found_some() {
let option: Option<String> = Some("value".to_string());
let result = option.or_not_found("Resource", "id");
assert!(result.is_ok());
assert_eq!(result.unwrap(), "value");
}
#[test]
fn test_or_not_found_none() {
let option: Option<String> = None;
let result = option.or_not_found("User", "alice");
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
AmiError::ResourceNotFound { .. }
));
}
}