# KeyTree
[](http://opensource.org/licenses/MIT)
`KeyTree` is an elegant markup language designed to convert human readable information into Rust
data-structures. It is designed to be fast, to reduce cognitive load and to be easy to
implement for one's own types. It has no dependencies on other crates and so is fast to
compile. The format looks like
```text
hobbit:
name: Frodo Baggins
age: 60
friends:
hobbit:
name: Bilbo Baggins
age: 111
hobbit:
name: Samwise Gamgee
age: 38
```
so data can be recursive. Also, it is easy to refer to a set of data using a path such as
`hobbit::friends::hobbit` refers to a collection of two hobbits.
This library does not follow the standard Rust error handling pattern. If there is a parsing
error it will crash or if there is an error in converting a value into a Rust type it will
crash (with a nice error message). If you don't want this to happen, you will need to run this
in its own thread/process.
## Data Format Rules
- Indentation has meaning and is 4 spaces, relative to the top key. Since indenting is
relative to the top key, then you can neatly align strings embedded in code.
- Each line can be empty, have whitespace only, be a comment, be a key, or be a key/value
pair.
- There are keys and values. Key/Value pairs look like
```text
name: Frodo
```
are used for `struct` fields and `enum` variants.
Keys refer to child keys or child key/value pairs indented on lines under it, for example
```text
hobbit:
name: Frodo
```
hobbit refers to the name of the struct or enum. In this way, the data maps simply to Rust
data-structures.
- If a key has many children with the same key, it forms a collection, for example
```test
hobbit:
name: Frodo
name: Bilbo
```
is a collection of hobbits.
- Keys must not include but must be followed by a colon `:`.
- Values are all characters between the combination of ':' and whitespace and the end of the
line. The value is trimmed of whitespace at both ends.
- Comments require `//` at the start of the line. For example
```text
// comment
hobbit:
name: Frodo
```
## Example
`Into` from `KeyTree` into Rust types is automatically implemented for `Vec<T>`, `Option<T>`
and basic Rust types. `KeyTree` text can be automatically converted to these data types, making
use of type inference. The `at()` function returns an iterator over `KeyTree` types that can be
used to implement `Into` for your own types. The following example should cover 90 percent of
use cases,
```rust
use keytree::KeyTree;
use keytree::parser::KeyTreeBuilder;
#[derive(Debug)]
struct Hobbit {
name: String,
age: u32,
friends: Vec<Hobbit>,
nick: Option<String>,
}
impl<'a> Into<Hobbit> for KeyTree<'a> {
fn into(self) -> Hobbit {
Hobbit {
name: self.at("hobbit::name"),
age: self.at("hobbit::age"),
friends: self.at("hobbit::friends::hobbit"),
nick: self.op("hobbit::nick"),
}
}
}
fn main() {
let s = r#"
hobbit:
name: Frodo Baggins
age: 98
friends:
hobbit:
name: Bilbo Baggins
age: 176
hobbit:
name: Samwise Gamgee
age: 66
nick: Sam"#;
let core = KeyTreeBuilder::parse(s);
let hobbit: Hobbit = KeyTree::from_core(&core).into();
dbg!(&hobbit);
}
```
## Details
We'll have a look in detail at what is happening in the example on the line
```
friends: self.at("hobbit::friends::hobbit"),
```
In the `Into` trait impl, we want Bilbo Baggins and Samwise Gamgee to be Frodo's
friends. We specify their location in the `KeyTree` string using a path
`"hobbit::friends::hobbit"` which refers to two branches in the tree (two
hobbits). The `at()` function, unlike the the `op()` function, requires that the
branches exist. Rust infers that they need to be converted into the type `Vec<Hobbit>` as
specified in the `Hobbit` struct. The `Vec<T>` impl of `Into` is supplied by `KeyTree`. In fact
the `at()` function supplies an iterator over the Hobbits, which the `Vec<T>` impl uses.