sml 0.1.32

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.

2. All values must be double quoted.

3. Every key/value combination must be nested in a key. For example
```rust
    hobbit: "Frodo"
```
by itself is invalid. It can be written:
```rust
    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 1: 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);
}
```
## Example 2: From your data-structure to a Small-formatted string.

To convert from a data-structure to a string,

```rust
use sml::{Small, ToSmall, SmallError};

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

impl ToSmall for Hobbit {
    fn to_small(&self, key: &str) -> Result<Small, SmallError> {
        Small::join("hobbit", &vec!(
            self.name.to_small("name")?,                
            self.age.to_small("age")?,                     
            self.friends.to_small("friends")?,   
            self.bicycle.to_small("bicycle")?,
        ))
    }
}

println!("{}", frodo::key("hobbit"));

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

## Basic Organization

```text
  --------------------------from_str()----------------------------
  |                                                              |
  |  --------path()--------                                      |
  |  |                    |                                      |
  |  |   FromSmall trait  |                                      |
  |  |  --from_small()--  |  -----to_ref()----  --from_str()---  |
  |  |  |              |  |  |               |  |             |  |
  v  v  v              |  |  v               |  v             |  |
----------          ------------           ---------       ----------
| Hobbit |          | SmallRef |-ref into->| Small |       | String |
----------          ------------           ---------       ----------
      ^                                      ^  |             ^
      |                                      |  |             |
      ------------ to_small()-----------------  --to_string()--
                  ToSmall trait
```

## Functions on `Small`

```rust
join(key: &str, subs: &Vec<Small>) -> Result<Small, SmallError>
```

Returns a `Small` type given a key and a `Vec` of `Small`s. The `Vec` of `Small`s are
indented below the key. See example 2.

```rust
key_value(key: &str, value: String) -> Result<Small, SmallError>
```

Returns a `Small` type that consists of one key-value pair.

```rust
to_ref(&self) -> SmallRef
```

Converts `self` into a `SmallRef`. 

## `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.

## `ToSmall` Trait
The `ToSmall` trait is implemented for `String`s, `Vec<T>`, `Option<T>`, `bool` and all the
standard library integer and float types.

Required function:
```rust
fn to_small(&self, key: &str) -> Result<Small, SmallError>;
```
Converts a receiver that implements `ToSmall` into a `Small`-formatted string. `key` can be
overridden in the implementation, depending on whether you want to data-structure itself to
set the key name or whether you want to context of the `Small`-formatted string to set the
key name.