use ayun_core::{
errors::ContainerError,
traits::{ErrorTrait, InstanceTrait},
Container, Error, Result,
};
use std::str::FromStr;
#[derive(Debug, Default, Clone)]
pub enum Environment {
#[default]
Development,
Production,
Testing,
Any(String),
}
impl InstanceTrait for Environment {
fn register(_: &Container) -> Result<Self, ContainerError> {
let environment = match Self::try_from_args() {
Ok(env) => env,
Err(_) => Self::try_from_assertion().map_err(Error::wrap)?,
};
#[cfg(feature = "color-eyre")]
if !environment.production() {
color_eyre::install().expect("Failed to install color eyre");
}
Ok(environment)
}
}
impl Environment {
fn try_from_args() -> Result<Self, Error> {
let args: Vec<String> = std::env::args()
.filter(|arg| arg.starts_with("--env="))
.map(|arg| arg.replace("--env=", ""))
.collect();
let env = args
.first()
.map(|arg| arg.to_owned().into())
.ok_or(Error::InvalidArgument(
"No environment specified".to_string(),
))?;
Ok(env)
}
fn try_from_assertion() -> Result<Self, Error> {
match cfg!(debug_assertions) {
true => Ok(Self::Development),
false => Ok(Self::Production),
}
}
}
impl Environment {
pub fn production(&self) -> bool {
matches!(self, Self::Production)
}
pub fn development(&self) -> bool {
matches!(self, Self::Development)
}
pub fn testing(&self) -> bool {
matches!(self, Self::Testing)
}
}
impl From<String> for Environment {
fn from(env: String) -> Self {
Self::from_str(&env).unwrap_or(Self::Any(env))
}
}
impl FromStr for Environment {
type Err = &'static str;
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"production" => Ok(Self::Production),
"development" => Ok(Self::Development),
"test" => Ok(Self::Testing),
s => Ok(Self::Any(s.to_string())),
}
}
}
impl std::fmt::Display for Environment {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Environment::Development => "development".fmt(f),
Environment::Production => "production".fmt(f),
Environment::Testing => "testing".fmt(f),
Environment::Any(s) => s.fmt(f),
}
}
}