Crates.io | curlyconf |
lib.rs | curlyconf |
version | 0.1.0 |
source | src |
created_at | 2020-08-11 21:56:44.133834 |
updated_at | 2021-01-21 10:36:38.055126 |
description | Configuration file parser |
homepage | https://github.com/miquels/curlyconf-rs |
repository | https://github.com/miquels/curlyconf-rs |
max_upload_size | |
id | 275514 |
size | 107,704 |
Curlyconf is a configuration file reader for the configuration file format used by, for example, named.conf and dhcpd.conf.
person charlie {
fullname "Charlie Brown";
address 192.168.1.1;
}
person snoopy {
fullname "Snoopy";
}
use serde::Deserialize;
// The initial section of any config is a rust struct.
#[derive(Debug, Deserialize)]
struct Config {
person: Vec<Person>,
}
#[derive(Debug, Deserialize)]
struct Person {
#[serde(rename = "__label__")]
name: String,
#[serde(default)]
fullname: Option<String>,
#[serde(default)]
address: Option<std::net::IpAddr>,
}
fn main() {
// Read the configuration file.
let config: Config = match curlyconf::from_file("file.cfg") {
Ok(cfg) => cfg,
Err(e) => {
eprintln!("{}", e);
std::process::exit(1);
}
};
// Print what we got (println!("{:?}", config) would be easier...).
for (i, p) in config.person.iter().enumerate() {
println!("{}: {} fullname {:?} addr {:?}", i, p.name, p.fullname, p.address);
}
}
0: charlie fullname Some("Charlie Brown") addr Some(V4(192.168.1.1))
1: snoopy fullname Some("Snoopy") addr None
Curlyconf uses serde to deserialize the configuration file values to rust types, just like almost every other crate that does something similar.
The configuration file contains section names, labels, sections, value names, and values:
Vec
,
there can be multiple values, separated by a comma.A section can only have a label if:
HashMap<Key, Section>
, orVec<Section>
and the rust struct that corresponds to the
section has a __label__
field. That field will be set to the label value.The label type can be any type, it does not have to be a string - it could
also be, for example, a PathBuf
or IpAddr
.
The basic structure of a config file is thus:
section_name [label] {
value_name value [,value...];
value_name value [,value...];
section_name [label] {
value_name value [,value...];
}
}
Enum
s are also supported (see the serde
docs) so you can do things like:
#[derive(Debug, Deserialize)]
struct Config {
animal: Animal,
}
#[derive(Debug, Deserialize)]
enum Animal {
Cat {
purrs: bool,
},
Dog {
barks: bool,
},
}
And then have a config like
animal cat {
purrs;
}
In every section it is possible to include another file, or multiple files. Simply do:
include otherconfig.cfg;
If the pathname of the included file is relative, it will be interpreted as relative to the current file being parsed. It's possible to use wildcards as well, for example:
configs {
include conf.d/*.cfg;
}
There are some limitations, the main one is that you cannot use the "include" statement in the middle of a map or list of subsections. Because of the "include" statement there, the parser cannot lookahead through that statement to see if the list is bding continued.
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.