use super::BoxError;
use crate::client::interceptors::context::phase::Phase;
use crate::client::interceptors::InterceptorError;
use crate::client::orchestrator::HttpResponse;
use crate::type_erasure::TypeErasedError;
use aws_smithy_http::result::{ConnectorError, SdkError};
use std::fmt::Debug;
#[derive(Debug)]
#[non_exhaustive]
pub enum OrchestratorError<E: Debug> {
Interceptor { err: InterceptorError },
Operation { err: E },
Other { err: BoxError },
}
impl<E: Debug> OrchestratorError<E> {
pub fn other(err: BoxError) -> Self {
Self::Other { err }
}
pub fn operation(err: E) -> Self {
Self::Operation { err }
}
pub fn interceptor(err: InterceptorError) -> Self {
Self::Interceptor { err }
}
pub fn into_sdk_error(
self,
phase: &Phase,
response: Option<HttpResponse>,
) -> SdkError<E, HttpResponse> {
match self {
Self::Interceptor { err } => {
use Phase::*;
match phase {
BeforeSerialization | Serialization => SdkError::construction_failure(err),
BeforeTransmit | Transmit => match response {
Some(response) => SdkError::response_error(err, response),
None => SdkError::dispatch_failure(ConnectorError::other(err.into(), None)),
},
BeforeDeserialization | Deserialization | AfterDeserialization => {
SdkError::response_error(err, response.expect("phase has a response"))
}
}
}
Self::Operation { err } => {
debug_assert!(phase.is_after_deserialization(), "operation errors are a result of successfully receiving and parsing a response from the server. Therefore, we must be in the 'After Deserialization' phase.");
SdkError::service_error(err, response.expect("phase has a response"))
}
Self::Other { err } => {
use Phase::*;
match phase {
BeforeSerialization | Serialization => SdkError::construction_failure(err),
BeforeTransmit | Transmit => convert_dispatch_error(err, response),
BeforeDeserialization | Deserialization | AfterDeserialization => {
SdkError::response_error(err, response.expect("phase has a response"))
}
}
}
}
}
}
fn convert_dispatch_error<O>(
err: BoxError,
response: Option<HttpResponse>,
) -> SdkError<O, HttpResponse> {
let err = match err.downcast::<ConnectorError>() {
Ok(connector_error) => {
return SdkError::dispatch_failure(*connector_error);
}
Err(e) => e,
};
match response {
Some(response) => SdkError::response_error(err, response),
None => SdkError::dispatch_failure(ConnectorError::other(err, None)),
}
}
impl<E> From<InterceptorError> for OrchestratorError<E>
where
E: Debug + std::error::Error + 'static,
{
fn from(err: InterceptorError) -> Self {
Self::interceptor(err)
}
}
impl<E> From<BoxError> for OrchestratorError<E>
where
E: Debug + std::error::Error + 'static,
{
fn from(err: BoxError) -> Self {
Self::other(err)
}
}
impl From<TypeErasedError> for OrchestratorError<TypeErasedError> {
fn from(err: TypeErasedError) -> Self {
Self::operation(err)
}
}