1use serde::Deserialize;
2use std::sync::Arc;
3
4#[derive(Deserialize)]
6pub struct Config {
7 app_name: Option<Arc<str>>,
8 host: Option<Arc<str>>,
9 port: Option<u16>,
10 #[serde(skip)]
11 address: Option<Arc<str>>,
12}
13
14impl Config {
15 pub fn new() -> envy::Result<Self> {
17 ConfigBuilder::default().build()
18 }
19
20 pub fn builder<'a>() -> ConfigBuilder<'a> {
22 ConfigBuilder::default()
23 }
24
25 pub fn app_name(&self) -> &str {
27 self.app_name.as_deref().unwrap()
28 }
29
30 pub fn address(&self) -> &str {
32 self.address.as_deref().unwrap()
33 }
34
35 pub fn port(&self) -> u16 {
37 self.port.unwrap_or(3000)
38 }
39}
40
41#[derive(Default)]
43pub struct ConfigBuilder<'a> {
44 prefix: Option<&'a str>,
45}
46
47impl<'a> ConfigBuilder<'a> {
48 pub fn with_prefix(mut self, prefix: &'a str) -> Self {
50 self.prefix = Some(prefix);
51 self
52 }
53
54 pub fn build(self) -> envy::Result<Config> {
56 let prefix = self.prefix.unwrap_or("SERVER_");
57 let mut cfg: Config = envy::prefixed(prefix).from_env()?;
58 if cfg.app_name.is_none() {
59 cfg.app_name = Some(Arc::from("quick-microservice"));
60 }
61 let host = cfg.host.as_deref().unwrap_or("127.0.0.1");
62 let port = cfg.port.unwrap_or(3000);
63 cfg.address = Some(Arc::from(format!("{}:{}", host, port)));
64 Ok(cfg)
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 #[test]
71 fn parse_builtin_config_test() -> envy::Result<()> {
72 let cfg = super::Config::builder()
73 .with_prefix("DEFAULT_SERVER_NOT_SET_IN_SHELL_")
74 .build()?;
75 assert_eq!(cfg.address(), "127.0.0.1:3000");
76 Ok(())
77 }
78
79 #[test]
80 fn parse_default_config_test() -> envy::Result<()> {
81 std::env::set_var("SERVER_HOST", "localhost");
82 std::env::set_var("SERVER_PORT", "3000");
83 let cfg = super::Config::new()?;
84 assert_eq!(cfg.address(), "localhost:3000");
85 Ok(())
86 }
87
88 #[test]
89 fn parse_prefixed_config_test() -> envy::Result<()> {
90 std::env::set_var("SERVER_CUSTOM_HOST", "localhost");
91 std::env::set_var("SERVER_CUSTOM_PORT", "3000");
92 let cfg = super::Config::builder()
93 .with_prefix("SERVER_CUSTOM_")
94 .build()?;
95 assert_eq!(cfg.address(), "localhost:3000");
96 Ok(())
97 }
98}