# curlyconf
[](https://www.apache.org/licenses/LICENSE-2.0.txt)
[](http://opensource.org/licenses/MIT)
[](https://crates.io/crates/curlyconf)
[](https://docs.rs/curlyconf)
### Curlyconf
Curlyconf is a configuration file reader for the configuration
file format used by, for example, named.conf and dhcpd.conf.
### Example config (file.cfg)
```
person charlie {
fullname "Charlie Brown";
address 192.168.1.1;
}
person snoopy {
fullname "Snoopy";
}
```
### Example code
```rust
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);
}
}
```
### This will print:
```
0: charlie fullname Some("Charlie Brown") addr Some(V4(192.168.1.1))
1: snoopy fullname Some("Snoopy") addr None
```
Curlyconf uses [serde](https://crates.io/crates/serde) to deserialize the
configuration file values to rust types, just like almost every other
crate that does something similar.
### Sections and values.
The configuration file contains section names, labels, sections, value names, and values:
- **sections**. they have a section\_name, an optional label, and contain
a list of other sections and values. The rust type of a section is a struct.
- **values**. this is a value\_name, followed by a value. If the value is a `Vec`,
there can be multiple values, separated by a comma.
A section can only have a label if:
- it is part of a `HashMap<Key, Section>`, or
- it is part of a `Vec<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:
```rust
#[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;
}
```
### Includes.
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.
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
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.