google_cloud_auth/
build_errors.rs

1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Errors created during credentials construction.
16
17type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
18
19/// The error type for [Credentials] builders.
20///
21/// Applications rarely need to create instances of this error type. The
22/// exception might be when testing application code, where the application is
23/// mocking a client library behavior.
24///
25/// [Credentials]: super::credentials::Credentials
26#[derive(thiserror::Error, Debug)]
27#[error(transparent)]
28pub struct Error(ErrorKind);
29
30impl Error {
31    /// A problem finding or opening the credentials file.
32    pub fn is_loading(&self) -> bool {
33        matches!(self.0, ErrorKind::Loading(_))
34    }
35
36    /// A problem parsing a credentials JSON specification.
37    pub fn is_parsing(&self) -> bool {
38        matches!(self.0, ErrorKind::Parsing(_))
39    }
40
41    /// The credentials type is invalid or unknown.
42    pub fn is_unknown_type(&self) -> bool {
43        matches!(self.0, ErrorKind::UnknownType(_))
44    }
45
46    /// A required field was missing from the builder.
47    pub fn is_missing_field(&self) -> bool {
48        matches!(self.0, ErrorKind::MissingField(_))
49    }
50
51    #[cfg(google_cloud_unstable_id_token)]
52    /// The credential type is not supported for the given use case.
53    pub fn is_not_supported(&self) -> bool {
54        matches!(self.0, ErrorKind::NotSupported(_))
55    }
56
57    /// Create an error representing problems loading or reading a credentials
58    /// file.
59    pub(crate) fn loading<T>(source: T) -> Error
60    where
61        T: Into<BoxError>,
62    {
63        Error(ErrorKind::Loading(source.into()))
64    }
65
66    /// A problem parsing a credentials specification.
67    pub(crate) fn parsing<T>(source: T) -> Error
68    where
69        T: Into<BoxError>,
70    {
71        Error(ErrorKind::Parsing(source.into()))
72    }
73
74    /// The credential type is unknown or invalid.
75    pub(crate) fn unknown_type<T>(source: T) -> Error
76    where
77        T: Into<BoxError>,
78    {
79        Error(ErrorKind::UnknownType(source.into()))
80    }
81
82    /// A required field was missing from the builder.
83    pub(crate) fn missing_field(field: &'static str) -> Error {
84        Error(ErrorKind::MissingField(field))
85    }
86
87    #[cfg(google_cloud_unstable_id_token)]
88    /// The given credential type is not supported.
89    pub(crate) fn not_supported<T>(credential_type: T) -> Error
90    where
91        T: Into<BoxError>,
92    {
93        Error(ErrorKind::NotSupported(credential_type.into()))
94    }
95}
96
97#[derive(thiserror::Error, Debug)]
98enum ErrorKind {
99    #[error("could not find or open the credentials file {0}")]
100    Loading(#[source] BoxError),
101    #[error("cannot parse the credentials file {0}")]
102    Parsing(#[source] BoxError),
103    #[error("unknown or invalid credentials type {0}")]
104    UnknownType(#[source] BoxError),
105    #[error("missing required field: {0}")]
106    MissingField(&'static str),
107    #[cfg(google_cloud_unstable_id_token)]
108    #[error("credentials type not supported: {0}")]
109    NotSupported(#[source] BoxError),
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115    use std::error::Error as _;
116
117    #[test]
118    fn constructors() {
119        let error = Error::loading("test message");
120        assert!(error.is_loading(), "{error:?}");
121        assert!(error.source().is_some(), "{error:?}");
122        assert!(error.to_string().contains("test message"), "{error}");
123
124        let error = Error::parsing("test message");
125        assert!(error.is_parsing(), "{error:?}");
126        assert!(error.source().is_some(), "{error:?}");
127        assert!(error.to_string().contains("test message"), "{error}");
128
129        let error = Error::unknown_type("test message");
130        assert!(error.is_unknown_type(), "{error:?}");
131        assert!(error.source().is_some(), "{error:?}");
132        assert!(error.to_string().contains("test message"), "{error}");
133
134        let error = Error::missing_field("test field");
135        assert!(error.is_missing_field(), "{error:?}");
136        assert!(error.source().is_none(), "{error:?}");
137        assert!(error.to_string().contains("test field"), "{error}");
138    }
139}