sml 0.1.46

Simple markup language optimized for loading config files and schemas.
Documentation
extern crate sml;

use sml::{KeyPath, Small, SmallString, FromSmall, SmallError};

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

impl FromSmall for Hobbit {
    fn from_small(s: &Small) -> 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")?,
        })
    }
}

#[test]
fn basic1() {
    let s = r#"
        hobbit:
            name:         "Frodo Baggins"
            age:          "98""#;
    let frodo = Hobbit::from_str_debug(s);
    assert_eq!(frodo.name, "Frodo Baggins");
}

#[test]
fn basic2() {
    let s = r#"
        hobbit:
            name:         "Frodo Baggins"
            age:          "98""#;
    let frodo = Hobbit::from_str_debug(s);
    assert_eq!(frodo.age, 98);
}

#[test]
fn basic3() {
    let s = r#"
        hobbit:
            name:         "Frodo Baggins"
            age:          "98""#;
    let frodo = Hobbit::from_str_debug(s);
    assert!(frodo.friends.is_empty());
}

#[test]
fn basic4() {
    let s = r#"
        hobbit:
            name:         "Frodo Baggins"
            age:          "98""#;
    let frodo = Hobbit::from_str_debug(s);
    assert_eq!(frodo.bicycle, None);
}

// SmallError tests.

#[test]
fn bool_parse_error() {
    // TODO
}

#[test]
fn empty_error() {
    assert!(
        match Hobbit::from_str("") {
            Err(SmallError::Empty) => true,
            _ => false,
        }
    );
    assert!(
        match Hobbit::from_str("  \n ") {
            Err(SmallError::Empty) => true,
            _ => false,
        }
    );
}

#[test]
fn empty_key_error() {
    // TODO
}

#[test]
// The 'name:' key is indented incorrectly.
fn indent1() {
    let s = r#"
        hobbit:
         name:         "Frodo Baggins"  
            age:          "98""#;
    assert!(
        match Hobbit::from_str(s) {
            Err(SmallError::Indent(_, 8)) => true,
            _ => false,
        }
    );

}


#[test]
fn float_parse_error() {
    // TODO
}

#[test]
fn is_key_error() {
    // TODO
}

#[test]
fn is_value_error() {
    // TODO
}

#[test]
fn parse_value_error() {
    let s = r#"
        hobbit:
            name: "Frodo Baggins"
            age:  "98.2""#;
    assert!(
        match Hobbit::from_str(s) {
            Err(SmallError::ParseValue(_,"u32")) => true,
            _ => false,
        }
    );
}

#[test]
fn key_parse1() {
    assert!(
        match KeyPath::from_str("") {
            Err(SmallError::KeyParse(_)) => true,
            _ => false,
        }
    );
}

fn key_parse2() {
    assert!(
        match KeyPath::from_str("a:b") {
            Err(SmallError::KeyParse(_)) => true,
            _ => false,
        }
    );
}

#[test]
fn no_colon_error1() {
    let s = r#"
        hobbit 
            name: "Frodo Baggins"  
            age:  "98""#;
    assert!(
        match Hobbit::from_str(s) {
            Err(SmallError::NoColon(_, _)) => true,
            _ => false,
        }
    );
}
#[test]
fn no_colon_error2() {
    let s = r#"
        hobbit: 
            name  "Frodo Baggins"  
            age:  "98""#;
    assert!(
        match Hobbit::from_str(s) {
            Err(SmallError::NoColon(_, _)) => true,
            _ => false,
        }
    );
}

#[test]
fn not_unique_error() {
    // TODO
}

#[test]
fn no_quote_after_key_error() {
    // TODO
}

#[test]
fn no_second_quote() {
    let s = r#"
        hobbit:
            name: "Frodo Baggins  
            age:  "98""#;
    assert!(
        match Hobbit::from_str(s) {
            Err(SmallError::NoSecondQuote(_, _)) => true,
            _ => false,
        }
    );
}

#[test]
fn no_space_after_key() {
    let s = r#"
        hobbit:
            name:"Frodo Baggins"  
            age: "98""#;
    assert!(
        match Hobbit::from_str(s) {
            Err(SmallError::NoSpaceAfterKey(_)) => true,
            _ => false,
        }
    );
}

// The 'name:' key has the same indentation as `hobbit:'. The parser reads this as the start of a
// new object, as so the parser can't figure out the rest of Hobbit.
#[test]
fn missing_token_error() {
    let s = r#"
        hobbit:
        name:    "Frodo Baggins"  
            age: "98""#;
    assert!(
        match Hobbit::from_str(s) {
            Err(SmallError::MissingToken) => true,
            _ => false,
        }
    );
}

#[test]
fn path1() {
    let s = r#"
        hobbit:
            name:         "Frodo Baggins"
            age:          "98"
            friends:
                hobbit:
                    name: "Bilbo Baggins"
                    age:  "176"
                hobbit:
                    name: "Samwise Gamgee"
                    age:  "66""#;
    let small = SmallString::from_str(s).unwrap();
    assert_eq!(String::path(&small.to_ref(), "hobbit::name").unwrap(), "Frodo Baggins");
}

#[test]
fn path_not_unique() {
    let s = r#"
        hobbit:
            name:         "Frodo Baggins"
            age:          "98"
            friends:
                hobbit:
                    name: "Bilbo Baggins"
                    age:  "176"
                hobbit:
                    name: "Samwise Gamgee"
                    age:  "66""#;
    let small = SmallString::from_str(s).unwrap();
    assert!(
        match String::path(&small.to_ref(), "hobbit::friends::hobbit") {
            Err(SmallError::NotUnique(2)) => true,
            _ => false,
        }
    );
}

#[test]
fn path_is_key() {
    let s = r#"
        hobbit:
            name:         "Frodo Baggins"
            age:          "98"
            friends:
                hobbit:
                    name: "Bilbo Baggins"
                    age:  "176"
                hobbit:
                    name: "Samwise Gamgee"
                    age:  "66""#;
    let small = SmallString::from_str(s).unwrap();
    assert!(
        match String::path(&small.to_ref(), "hobbit::friends") {
            Err(SmallError::IsKey(_)) => true,
            _ => false,
        }
    );
}

#[test]
fn path_vec_string() {
    let s = r#"
        hobbit:
            name:         "Frodo Baggins"
            age:          "98"
            friends:
                hobbit:
                    name: "Bilbo Baggins"
                    age:  "176"
                hobbit:
                    name: "Samwise Gamgee"
                    age:  "66""#;
    let small = SmallString::from_str(s).unwrap();
    assert_eq!(
        Vec::<String>::path(&small.to_ref(), "hobbit::friends::hobbit::name").unwrap()[0],
        "Bilbo Baggins"
    );
    assert_eq!(
        Vec::<String>::path(&small.to_ref(), "hobbit::friends::hobbit::name").unwrap()[1],
        "Samwise Gamgee"
    );
}