sml 0.1.43

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

[![Build Status](https://api.travis-ci.org/ericfindlay/SML.svg)](https://travis-ci.org/ericfindlay/SML)
[![](https://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT)
 
 `SML` is a simple markup language designed to convert human readable information into Rust
 types with a very specific purpose of 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. Key/value combinations are used for fields
 ```text
 name: "Frodo"
 ```
 are used for `struct` fields and `enum` variants. Keys only
 ```text
 hobbit:
     name: "Frodo"
 ```
 indicate a complete `struct` or `enum`. In this way, the data clearly indicates the mapping to
 Rust data structures.
 
 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.
 
 8. Empty lines or lines with whitespace only are ignored.
 
 ## Example. From `Small`-formatted string to your data-structure.

 This examples should cover 90 percent of use cases.
 
 ```rust
 use sml::{Small, FromSmall, SmallError};
 
 #[derive(Debug, Small)]
 struct Hobbit {
     name:    String,
     age:     u32,
     friends: Vec<Hobbit>,
     bicycle: Option<String>,
 }

 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: &Small) -> Result<Self, SmallError>
 ```
 The `from_small()` function describes how to create a data-structure from the parts of
 `Small`. See example 1 for canonical usage.

 ```rust
 path(small: &Small, key_path: &str) -> Result<Self, SmallError>
 ```
 Reduces `Small` 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.

 # Implementation

 A `Small` value may be a collection of `Small` values. For example,

 ```text
 hobbit:
     name: "Bilbo Baggins"
     age:  "176"
 hobbit:
     name: "Samwise Gamgee"
     age:  "66"
 ```
 is a collection of two elements
 ```text
 hobbit:
     name: "Bilbo Baggins"
     age:  "176"
 ```
 and 
 ```text
 hobbit:
     name: "Samwise Gamgee"
     age:  "66"
 ```
 Often when implementing `FromSmall` we want to convert a `Small` object into a single value, so
 we need to check that `Small` has only one element The implementation to convert from `Small`
 to `u32` gives indicates how to do this. `unique_value()` checks that there is only one element
 in `Small` and if so returns that one element and `value()` extracts that value as a `String`.

 ```rust
 impl FromSmall for u32 {
     fn from_small(s: &Small) -> Result<Self, SmallError> {
         let token = s.unique_value()?;
         token
             .value()?
             .parse::<u32>()
             .map_err(|_| SmallError::ParseValue(token, "u32"))
     }
 }
 ```