sml 0.1.12

Simple markup language.
Documentation

SML

SML is a simple markup language. It is designed to convert human readable information into Rust data-structures.

Note: The API is very far from stable. In fact everything is very far from stable. I'm working on the serialization side of things now (1st April 2019). Any version that is 0.1.x can be considered pretty much unusable.

The format looks this,

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

    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 may not include :.

  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.

Basic Organization

           ToSmall
           trait          to_string()
             --->           --->
-------------    -----------    ----------
| data-     |    |  Small  |    | String |
| structure |    |         |    |        |
-------------    -----------    ----------
             <---           <---
           FromSmall      from_str()
           trait

Example

To convert from Small to a data-structure,

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

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

impl Small for Hobbit {
    fn from_small(small: Small) -> Result<Self, SmallError> {
        Ok(Self {
            name:    String::sml(&small, "hobbit::name")?,
            age:     u32::sml(&small, "hobbit::age")?,
            friends: Vec::<Hobbit>::sml(&small, "hobbit::friends::hobbit")?,
            bicycle: Option::<String>::sml(&small, "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);
}

and to convert from a data-structure to Small,

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(key, &vec!(
            self.name.to_small("name")?,                
            self.age.to_small("age")?,                     
            self.friends.to_small("friends")?,   
            self.bicycle.to_small("bicycle")?,
        ))
    }
}

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

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