Skip to content

Commit 8edde3e

Browse files
committed
feature: support a simple config loader
1 parent 65bf817 commit 8edde3e

File tree

7 files changed

+227
-1
lines changed

7 files changed

+227
-1
lines changed

Cargo.lock

+110
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ edition = "2021"
99
anyhow = "1.0.83"
1010
arc-swap = "1.7.1"
1111
crossbeam-channel = "0.5.12"
12+
serde = { version = "1.0.203", features = ["derive"] }
13+
serde_yaml = "0.9.34"

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Geektime Rust 语言训练营
22

3-
0512 答疑
3+
答疑代码

examples/config.rs

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
use anyhow::Result;
2+
use serde::Deserialize;
3+
4+
trait ConfigMerge {
5+
fn merge(&mut self, to_merge: Self) -> Result<()>;
6+
}
7+
8+
#[derive(Debug, Default, Deserialize)]
9+
pub struct Config {
10+
#[serde(default)]
11+
pub server: ServerConfig,
12+
#[serde(default)]
13+
pub database: DatabaseConfig,
14+
}
15+
16+
#[derive(Debug, Default, Deserialize)]
17+
pub struct ServerConfig {
18+
#[serde(default)]
19+
pub port: u16,
20+
}
21+
22+
#[derive(Debug, Default, Deserialize)]
23+
pub struct DatabaseConfig {
24+
#[serde(default)]
25+
pub host: String,
26+
#[serde(default)]
27+
pub dbname: String,
28+
#[serde(default)]
29+
pub user: String,
30+
#[serde(default)]
31+
pub password: String,
32+
}
33+
34+
impl Config {
35+
pub fn load(env: &str) -> Result<Config> {
36+
let mut base = Config::load_default()?;
37+
match env {
38+
"prod" => {
39+
let config = std::fs::read_to_string("fixtures/prod.yml")?;
40+
let to_merge = serde_yaml::from_str(&config)?;
41+
base.merge(to_merge)?
42+
}
43+
"dev" => {
44+
let config = std::fs::read_to_string("fixtures/dev.yml")?;
45+
let to_merge = serde_yaml::from_str(&config)?;
46+
base.merge(to_merge)?
47+
}
48+
_ => panic!("Unknown environment"),
49+
};
50+
Ok(base)
51+
}
52+
53+
fn load_default() -> Result<Config> {
54+
let config = include_str!("../fixtures/default.yml");
55+
let config: Config = serde_yaml::from_str(config)?;
56+
Ok(config)
57+
}
58+
}
59+
60+
impl ConfigMerge for ServerConfig {
61+
fn merge(&mut self, to_merge: Self) -> Result<()> {
62+
if to_merge.port != 0 {
63+
self.port = to_merge.port;
64+
}
65+
Ok(())
66+
}
67+
}
68+
69+
impl ConfigMerge for DatabaseConfig {
70+
fn merge(&mut self, to_merge: Self) -> Result<()> {
71+
if !to_merge.host.is_empty() {
72+
self.host = to_merge.host;
73+
}
74+
if !to_merge.dbname.is_empty() {
75+
self.dbname = to_merge.dbname;
76+
}
77+
if !to_merge.user.is_empty() {
78+
self.user = to_merge.user;
79+
}
80+
if !to_merge.password.is_empty() {
81+
self.password = to_merge.password;
82+
}
83+
Ok(())
84+
}
85+
}
86+
87+
impl ConfigMerge for Config {
88+
fn merge(&mut self, to_merge: Self) -> Result<()> {
89+
self.server.merge(to_merge.server)?;
90+
self.database.merge(to_merge.database)?;
91+
Ok(())
92+
}
93+
}
94+
95+
fn main() -> Result<()> {
96+
let config = Config::load("prod")?;
97+
println!("{:?}", config);
98+
Ok(())
99+
}

fixtures/default.yml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
server:
2+
port: 8080
3+
4+
database:
5+
host: localhost:5432
6+
user: myuser
7+
password: vault:secret:mydb:myuser
8+
dbname: mydb

fixtures/dev.yml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
server:
2+
port: 8081

fixtures/prod.yml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
server:
2+
port: 80
3+
4+
database:
5+
host: db.acme.com:5432

0 commit comments

Comments
 (0)