Skip to main content

objstore_r/
error.rs

1// Author: spicyzhug@gmail.com
2// Copyright: lituus-io, all rights reserved
3//
4//! Errors.
5
6/// Result alias.
7pub type Result<T, E = Error> = std::result::Result<T, E>;
8
9/// Everything an object store can report.
10#[derive(Debug, thiserror::Error)]
11#[non_exhaustive]
12pub enum Error {
13    /// The object does not exist (ranged reads only; `get`/`head` return `None`).
14    #[error("object not found")]
15    NotFound,
16    /// A [`Cond::CreateOnly`](crate::Cond::CreateOnly) write found an existing object.
17    #[error("object already exists")]
18    Conflict,
19    /// A [`Cond::IfGeneration`](crate::Cond::IfGeneration) write found another
20    /// generation (or no object).
21    #[error("generation precondition failed")]
22    PreconditionFailed,
23    /// The key or prefix is not valid (see [`Key::parse`](crate::Key::parse)).
24    #[error("invalid key: {reason}")]
25    InvalidKey {
26        /// Why.
27        reason: &'static str,
28    },
29    /// The store could not be reached or refused for a transient reason.
30    #[error("store unavailable: {message}")]
31    Unavailable {
32        /// What happened (never contains credentials).
33        message: String,
34        /// Worth retrying.
35        retriable: bool,
36    },
37    /// Authentication or authorization failed.
38    #[error("not authorized: {message}")]
39    Auth {
40        /// What happened (never contains credentials).
41        message: String,
42    },
43    /// The body exceeds a configured limit.
44    #[error("object larger than the {limit}-byte limit")]
45    TooLarge {
46        /// The limit.
47        limit: u64,
48    },
49    /// The store answered with something unexpected.
50    #[error("protocol error: {message}")]
51    Protocol {
52        /// What was wrong.
53        message: String,
54    },
55    /// A fenced publish lost to another writer (see [`crate::fenced`]).
56    /// Stop writing; re-read before publishing again.
57    #[error("fenced: {reason}")]
58    Fenced {
59        /// Why.
60        reason: &'static str,
61    },
62    /// Published data failed verification against the record naming it.
63    #[error("corrupt: {message}")]
64    Corrupt {
65        /// What was wrong.
66        message: String,
67    },
68    /// Local I/O.
69    #[error("i/o: {source}")]
70    Io {
71        /// The underlying error.
72        #[from]
73        source: std::io::Error,
74    },
75    // New variants go last: a variant's position is its discriminant.
76    /// A ranged read of an object stored with a content encoding: a byte
77    /// range of an encoded (compressed) stream is meaningless. Read it whole
78    /// with `get`, which decodes it.
79    #[error("ranged read of a {encoding}-encoded object: read it whole")]
80    EncodedRange {
81        /// The object's `Content-Encoding`.
82        encoding: String,
83    },
84    /// A content encoding this build cannot write or decode (an unknown
85    /// token, or `gzip` without feature `gzip`).
86    #[error("unsupported content encoding {encoding:?}")]
87    UnsupportedEncoding {
88        /// The encoding named (at most 64 characters).
89        encoding: String,
90    },
91}
92
93impl Error {
94    /// Worth retrying (transient unavailability; never conflicts or preconditions).
95    #[must_use]
96    pub fn is_retriable(&self) -> bool {
97        matches!(self, Error::Unavailable { retriable: true, .. })
98    }
99
100    #[cfg_attr(not(any(feature = "gcs", test)), allow(dead_code))]
101    pub(crate) fn unavailable(message: impl Into<String>, retriable: bool) -> Self {
102        Error::Unavailable { message: message.into(), retriable }
103    }
104
105    pub(crate) fn corrupt(message: impl Into<String>) -> Self {
106        Error::Corrupt { message: message.into() }
107    }
108
109    #[cfg_attr(not(feature = "gcs"), allow(dead_code))]
110    pub(crate) fn protocol(message: impl Into<String>) -> Self {
111        Error::Protocol { message: message.into() }
112    }
113}