use_config_profile/
lib.rs1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use core::{fmt, str::FromStr};
5use std::error::Error;
6
7#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
9pub enum ConfigProfile {
10 Local,
12 Development,
14 Test,
16 Staging,
18 Production,
20 Custom(String),
22}
23
24#[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}