Skip to main content

use_config_profile/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use core::{fmt, str::FromStr};
5use std::error::Error;
6
7/// A primitive runtime or deployment profile name.
8#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
9pub enum ConfigProfile {
10    /// Local developer profile.
11    Local,
12    /// Development profile.
13    Development,
14    /// Test profile.
15    Test,
16    /// Staging profile.
17    Staging,
18    /// Production profile.
19    Production,
20    /// Caller-defined profile name.
21    Custom(String),
22}
23
24/// Error returned when a profile name is invalid.
25#[derive(Clone, Copy, Debug, Eq, PartialEq)]
26pub struct ConfigProfileError;
27
28impl fmt::Display for ConfigProfileError {
29    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
30        formatter.write_str("configuration profile is empty")
31    }
32}
33
34impl Error for ConfigProfileError {}
35
36impl fmt::Display for ConfigProfile {
37    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
38        match self {
39            Self::Local => formatter.write_str("local"),
40            Self::Development => formatter.write_str("development"),
41            Self::Test => formatter.write_str("test"),
42            Self::Staging => formatter.write_str("staging"),
43            Self::Production => formatter.write_str("production"),
44            Self::Custom(value) => formatter.write_str(value),
45        }
46    }
47}
48
49impl FromStr for ConfigProfile {
50    type Err = ConfigProfileError;
51
52    fn from_str(input: &str) -> Result<Self, Self::Err> {
53        let trimmed = input.trim();
54
55        if trimmed.is_empty() {
56            return Err(ConfigProfileError);
57        }
58
59        let profile = match trimmed.to_ascii_lowercase().as_str() {
60            "local" => Self::Local,
61            "development" | "dev" => Self::Development,
62            "test" | "testing" => Self::Test,
63            "staging" | "stage" => Self::Staging,
64            "production" | "prod" => Self::Production,
65            _ => Self::Custom(trimmed.to_owned()),
66        };
67
68        Ok(profile)
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::{ConfigProfile, ConfigProfileError};
75    use std::str::FromStr;
76
77    #[test]
78    fn parse_known_profiles() {
79        assert_eq!(ConfigProfile::from_str("local"), Ok(ConfigProfile::Local));
80        assert_eq!(
81            ConfigProfile::from_str("development"),
82            Ok(ConfigProfile::Development)
83        );
84        assert_eq!(ConfigProfile::from_str("test"), Ok(ConfigProfile::Test));
85        assert_eq!(
86            ConfigProfile::from_str("staging"),
87            Ok(ConfigProfile::Staging)
88        );
89        assert_eq!(
90            ConfigProfile::from_str("production"),
91            Ok(ConfigProfile::Production)
92        );
93    }
94
95    #[test]
96    fn parse_aliases() {
97        assert_eq!(
98            ConfigProfile::from_str("dev"),
99            Ok(ConfigProfile::Development)
100        );
101        assert_eq!(
102            ConfigProfile::from_str("prod"),
103            Ok(ConfigProfile::Production)
104        );
105        assert_eq!(ConfigProfile::from_str("stage"), Ok(ConfigProfile::Staging));
106    }
107
108    #[test]
109    fn parse_custom_profile() {
110        assert_eq!(
111            ConfigProfile::from_str("preview"),
112            Ok(ConfigProfile::Custom("preview".to_owned()))
113        );
114        assert_eq!(ConfigProfile::from_str(" "), Err(ConfigProfileError));
115    }
116
117    #[test]
118    fn display_known_profiles() {
119        assert_eq!(ConfigProfile::Local.to_string(), "local");
120        assert_eq!(ConfigProfile::Development.to_string(), "development");
121        assert_eq!(ConfigProfile::Production.to_string(), "production");
122    }
123
124    #[test]
125    fn display_custom_profile() {
126        assert_eq!(
127            ConfigProfile::Custom("preview".to_owned()).to_string(),
128            "preview"
129        );
130    }
131}