[][src]Crate sml

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

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

    hobbit: "Frodo"

by itself is invalid. It can be written:

    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.

  1. Separation of lines has meaning.

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

  3. Double quotes in values must be escaped using \".

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

  5. 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.

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,

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

  --------------------------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

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

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

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

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

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:

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.

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.

from_str(s: &str) -> Result<Self, SmallError>

Top level function that convert a Small-formatted string into the receiver.

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 Strings, Vec<T>, Option<T>, bool and all the standard library integer and float types.

Required function:

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.

Structs

KeyPath
Small

Small represents a string in Small data format.

SmallRef

SmallRef is a selection of Small. Its function is to encapsulate path selections. See the path() function implemented by the FromSmall trait.

Token

The Token struct contains implementation details of a parsed line a Small-formatted string. It is not really part of the API, but gets passed around by SmallError and as such is public.

Enums

SmallError

Traits

FromSmall

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

ToSmall

Types that implement the ToSmall trait can be converted to the Small.