use std::fmt;
use std::str::FromStr;
#[derive(Debug)]
struct ParseEnumError(String);
impl fmt::Display for ParseEnumError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl std::error::Error for ParseEnumError {}
#[derive(confroid::ConfigValue, Debug, Clone, Copy, PartialEq, Eq)]
enum LogLevel {
Error,
Warn,
Info,
Debug,
Trace,
}
impl FromStr for LogLevel {
type Err = ParseEnumError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"error" => Ok(Self::Error),
"warn" | "warning" => Ok(Self::Warn),
"info" => Ok(Self::Info),
"debug" => Ok(Self::Debug),
"trace" => Ok(Self::Trace),
other => Err(ParseEnumError(format!(
"unknown log level `{other}` (expected error|warn|info|debug|trace)"
))),
}
}
}
impl fmt::Display for LogLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::Error => "error",
Self::Warn => "warn",
Self::Info => "info",
Self::Debug => "debug",
Self::Trace => "trace",
})
}
}
#[derive(confroid::ConfigValue, Debug, Clone, Copy, PartialEq, Eq)]
enum Mode {
Standalone,
Cluster,
}
impl FromStr for Mode {
type Err = ParseEnumError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"standalone" => Ok(Self::Standalone),
"cluster" => Ok(Self::Cluster),
other => Err(ParseEnumError(format!(
"unknown mode `{other}` (expected standalone|cluster)"
))),
}
}
}
impl fmt::Display for Mode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::Standalone => "standalone",
Self::Cluster => "cluster",
})
}
}
#[derive(confroid::Config, Debug)]
#[allow(dead_code)] struct Config {
#[confroid(default = LogLevel::Info, example = "debug")]
log_level: LogLevel,
#[confroid(default = Mode::Standalone)]
mode: Mode,
}
fn main() {
match confroid::from_env::<Config>() {
Ok(config) => println!("from environment: {config:?}"),
Err(err) => eprintln!("config error: {err}"),
}
let config: Config =
confroid::from_pairs([("LOG_LEVEL", "debug"), ("MODE", "cluster")]).expect("valid config");
println!("explicit: {config:?}");
let defaults: Config =
confroid::from_pairs(Vec::<(&str, &str)>::new()).expect("defaults are total");
println!("all defaults: {defaults:?}");
}