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