use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Environment {
Development,
Test,
Production,
Other(String),
}
impl Environment {
#[must_use]
pub fn parse(name: &str) -> Self {
match name.trim().to_ascii_lowercase().as_str() {
"development" | "dev" | "" => Self::Development,
"test" => Self::Test,
"production" | "prod" => Self::Production,
other => Self::Other(other.to_string()),
}
}
#[must_use]
pub fn from_env() -> Self {
std::env::var("APP_ENV")
.or_else(|_| std::env::var("LOCO_ENV"))
.map_or(Self::Development, |name| Self::parse(&name))
}
#[must_use]
pub fn is_production_like(&self) -> bool {
!matches!(self, Self::Development | Self::Test)
}
}
impl fmt::Display for Environment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::Development => "development",
Self::Test => "test",
Self::Production => "production",
Self::Other(name) => name,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_names_and_short_forms() {
assert_eq!(Environment::parse("prod"), Environment::Production);
assert_eq!(Environment::parse("DEV"), Environment::Development);
assert_eq!(Environment::parse("test"), Environment::Test);
}
#[test]
fn names_round_trip() {
for name in ["development", "test", "production", "staging"] {
assert_eq!(Environment::parse(name).to_string(), name);
}
}
#[test]
fn empty_name_means_development() {
assert_eq!(Environment::parse(" "), Environment::Development);
}
#[test]
fn unknown_environment_is_production_like() {
assert!(Environment::parse("staging").is_production_like());
assert!(!Environment::Test.is_production_like());
}
}