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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Author: spicyzhug@gmail.com
// Copyright: lituus-io, all rights reserved
//
//! Errors.
/// Result alias.
pub type Result<T, E = Error> = std::result::Result<T, E>;
/// Everything an object store can report.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
/// The object does not exist (ranged reads only; `get`/`head` return `None`).
#[error("object not found")]
NotFound,
/// A [`Cond::CreateOnly`](crate::Cond::CreateOnly) write found an existing object.
#[error("object already exists")]
Conflict,
/// A [`Cond::IfGeneration`](crate::Cond::IfGeneration) write found another
/// generation (or no object).
#[error("generation precondition failed")]
PreconditionFailed,
/// The key or prefix is not valid (see [`Key::parse`](crate::Key::parse)).
#[error("invalid key: {reason}")]
InvalidKey {
/// Why.
reason: &'static str,
},
/// The store could not be reached or refused for a transient reason.
#[error("store unavailable: {message}")]
Unavailable {
/// What happened (never contains credentials).
message: String,
/// Worth retrying.
retriable: bool,
},
/// Authentication or authorization failed.
#[error("not authorized: {message}")]
Auth {
/// What happened (never contains credentials).
message: String,
},
/// The body exceeds a configured limit.
#[error("object larger than the {limit}-byte limit")]
TooLarge {
/// The limit.
limit: u64,
},
/// The store answered with something unexpected.
#[error("protocol error: {message}")]
Protocol {
/// What was wrong.
message: String,
},
/// A fenced publish lost to another writer (see [`crate::fenced`]).
/// Stop writing; re-read before publishing again.
#[error("fenced: {reason}")]
Fenced {
/// Why.
reason: &'static str,
},
/// Published data failed verification against the record naming it.
#[error("corrupt: {message}")]
Corrupt {
/// What was wrong.
message: String,
},
/// Local I/O.
#[error("i/o: {source}")]
Io {
/// The underlying error.
#[from]
source: std::io::Error,
},
// New variants go last: a variant's position is its discriminant.
/// A ranged read of an object stored with a content encoding: a byte
/// range of an encoded (compressed) stream is meaningless. Read it whole
/// with `get`, which decodes it.
#[error("ranged read of a {encoding}-encoded object: read it whole")]
EncodedRange {
/// The object's `Content-Encoding`.
encoding: String,
},
/// A content encoding this build cannot write or decode (an unknown
/// token, or `gzip` without feature `gzip`).
#[error("unsupported content encoding {encoding:?}")]
UnsupportedEncoding {
/// The encoding named (at most 64 characters).
encoding: String,
},
/// The object was replaced or deleted while a read that had to resume
/// was in flight. Nothing from either generation is returned (two
/// generations are never spliced); read it again.
#[error("object replaced during a resumed read")]
Changed,
}
impl Error {
/// Worth retrying (transient unavailability; never conflicts or preconditions).
#[must_use]
pub fn is_retriable(&self) -> bool {
matches!(self, Error::Unavailable { retriable: true, .. })
}
#[cfg_attr(not(any(feature = "gcs", test)), allow(dead_code))]
pub(crate) fn unavailable(message: impl Into<String>, retriable: bool) -> Self {
Error::Unavailable { message: message.into(), retriable }
}
pub(crate) fn corrupt(message: impl Into<String>) -> Self {
Error::Corrupt { message: message.into() }
}
#[cfg_attr(not(feature = "gcs"), allow(dead_code))]
pub(crate) fn protocol(message: impl Into<String>) -> Self {
Error::Protocol { message: message.into() }
}
}