aws_sdk_s3_transfer_manager/
error.rs1use std::fmt;
7
8pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
10
11use aws_sdk_s3::error::ProvideErrorMetadata;
12
13#[derive(Debug)]
18pub struct Error {
19 kind: ErrorKind,
20 source: BoxError,
21}
22
23#[derive(Clone, Debug, Eq, PartialEq)]
25#[non_exhaustive]
26pub enum ErrorKind {
27 InputInvalid,
29
30 IOError,
32
33 RuntimeError,
35
36 ObjectNotDiscoverable,
38
39 ChunkFailed(ChunkFailed),
41
42 NotFound,
44
45 ChildOperationFailed,
47
48 OperationCancelled,
51}
52
53#[derive(Clone, Debug, Eq, PartialEq)]
55pub struct ChunkFailed {
56 id: ChunkId,
60}
61
62#[derive(Clone, Debug, Eq, PartialEq)]
63pub(crate) enum ChunkId {
64 Download(u64),
65 Upload(String),
66}
67
68impl ChunkFailed {
69 pub(crate) fn download_seq(&self) -> Option<u64> {
71 match self.id {
72 ChunkId::Download(seq) => Some(seq),
73 _ => None,
74 }
75 }
76
77 #[allow(dead_code)]
78 pub(crate) fn upload_id(&self) -> Option<&str> {
80 match &self.id {
81 ChunkId::Upload(id) => Some(id),
82 _ => None,
83 }
84 }
85}
86
87impl Error {
88 pub fn new<E>(kind: ErrorKind, err: E) -> Error
91 where
92 E: Into<BoxError>,
93 {
94 Error {
95 kind,
96 source: err.into(),
97 }
98 }
99
100 pub fn kind(&self) -> &ErrorKind {
102 &self.kind
103 }
104}
105
106impl fmt::Display for Error {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 match &self.kind {
109 ErrorKind::InputInvalid => write!(f, "invalid input"),
110 ErrorKind::IOError => write!(f, "I/O error"),
111 ErrorKind::RuntimeError => write!(f, "runtime error"),
112 ErrorKind::ObjectNotDiscoverable => write!(f, "object discovery failed"),
113 ErrorKind::ChunkFailed(chunk_failed) => {
114 write!(f, "failed to process chunk {:?}", chunk_failed.id)
115 }
116 ErrorKind::NotFound => write!(f, "resource not found"),
117 ErrorKind::ChildOperationFailed => write!(f, "child operation failed"),
118 ErrorKind::OperationCancelled => write!(f, "operation cancelled"),
119 }
120 }
121}
122
123impl std::error::Error for Error {
124 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
125 Some(self.source.as_ref())
126 }
127}
128
129impl From<crate::io::error::Error> for Error {
130 fn from(value: crate::io::error::Error) -> Self {
131 Self::new(ErrorKind::IOError, value)
132 }
133}
134
135impl From<std::io::Error> for Error {
136 fn from(value: std::io::Error) -> Self {
137 Self::new(ErrorKind::IOError, value)
138 }
139}
140
141impl From<tokio::task::JoinError> for Error {
142 fn from(value: tokio::task::JoinError) -> Self {
143 Self::new(ErrorKind::RuntimeError, value)
144 }
145}
146
147impl<T> From<std::sync::PoisonError<T>> for Error
148where
149 T: Send + Sync + 'static,
150{
151 fn from(value: std::sync::PoisonError<T>) -> Self {
152 Self::new(ErrorKind::RuntimeError, value)
153 }
154}
155
156impl From<aws_smithy_types::error::operation::BuildError> for Error {
157 fn from(value: aws_smithy_types::error::operation::BuildError) -> Self {
158 Self::new(ErrorKind::InputInvalid, value)
159 }
160}
161
162pub(crate) fn invalid_input<E>(err: E) -> Error
163where
164 E: Into<BoxError>,
165{
166 Error::new(ErrorKind::InputInvalid, err)
167}
168
169pub(crate) fn discovery_failed<E>(err: E) -> Error
170where
171 E: Into<BoxError>,
172{
173 Error::new(ErrorKind::ObjectNotDiscoverable, err)
174}
175
176pub(crate) fn chunk_failed<E>(id: ChunkId, err: E) -> Error
177where
178 E: Into<BoxError>,
179{
180 Error::new(ErrorKind::ChunkFailed(ChunkFailed { id }), err)
181}
182
183pub(crate) fn from_kind<E>(kind: ErrorKind) -> impl FnOnce(E) -> Error
184where
185 E: Into<BoxError>,
186{
187 |err| Error::new(kind, err)
188}
189
190impl<E, R> From<aws_sdk_s3::error::SdkError<E, R>> for Error
191where
192 E: std::error::Error + ProvideErrorMetadata + Send + Sync + 'static,
193 R: Send + Sync + fmt::Debug + 'static,
194{
195 fn from(value: aws_sdk_s3::error::SdkError<E, R>) -> Self {
196 let kind = match value.code() {
198 Some("NotFound" | "NoSuchKey" | "NoSuchUpload" | "NoSuchBucket") => ErrorKind::NotFound,
199 _ => ErrorKind::ChildOperationFailed,
201 };
202
203 Error::new(kind, value)
204 }
205}
206
207static CANCELLATION_ERROR: &str =
208 "at least one operation has been aborted, cancelling all ongoing requests";
209
210pub(crate) fn operation_cancelled() -> Error {
211 Error::new(ErrorKind::OperationCancelled, CANCELLATION_ERROR)
212}