Crates.io | stackedconfig |
lib.rs | stackedconfig |
version | 0.1.2 |
source | src |
created_at | 2018-01-09 03:12:13.87681 |
updated_at | 2018-01-19 04:31:01.738144 |
description | !!! DO NOT USE !!! Treat multiple nested config objects as a single config object with precedence. !!! DO NOT USE !!! |
homepage | https://github.com/bheklilr/rust-stackedconfig |
repository | https://github.com/bheklilr/rust-stackedconfig |
max_upload_size | |
id | 46052 |
size | 667,914 |
Treat multiple nested config objects (e.g. JSON or YAML files) as a single config object with precedence.
You shouldn't, it isn't anywhere near done yet and I'm definitely not the best at keeping up with side projects. This software is pre-alpha.
This is a fun, small side-project for me to learn rust better, but my goal is for it to be good enough eventually for someone else to use seriously.
Have you ever had the situation where your application had complex configuration? Something like this contrived example?
notifications:
email:
address: user@example.com
on_new_post: false
on_new_message: true
appearance:
theme: dark
font:
family: Arial
size: 14pt
web:
proxy:
http: http://proxy.com
https: https://proxy.com
ssl_verify: true
trusted_hosts:
- crates.io
- rust-lang.org
credentials:
username: null
token: null
And you wanted to have multiple config files, such as on the system level in
$APPDIR/app_config.yaml
, on the user level at $HOME/app_config.yaml
, and
on the project level at $PROJECTDIR/app_config.yaml
. Managing multiple config
files with fallback is a pain. This library aims to make it easy to work with:
extern crate serde_json;
extern crate stackedconfig;
use serde_json::{Value, from_str};
use stackedconfig::{ConfigStack};
fn main() {
// Normally would load these from disk
let system_conf: Value = from_str(r#"
{
"notifications": {
"email": {
"on_new_post": true,
"on_new_message": true
}
},
"appearance":{
"theme": "light",
"font": {
"family": "Arial",
"size": "14pt"
}
}
"web": {
"proxy": {
"http": "http://proxy.com",
"https": "https://proxy.com"
},
"ssl_verify": true,
"trusted_hosts": []
},
"credentials": {
"username": null,
"token": null
}
}
"#)?;
let user_conf: Value = from_str(r#"
{
"notifications": {
"email": {
"address": "user@example.com"
}
},
"appearance": {
"theme": "dark"
},
"web": {
"trusted_hosts": ["crates.io", "rust-lang.org"]
},
"credentials": {
"username": "bheklilr",
"token": "123456abcdef"
}
}
"#)?;
let stack = ConfigStack::new()
.stack(system_conf)
.stack(user_conf);
// Nested access is available, separator can be customized to any character
// with the `with_sep` method.
println!("{}", stack.get("notifications/email/address")?.unwrap());
// Calls to `get` return a `ConfigStack`, so sub-sections could be passed to
// the relevant parts of your application
println!("{}", stack.get("appearance")?.get("theme")?.unwrap());
// The last config stacked takes precedence when doing lookups.
// Values can be unwrapped from the stack for actual use later.
println!("{}", stack.get("web/proxy/http")?.unwrap());
}
Currently right now it only supports serde_json
. My plan is to add
serde_yaml
and maybe some other formats as this project grows.
I put it under MIT, but honestly I really don't care what anyone does with this code. It is provided as-is. If you find a bug, feel free to submit an issue, or even better submit a PR fixing it.