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    /// The credential type is not supported for the given use case.
52    pub fn is_not_supported(&self) -> bool {
53        matches!(self.0, ErrorKind::NotSupported(_))
54    }
55
56    /// Create an error representing problems loading or reading a credentials
57    /// file.
58    pub(crate) fn loading<T>(source: T) -> Error
59    where
60        T: Into<BoxError>,
61    {
62        Error(ErrorKind::Loading(source.into()))
63    }
64
65    /// A problem parsing a credentials specification.
66    pub(crate) fn parsing<T>(source: T) -> Error
67    where
68        T: Into<BoxError>,
69    {
70        Error(ErrorKind::Parsing(source.into()))
71    }
72
73    /// The credential type is unknown or invalid.
74    pub(crate) fn unknown_type<T>(source: T) -> Error
75    where
76        T: Into<BoxError>,
77    {
78        Error(ErrorKind::UnknownType(source.into()))
79    }
80
81    /// A required field was missing from the builder.
82    pub(crate) fn missing_field(field: &'static str) -> Error {
83        Error(ErrorKind::MissingField(field))
84    }
85
86    /// The given credential type is not supported.
87    pub(crate) fn not_supported<T>(credential_type: T) -> Error
88    where
89        T: Into<BoxError>,
90    {
91        Error(ErrorKind::NotSupported(credential_type.into()))
92    }
93}
94
95#[derive(thiserror::Error, Debug)]
96enum ErrorKind {
97    #[error("could not find or open the credentials file {0}")]
98    Loading(#[source] BoxError),
99    #[error("cannot parse the credentials file {0}")]
100    Parsing(#[source] BoxError),
101    #[error("unknown or invalid credentials type {0}")]
102    UnknownType(#[source] BoxError),
103    #[error("missing required field: {0}")]
104    MissingField(&'static str),
105    #[error("credentials type not supported: {0}")]
106    NotSupported(#[source] BoxError),
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112    use std::error::Error as _;
113
114    #[test]
115    fn constructors() {
116        let error = Error::loading("test message");
117        assert!(error.is_loading(), "{error:?}");
118        assert!(error.source().is_some(), "{error:?}");
119        assert!(error.to_string().contains("test message"), "{error}");
120
121        let error = Error::parsing("test message");
122        assert!(error.is_parsing(), "{error:?}");
123        assert!(error.source().is_some(), "{error:?}");
124        assert!(error.to_string().contains("test message"), "{error}");
125
126        let error = Error::unknown_type("test message");
127        assert!(error.is_unknown_type(), "{error:?}");
128        assert!(error.source().is_some(), "{error:?}");
129        assert!(error.to_string().contains("test message"), "{error}");
130
131        let error = Error::missing_field("test field");
132        assert!(error.is_missing_field(), "{error:?}");
133        assert!(error.source().is_none(), "{error:?}");
134        assert!(error.to_string().contains("test field"), "{error}");
135    }
136}