enum_config/
enum_config.rs1use std::fmt;
11use std::str::FromStr;
12
13#[derive(Debug)]
14struct ParseEnumError(String);
15
16impl fmt::Display for ParseEnumError {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 f.write_str(&self.0)
19 }
20}
21
22impl std::error::Error for ParseEnumError {}
23
24#[derive(confroid::ConfigValue, Debug, Clone, Copy, PartialEq, Eq)]
26enum LogLevel {
27 Error,
28 Warn,
29 Info,
30 Debug,
31 Trace,
32}
33
34impl FromStr for LogLevel {
35 type Err = ParseEnumError;
36 fn from_str(s: &str) -> Result<Self, Self::Err> {
37 match s.to_ascii_lowercase().as_str() {
38 "error" => Ok(Self::Error),
39 "warn" | "warning" => Ok(Self::Warn),
40 "info" => Ok(Self::Info),
41 "debug" => Ok(Self::Debug),
42 "trace" => Ok(Self::Trace),
43 other => Err(ParseEnumError(format!(
44 "unknown log level `{other}` (expected error|warn|info|debug|trace)"
45 ))),
46 }
47 }
48}
49
50impl fmt::Display for LogLevel {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 f.write_str(match self {
53 Self::Error => "error",
54 Self::Warn => "warn",
55 Self::Info => "info",
56 Self::Debug => "debug",
57 Self::Trace => "trace",
58 })
59 }
60}
61
62#[derive(confroid::ConfigValue, Debug, Clone, Copy, PartialEq, Eq)]
64enum Mode {
65 Standalone,
66 Cluster,
67}
68
69impl FromStr for Mode {
70 type Err = ParseEnumError;
71 fn from_str(s: &str) -> Result<Self, Self::Err> {
72 match s.to_ascii_lowercase().as_str() {
73 "standalone" => Ok(Self::Standalone),
74 "cluster" => Ok(Self::Cluster),
75 other => Err(ParseEnumError(format!(
76 "unknown mode `{other}` (expected standalone|cluster)"
77 ))),
78 }
79 }
80}
81
82impl fmt::Display for Mode {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.write_str(match self {
85 Self::Standalone => "standalone",
86 Self::Cluster => "cluster",
87 })
88 }
89}
90
91#[derive(confroid::Config, Debug)]
92#[allow(dead_code)] struct Config {
94 #[confroid(default = LogLevel::Info, example = "debug")]
96 log_level: LogLevel,
97 #[confroid(default = Mode::Standalone)]
99 mode: Mode,
100}
101
102fn main() {
103 match confroid::from_env::<Config>() {
105 Ok(config) => println!("from environment: {config:?}"),
106 Err(err) => eprintln!("config error: {err}"),
107 }
108
109 let config: Config =
111 confroid::from_pairs([("LOG_LEVEL", "debug"), ("MODE", "cluster")]).expect("valid config");
112 println!("explicit: {config:?}");
113
114 let defaults: Config =
115 confroid::from_pairs(Vec::<(&str, &str)>::new()).expect("defaults are total");
116 println!("all defaults: {defaults:?}");
117}