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