aws_types/
service_config.rs

1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! Code for extracting service config from the user's environment.
7
8use std::fmt;
9
10/// A struct used with the [`LoadServiceConfig`] trait to extract service config from the user's environment.
11// [profile active-profile]
12// services = dev
13//
14// [services dev]
15// service-id =
16//   config-key = config-value
17#[derive(Clone, Debug, PartialEq, Eq, Hash)]
18pub struct ServiceConfigKey<'a> {
19    service_id: &'a str,
20    profile: &'a str,
21    env: &'a str,
22}
23
24impl<'a> ServiceConfigKey<'a> {
25    /// Create a new [`ServiceConfigKey`] builder struct.
26    pub fn builder() -> builder::Builder<'a> {
27        Default::default()
28    }
29    /// Get the service ID.
30    pub fn service_id(&self) -> &'a str {
31        self.service_id
32    }
33    /// Get the profile key.
34    pub fn profile(&self) -> &'a str {
35        self.profile
36    }
37    /// Get the environment key.
38    pub fn env(&self) -> &'a str {
39        self.env
40    }
41}
42
43pub mod builder {
44    //! Builder for [`ServiceConfigKey`].
45
46    use super::ServiceConfigKey;
47    use std::fmt;
48
49    /// Builder for [`ServiceConfigKey`].
50    #[derive(Default, Debug)]
51    pub struct Builder<'a> {
52        service_id: Option<&'a str>,
53        profile: Option<&'a str>,
54        env: Option<&'a str>,
55    }
56
57    impl<'a> Builder<'a> {
58        /// Set the service ID.
59        pub fn service_id(mut self, service_id: &'a str) -> Self {
60            self.service_id = Some(service_id);
61            self
62        }
63
64        /// Set the profile key.
65        pub fn profile(mut self, profile: &'a str) -> Self {
66            self.profile = Some(profile);
67            self
68        }
69
70        /// Set the environment key.
71        pub fn env(mut self, env: &'a str) -> Self {
72            self.env = Some(env);
73            self
74        }
75
76        /// Build the [`ServiceConfigKey`].
77        ///
78        /// Returns an error if any of the required fields are missing.
79        pub fn build(self) -> Result<ServiceConfigKey<'a>, Error> {
80            Ok(ServiceConfigKey {
81                service_id: self.service_id.ok_or_else(Error::missing_service_id)?,
82                profile: self.profile.ok_or_else(Error::missing_profile)?,
83                env: self.env.ok_or_else(Error::missing_env)?,
84            })
85        }
86    }
87
88    #[allow(clippy::enum_variant_names)]
89    #[derive(Debug)]
90    enum ErrorKind {
91        MissingServiceId,
92        MissingProfile,
93        MissingEnv,
94    }
95
96    impl fmt::Display for ErrorKind {
97        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98            match self {
99                ErrorKind::MissingServiceId => write!(f, "missing required service-id"),
100                ErrorKind::MissingProfile => write!(f, "missing required active profile name"),
101                ErrorKind::MissingEnv => write!(f, "missing required environment variable name"),
102            }
103        }
104    }
105
106    /// Error type for [`ServiceConfigKey::builder`]
107    #[derive(Debug)]
108    pub struct Error {
109        kind: ErrorKind,
110    }
111
112    impl fmt::Display for Error {
113        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114            write!(f, "couldn't build a ServiceEnvConfigKey: {}", self.kind)
115        }
116    }
117
118    impl std::error::Error for Error {}
119
120    impl Error {
121        /// Create a new "missing service ID" error
122        pub fn missing_service_id() -> Self {
123            Self {
124                kind: ErrorKind::MissingServiceId,
125            }
126        }
127        /// Create a new "missing profile key" error
128        pub fn missing_profile() -> Self {
129            Self {
130                kind: ErrorKind::MissingProfile,
131            }
132        }
133        /// Create a new "missing env key" error
134        pub fn missing_env() -> Self {
135            Self {
136                kind: ErrorKind::MissingEnv,
137            }
138        }
139    }
140}
141
142/// Implementers of this trait can provide service config defined in a user's environment.
143pub trait LoadServiceConfig: fmt::Debug + Send + Sync {
144    /// Given a [`ServiceConfigKey`], return the value associated with it.
145    fn load_config(&self, key: ServiceConfigKey<'_>) -> Option<String>;
146}