sml 0.1.38

Simple markup language optimized for loading config files and schemas.
Documentation
# SML

`SML` is a simple markup language designed to convert human readable information into Rust
types, focusing on simplicity, usability and hands-on control. Its optimal usage is in loading
config files and schemas.

The format looks like

```text
hobbit:
    name:         "Frodo Baggins"
    age:          "98"
    friends:
        hobbit:
            name: "Bilbo Baggins"
            age:  "176"
        hobbit:
            name: "Samwise Gamgee"
            age:  "66"
```

## Data Format Rules

1. Indentation has meaning and is 4 spaces, relative to the top key. If indenting is relative
   to the top key, then you can neatly align strings embedded in code.

2. All values must be double quoted.

3. Every key/value combination must be nested in a key. For example
```text
    hobbit: "Frodo"
```
by itself is invalid. It can be written:
```text
    hobbit:
        name: "Frodo"
```
The motivation behind this is for the data format to distinguish clearly
between whole data structures, which are headed by a key only, and parts of a
data structure which are either key/value pairs, representing fields or
variants, or other data-structures, which again are headed by a key only.

4. Separation of lines has meaning.

5. Keys must not include but must be followed by a colon `:`.

6. Double quotes in values must be escaped using `\"`.

7. Everything after the second double quote is ignored (and can be used for commenting).

8. Empty lines or lines with whitespace only are ignored.

## Example. From `Small`-formatted string to your data-structure.

The following two examples should cover 90 percent of use cases.
data-structure.

```rust
use small::{Small, FromSmall, SmallError};

#[derive(Debug)]
struct Hobbit {
    name:    String,
    age:     u32,
    friends: Vec<Hobbit>,
    bicycle: Option<String>,
}

impl FromSmall for Hobbit {
    fn from_small(s: &SmallRef) -> Result<Self, SmallError> {
        Ok(Self {
            name:    String::path(&s, "hobbit::name")?,
            age:     u32::path(&s, "hobbit::age")?,
            friends: Vec::<Hobbit>::path(&s, "hobbit::friends::hobbit")?,
            bicycle: Option::<String>::path(&s, "hobbit::bicycle")?,
        })
    }
}

fn main() {
    let s = r#"
        hobbit:
            name:         "Frodo Baggins"
            age:          "98"
            friends:
                hobbit:
                    name: "Bilbo Baggins"
                    age:  "176"
                hobbit:
                    name: "Samwise Gamgee"
                    age:  "66""#;
    
    let frodo = Hobbit::from_str_debug(s);
}
```

## `FromSmall` Trait
Types that implement the `FromSmall` trait can be constructed from a `Small`-formatted string.

Required function:
```rust
from_small(slice: &SmallRef) -> Result<Self, SmallError>
```
The `from_small()` function describes how to create a data-structure from the parts of
`SmallRef`. See example 1 for canonical usage.

```rust
path(small: &SmallRef, key_path: &str) -> Result<Self, SmallError>
```
Reduces `SmallRef` to the `key_path` and then uses the `FromSmall` trait to convert to the
receiver type.

```rust
from_str(s: &str) -> Result<Self, SmallError>
```
Top level function that convert a `Small`-formatted string into the receiver.

```rust
from_str_debug(s: &str) -> Self
```
Top level function that converts a `Small`-formatted string into the receiver giving helpful
error messages for debugging.