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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// 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,
/// A request refused by the transport's request policy before any byte
/// was sent (see `http::Client::with_policy`).
#[error("refused by policy: {0}")]
Policy(#[from] PolicyError),
/// Credential discovery found no credential it is allowed to use (for
/// example under `token::MetadataPolicy::Forbid` with no user
/// credentials), or an empty token was supplied. Nothing was contacted.
#[error("no credentials: {reason}")]
NoCredentials {
/// Why.
reason: &'static str,
},
}
/// Why a request policy refused a request. Never carries the URL's query
/// string, a body or a token.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[non_exhaustive]
pub enum PolicyError {
/// The method, scheme, host, port or path is not one the policy allows.
#[error("endpoint not allowed: {reason}")]
Endpoint {
/// Which rule refused it.
reason: &'static str,
},
/// The SQL text of a `BigQuery` query job was refused.
#[error("query not allowed: {reason}")]
Query {
/// Why (the policy's own wording).
reason: std::borrow::Cow<'static, str>,
},
/// A request to a `BigQuery` query endpoint whose SQL could not be
/// isolated for checking (unreadable body, non-query or legacy-SQL job,
/// or a field that changes what the SQL reads). Refused under every
/// policy, so no query reaches `BigQuery` unchecked.
#[error("query body not checkable: {reason}")]
UncheckableQuery {
/// What was wrong.
reason: &'static str,
},
}
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() }
}
}