use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum EventsErrorCode {
ResourceNotFound,
ResourceAlreadyExists,
InvalidEventPattern,
#[default]
ValidationException,
LimitExceeded,
ConcurrentModification,
InternalException,
InvalidAction,
MissingAction,
ManagedRuleException,
OperationDisabled,
}
impl EventsErrorCode {
#[must_use]
pub fn error_type(&self) -> &'static str {
self.as_str()
}
#[must_use]
pub fn as_str(&self) -> &'static str {
match self {
Self::ResourceNotFound => "ResourceNotFoundException",
Self::ResourceAlreadyExists => "ResourceAlreadyExistsException",
Self::InvalidEventPattern => "InvalidEventPatternException",
Self::ValidationException => "ValidationException",
Self::LimitExceeded => "LimitExceededException",
Self::ConcurrentModification => "ConcurrentModificationException",
Self::InternalException => "InternalException",
Self::InvalidAction => "InvalidAction",
Self::MissingAction => "MissingAction",
Self::ManagedRuleException => "ManagedRuleException",
Self::OperationDisabled => "OperationDisabledException",
}
}
#[must_use]
pub fn default_status_code(&self) -> http::StatusCode {
match self {
Self::InternalException => http::StatusCode::INTERNAL_SERVER_ERROR,
_ => http::StatusCode::BAD_REQUEST,
}
}
}
impl fmt::Display for EventsErrorCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug)]
pub struct EventsError {
pub code: EventsErrorCode,
pub message: String,
pub status_code: http::StatusCode,
pub source: Option<Box<dyn std::error::Error + Send + Sync>>,
}
impl fmt::Display for EventsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "EventsError({}): {}", self.code, self.message)
}
}
impl std::error::Error for EventsError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.source
.as_ref()
.map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
}
}
impl EventsError {
#[must_use]
pub fn new(code: EventsErrorCode) -> Self {
Self {
status_code: code.default_status_code(),
message: code.as_str().to_owned(),
code,
source: None,
}
}
#[must_use]
pub fn with_message(code: EventsErrorCode, message: impl Into<String>) -> Self {
Self {
status_code: code.default_status_code(),
message: message.into(),
code,
source: None,
}
}
#[must_use]
pub fn error_type(&self) -> &'static str {
self.code.error_type()
}
#[must_use]
pub fn resource_not_found(message: impl Into<String>) -> Self {
Self::with_message(EventsErrorCode::ResourceNotFound, message)
}
#[must_use]
pub fn resource_already_exists(message: impl Into<String>) -> Self {
Self::with_message(EventsErrorCode::ResourceAlreadyExists, message)
}
#[must_use]
pub fn invalid_event_pattern(message: impl Into<String>) -> Self {
Self::with_message(EventsErrorCode::InvalidEventPattern, message)
}
#[must_use]
pub fn validation(message: impl Into<String>) -> Self {
Self::with_message(EventsErrorCode::ValidationException, message)
}
#[must_use]
pub fn internal_error(message: impl Into<String>) -> Self {
Self::with_message(EventsErrorCode::InternalException, message)
}
#[must_use]
pub fn missing_action() -> Self {
Self::with_message(
EventsErrorCode::MissingAction,
"Missing required header: X-Amz-Target",
)
}
#[must_use]
pub fn unknown_operation(target: &str) -> Self {
Self::with_message(
EventsErrorCode::InvalidAction,
format!("Operation {target} is not supported."),
)
}
#[must_use]
pub fn not_implemented(operation: &str) -> Self {
Self::with_message(
EventsErrorCode::InternalException,
format!("Operation {operation} is not yet implemented"),
)
}
#[must_use]
pub fn limit_exceeded(message: impl Into<String>) -> Self {
Self::with_message(EventsErrorCode::LimitExceeded, message)
}
}
#[macro_export]
macro_rules! events_error {
($code:ident) => {
$crate::error::EventsError::new($crate::error::EventsErrorCode::$code)
};
($code:ident, $msg:expr) => {
$crate::error::EventsError::with_message($crate::error::EventsErrorCode::$code, $msg)
};
}