1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
use crate::BoxError;
use derive_more::Display;
use thiserror::Error;
/// The Error returned by storage backends. Storage backend implementations should choose the
/// `ErrorKind` chosen for errors carefully since that will determine what is returned to the FTP
/// client.
#[derive(Debug, Error)]
#[error("storage error: {kind}")]
pub struct Error {
kind: ErrorKind,
#[source]
source: Option<BoxError>,
}
impl Error {
/// Creates a new storage error
pub fn new<E>(kind: ErrorKind, error: E) -> Error
where
E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
Error {
kind,
source: Some(error.into()),
}
}
/// Detailed information about what the FTP server should do with the failure
pub fn kind(&self) -> ErrorKind {
self.kind
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Error {
Error { kind, source: None }
}
}
/// The `ErrorKind` variants that can be produced by the [`StorageBackend`] implementations.
///
/// [`StorageBackend`]: trait.StorageBackend.html
#[derive(Copy, Clone, Eq, PartialEq, Debug, Display)]
pub enum ErrorKind {
/// Error that will cause an FTP reply code of 450 to be returned to the FTP client.
/// The storage back-end implementation should return this if a error occurred that my be
/// retried for example in the case where a file is busy.
#[display(fmt = "450 Transient file not available")]
TransientFileNotAvailable,
/// Error that will cause an FTP reply code of 550 to be returned to the FTP client.
/// The storage back-end implementation should return this if a error occurred where it doesn't
/// make sense for it to be retried. For example in the case where a file is busy.
#[display(fmt = "550 Permanent file not available")]
PermanentFileNotAvailable,
/// Error that will cause an FTP reply code of 550 to be returned to the FTP client.
/// The storage back-end implementation should return this if a error occurred where it doesn't
/// make sense for it to be retried. For example in the case where file access is denied.
#[display(fmt = "550 Permission denied")]
PermissionDenied,
/// Error that will cause an FTP reply code of 451 to be returned to the FTP client. Its means
/// the requested action was aborted due to a local error (internal storage back-end error) in
/// processing.
#[display(fmt = "451 Local error")]
LocalError,
/// 551 Requested action aborted. Page type unknown.
#[display(fmt = "551 Page type unknown")]
PageTypeUnknown,
/// 452 Requested action not taken. Insufficient storage space in system.
#[display(fmt = "452 Insufficient storage space error")]
InsufficientStorageSpaceError,
/// 552 Requested file action aborted. Exceeded storage allocation (for current directory or
/// dataset).
#[display(fmt = "552 Exceeded storage allocation error")]
ExceededStorageAllocationError,
/// Error that will cause an FTP reply code of 553 to be returned to the FTP client. Its means
/// the requested action was not taken due to an illegal file name.
#[display(fmt = "553 File name not allowed error")]
FileNameNotAllowedError,
/// Error that will cause an FTP reply code of 502. The indicates to the client that the command
/// is not implemented for the storage back-end. For instance the GCS back-end don't implement
/// RMD (remove directory) but returns this error instead from its StorageBackend::rmd
/// implementation.
#[display(fmt = "502 Command not implemented")]
CommandNotImplemented,
}