A config language for humans that is not self-describing.
Simple Config isn't specific to Rust or serde but the only known implementation uses both.
Simple config is based on the concept that you don't need to be able to form the schema from the config file. This is already common but in a more adhoc form, for example you may use a JSON string to hold a date such as "1990-02-14"
. Simple Config takes advantage of this to provide richer types and less escaping. For example a multi-line string requires no additional markup, the schema says it is a string so it won't try to parse it as a dict. Similarly you won't have type errors because false
or no
got parsed as a bool, and you don't have to worry about quoting strings that start with numbers.
This is a small example that shows both the schema (as Rust code) and the config (as a string literal). For a full explanation see below.
```rust
enum Country { CA, US, NO, }
enum Contact {
Email(String),
Matrix(String),
Phone{
number: u64,
#[serde(default)]
extension: Option
struct Contestant {
contact: Vec
#[serde(with = "humantime_serde")]
personal_best: std::time::Duration,
#[serde(with = "humantime_serde")]
last_seen: std::time::SystemTime,
}
let t: std::collections::BTreeMap
kevincox: contact: : email: kevincox@kevincox.ca
:
phone:
number: 18005551234
country: CA
personal-best: 1h 13min
last-seen: 2021-06-08 00:00:00Z
sarah: contact: : matrix: @me:matrix.example country: NO personal-best: 73min last-seen: 2019-06-30 07:24:30Z
").unwrap();
asserteq!(t, std::array::IntoIter::new([ ("kevincox".toowned(), Contestant { contact: vec![ Contact::Email("kevincox@kevincox.ca".into()), Contact::Phone{number: 18005551234, extension: None}, ], country: Country::CA, personalbest: std::time::Duration::fromsecs(13600 + 1360), lastseen: std::time::UNIXEPOCH + std::time::Duration::fromsecs(1623110400), }), ("sarah".toowned(), Contestant { contact: vec![ Contact::Matrix("@me:matrix.example".into()), ], country: Country::NO, personalbest: std::time::Duration::fromsecs(73*60), lastseen: std::time::UNIXEPOCH + std::time::Duration::from_secs(1561879470), }), ]).collect()); ```
For more examples see the examples directory. Note that some of the examples in this directory re-implementations of existing data structures and may contain hacks to work well with the previous config language, leading to suboptimal presentation in Simple Config.
yaml
key: value
Dictionaries are a mapping from a key to a value. The key is always a single-line value that doesn't contain a colon followed by a colon, however the exact parsing is dependent on the type.
```yaml
true: boolean key 123: integer key hello: string key ```
Values are arbitrary types. There are two ways to specify a value. How these values are parsed depends on the type.
yaml
key: inline value
key:
multi
line
value
For full reference on parsing see the docs for the type of the value.
Dictionaries can be nested, when nested the value must be specified as a mutli-line value.
yaml
vehicle:
type: Car
engine:
capacity_cc: 200
mass_g: 60k
wheels:
diameter_m: 550m
Lists contain multiple values. Depending on the schema the order may or may not be important.
yaml
strings:
string one
string two
string three
numbers:
1
1k
1M
By default list items are a single line long. To put a multi-line item in a list you must use the :
character to open a new level of indent. Single and multi-line items can be mixed. Note that Dictionaries must be multi-line.
yaml
strings:
single line string
:
multi
line
string
another single line string
dicts:
:
species: Cat
cuteness: 0.99
:
species: Dog
cuteness: 0.8
Strings can be single-line or multi-line. Currently no escaping is allowed or necessary, strings end at a newline or comment (#
) whichever comes first. However single-line strings starting with a double quote "
are reserved for future escaping capabilities. Mutli-line strings have the leading indentation stripped. Note that there are no special characters in a multi-line string, including comments. If you want to put a comment in a multi-line string you will need to use the destination comment format.
yaml
inline: a string # This comment is not part of the string.
out-of-line:
a string
multi-line: # This comment is not part of the string.
this
is
a
string
no-comments:
# This comment is a part of the string.
Warning: There is currently no way to specify a string where the first line is indented.
```yaml
doesnt-work: indented first line non-indented line ```
Numbers can be specified as you would expect. Additionally many suffixes are supported for scaling the numbers. It is an error to have an integer that is out-of-range for the associated type. Floating point values will be the nearest representable value.
```yaml simple-int: 123 simple-float: 3.14
base2: 0b01001011 base8: 0o664 base16: 0xCC
exponents: 6.022e1023 # 6.022 ⨉ 10^1023 2.5e-11 # 2.5 ⨉ 10^-11
si-suffixes: 1E 1P 1T 1G 1M 1k # K is also accepted for consistency. 1m 1u 1µ 1n 1p 1f 1a
iec-sufixes: 1Ei 1Pi 1Ti 1Gi 1Mi 1ki # Ki is also accepted for consistency. 1mi 1ui 1µi 1ni 1pi 1fi 1ai ```
Booleans are specified as true
or false
.
Bytes are currently unsupported. https://gitlab.com/kevincox/simple-config-rs/-/issues/1
An optional value can be specified as an empty value value.
Note: It is currently impossible to specify an empty string for Option<String>
, it is always assumed to mean None.
yaml
maybe_none:
maybe_some: 17
Comments start with a #
and extend to the end of the line. Comments can be placed in most places. However note that comments can't be placed in multi-line strings (they are considered part of the string).
```yaml
a-number: # comment 5 another-number: 5 # comment
a-string: # comment hi multi-line-string: # comment hi # NOT COMMENT # NOT COMMENT
list: # comment 1 # comment # comment 2
```