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
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
//! Code for extracting service config from the user's environment.
use std::fmt;
/// A struct used with the [`LoadServiceConfig`] trait to extract service config from the user's environment.
// [profile active-profile]
// services = dev
//
// [services dev]
// service-id =
// config-key = config-value
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ServiceConfigKey<'a> {
service_id: &'a str,
profile: &'a str,
env: &'a str,
}
impl<'a> ServiceConfigKey<'a> {
/// Create a new [`ServiceConfigKey`] builder struct.
pub fn builder() -> builder::Builder<'a> {
Default::default()
}
/// Get the service ID.
pub fn service_id(&self) -> &'a str {
self.service_id
}
/// Get the profile key.
pub fn profile(&self) -> &'a str {
self.profile
}
/// Get the environment key.
pub fn env(&self) -> &'a str {
self.env
}
}
pub mod builder {
//! Builder for [`ServiceConfigKey`].
use super::ServiceConfigKey;
use std::fmt;
/// Builder for [`ServiceConfigKey`].
#[derive(Default, Debug)]
pub struct Builder<'a> {
service_id: Option<&'a str>,
profile: Option<&'a str>,
env: Option<&'a str>,
}
impl<'a> Builder<'a> {
/// Set the service ID.
pub fn service_id(mut self, service_id: &'a str) -> Self {
self.service_id = Some(service_id);
self
}
/// Set the profile key.
pub fn profile(mut self, profile: &'a str) -> Self {
self.profile = Some(profile);
self
}
/// Set the environment key.
pub fn env(mut self, env: &'a str) -> Self {
self.env = Some(env);
self
}
/// Build the [`ServiceConfigKey`].
///
/// Returns an error if any of the required fields are missing.
pub fn build(self) -> Result<ServiceConfigKey<'a>, Error> {
Ok(ServiceConfigKey {
service_id: self.service_id.ok_or_else(Error::missing_service_id)?,
profile: self.profile.ok_or_else(Error::missing_profile)?,
env: self.env.ok_or_else(Error::missing_env)?,
})
}
}
#[allow(clippy::enum_variant_names)]
#[derive(Debug)]
enum ErrorKind {
MissingServiceId,
MissingProfile,
MissingEnv,
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorKind::MissingServiceId => write!(f, "missing required service-id"),
ErrorKind::MissingProfile => write!(f, "missing required active profile name"),
ErrorKind::MissingEnv => write!(f, "missing required environment variable name"),
}
}
}
/// Error type for [`ServiceConfigKey::builder`]
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "couldn't build a ServiceEnvConfigKey: {}", self.kind)
}
}
impl std::error::Error for Error {}
impl Error {
/// Create a new "missing service ID" error
pub fn missing_service_id() -> Self {
Self {
kind: ErrorKind::MissingServiceId,
}
}
/// Create a new "missing profile key" error
pub fn missing_profile() -> Self {
Self {
kind: ErrorKind::MissingProfile,
}
}
/// Create a new "missing env key" error
pub fn missing_env() -> Self {
Self {
kind: ErrorKind::MissingEnv,
}
}
}
}
/// Implementers of this trait can provide service config defined in a user's environment.
pub trait LoadServiceConfig: fmt::Debug + Send + Sync {
/// Given a [`ServiceConfigKey`], return the value associated with it.
fn load_config(&self, key: ServiceConfigKey<'_>) -> Option<String>;
}