#![warn(
missing_debug_implementations,
missing_docs,
rustdoc::all,
unreachable_pub
)]
use crate::operation;
use aws_smithy_types::retry::ErrorKind;
use std::error::Error;
use std::fmt;
use std::fmt::{Debug, Display, Formatter};
type BoxError = Box<dyn Error + Send + Sync>;
#[derive(Debug)]
pub struct SdkSuccess<O> {
pub raw: operation::Response,
pub parsed: O,
}
#[derive(Debug)]
pub enum SdkError<E, R = operation::Response> {
ConstructionFailure(BoxError),
TimeoutError(BoxError),
DispatchFailure(ConnectorError),
ResponseError {
err: BoxError,
raw: R,
},
ServiceError {
err: E,
raw: R,
},
}
#[derive(Debug)]
pub struct ConnectorError {
err: BoxError,
kind: ConnectorErrorKind,
}
impl Display for ConnectorError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.kind, self.err)
}
}
impl Error for ConnectorError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(self.err.as_ref())
}
}
impl ConnectorError {
pub fn timeout(err: BoxError) -> Self {
Self {
err,
kind: ConnectorErrorKind::Timeout,
}
}
pub fn user(err: BoxError) -> Self {
Self {
err,
kind: ConnectorErrorKind::User,
}
}
pub fn io(err: BoxError) -> Self {
Self {
err,
kind: ConnectorErrorKind::Io,
}
}
pub fn other(err: BoxError, kind: Option<ErrorKind>) -> Self {
Self {
err,
kind: ConnectorErrorKind::Other(kind),
}
}
pub fn is_io(&self) -> bool {
matches!(self.kind, ConnectorErrorKind::Io)
}
pub fn is_timeout(&self) -> bool {
matches!(self.kind, ConnectorErrorKind::Timeout)
}
pub fn is_user(&self) -> bool {
matches!(self.kind, ConnectorErrorKind::User)
}
pub fn is_other(&self) -> Option<ErrorKind> {
match &self.kind {
ConnectorErrorKind::Other(ek) => *ek,
_ => None,
}
}
}
#[derive(Debug)]
enum ConnectorErrorKind {
Timeout,
User,
Io,
Other(Option<ErrorKind>),
}
impl Display for ConnectorErrorKind {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
ConnectorErrorKind::Timeout => write!(f, "timeout"),
ConnectorErrorKind::User => write!(f, "user error"),
ConnectorErrorKind::Io => write!(f, "io error"),
ConnectorErrorKind::Other(Some(kind)) => write!(f, "{:?}", kind),
ConnectorErrorKind::Other(None) => write!(f, "other"),
}
}
}
impl<E, R> Display for SdkError<E, R>
where
E: Error,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SdkError::ConstructionFailure(err) => write!(f, "failed to construct request: {}", err),
SdkError::TimeoutError(err) => write!(f, "request has timed out: {}", err),
SdkError::DispatchFailure(err) => Display::fmt(&err, f),
SdkError::ResponseError { err, .. } => Display::fmt(&err, f),
SdkError::ServiceError { err, .. } => Display::fmt(&err, f),
}
}
}
impl<E, R> Error for SdkError<E, R>
where
E: Error + 'static,
R: Debug,
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
use SdkError::*;
match self {
ConstructionFailure(err) | TimeoutError(err) | ResponseError { err, .. } => {
Some(err.as_ref())
}
DispatchFailure(err) => Some(err),
ServiceError { err, .. } => Some(err),
}
}
}