gray_matter 0.3.2

Smart front matter parser. An implementation of gray-matter in rust. Parses YAML, JSON, TOML and support for custom parsers.
Documentation
use crate::engine::Engine;
use crate::Pod;
use crate::{Error, Result};
use std::collections::HashMap;
use yaml::{Yaml, YamlLoader};

/// [`Engine`](crate::engine::Engine) for the [YAML](https://yaml.org) configuration format.
pub struct YAML;

impl Engine for YAML {
    fn parse(content: &str) -> Result<Pod> {
        match YamlLoader::load_from_str(content) {
            Ok(docs) => {
                let mut doc = Pod::Null;
                if !docs.is_empty() {
                    doc = docs[0].clone().into();
                }
                Ok(doc)
            }
            Err(e) => Err(Error::deserialize_error(&format!("{}", e))),
        }
    }
}

impl Into<Pod> for Yaml {
    fn into(self) -> Pod {
        match self {
            Yaml::Real(val) => Pod::Float(val.parse().unwrap_or(0 as f64)),
            Yaml::Integer(val) => Pod::Integer(val),
            Yaml::String(val) => Pod::String(val),
            Yaml::Boolean(val) => Pod::Boolean(val),
            Yaml::Array(val) => val
                .iter()
                .map(|elem| elem.into())
                .collect::<Vec<Pod>>()
                .into(),
            Yaml::Hash(val) => val
                .iter()
                .filter_map(|(key, elem)| {
                    let key = match key {
                        Yaml::String(s) | Yaml::Real(s) => s.to_string(),
                        Yaml::Boolean(b) => b.to_string(),
                        Yaml::Integer(i) => i.to_string(),
                        Yaml::Null => "null".to_string(),
                        // Other types should not be expressible as keys.
                        _ => return None,
                    };

                    Some((key, elem.into()))
                })
                .collect::<HashMap<String, Pod>>()
                .into(),
            Yaml::Null => Pod::Null,
            _ => Pod::Null,
        }
    }
}

impl From<&Yaml> for Pod {
    fn from(val: &Yaml) -> Self {
        val.to_owned().into()
    }
}

#[cfg(test)]
mod test {
    use crate::engine::YAML;
    use crate::Matter;
    use crate::ParsedEntity;
    use crate::Result;
    use serde::Deserialize;

    #[test]
    fn test_matter() -> Result<()> {
        let matter: Matter<YAML> = Matter::new();
        let input = r#"---
one: foo
two: bar
three: baz
---"#;
        #[derive(Deserialize, PartialEq, Debug)]
        struct FrontMatter {
            one: String,
            two: String,
            three: String,
        }
        let data_expected = FrontMatter {
            one: "foo".to_string(),
            two: "bar".to_string(),
            three: "baz".to_string(),
        };
        let result: ParsedEntity<FrontMatter> = matter.parse(input)?;
        assert_eq!(result.data, Some(data_expected));
        Ok(())
    }

    #[test]
    fn non_string_keys() -> Result<()> {
        let matter: Matter<YAML> = Matter::new();
        let input = r#"---
1: foo
true: bar
three: baz
null: boo
---"#;
        #[derive(Deserialize, PartialEq, Debug)]
        struct FrontMatter {
            #[serde(rename = "1")]
            one: String,
            #[serde(rename = "true")]
            two: String,
            three: String,
            null: String,
        }
        let data_expected = FrontMatter {
            one: "foo".to_string(),
            two: "bar".to_string(),
            three: "baz".to_string(),
            null: "boo".to_string(),
        };
        let result: ParsedEntity<FrontMatter> = matter.parse(input)?;
        assert_eq!(result.data, Some(data_expected));
        Ok(())
    }
}