trace2_macro 0.1.0

The real proc macro implementation of trace2
use syn;

#[derive(Debug)]
pub struct Config {
    pub ignore: bool,
}

impl Config {
    fn from_raw_pairs(pairs: Vec<RawConfigPair>) -> Config {
        let mut config = Config::default();
        for pair in pairs {
            match pair.name.to_string().as_str() {
                "ignore" => {
                    assert!(pair.value.is_none());
                    config.ignore = true;
                }
                _ => panic!("Unexpected configuration: {}", pair.name),
            }
        }
        config
    }
}

impl syn::synom::Synom for Config {
    fn parse(cursor: syn::buffer::Cursor) -> syn::synom::PResult<Self> {
        let result =
            syn::punctuated::Punctuated::<RawConfigPair, Token![,]>::parse_terminated(cursor);
        result.map(|(pairs, cursor)| (Config::from_raw_pairs(pairs.into_iter().collect()), cursor))
    }
}

impl Default for Config {
    fn default() -> Self {
        Config { ignore: false }
    }
}

#[derive(Debug)]
struct RawConfigPair {
    name: syn::Ident,
    value: Option<syn::Lit>,
}

impl syn::synom::Synom for RawConfigPair {
    named!(parse -> Self, do_parse!(
        name: syn!(syn::Ident) >>
        value: option!(
            do_parse!(
                punct!(=) >>
                v: syn!(syn::Lit) >>
                (v)
            )
        ) >>
        (RawConfigPair {
            name,
            value,
        })
    ));
}

#[cfg(test)]
mod test {
    use super::{Config, RawConfigPair};

    use syn;

    #[test]
    fn parse_raw_config() {
        let pair = syn::parse_str::<RawConfigPair>("ignore").unwrap();
        assert_eq!(pair.name, "ignore");
        assert_eq!(pair.value, None);

        let pair = syn::parse_str::<RawConfigPair>("foo = \"bar\"").unwrap();
        assert_eq!(pair.name, "foo");
        let value = pair.value.unwrap();
        assert_eq!(quote!(#value).to_string(), "\"bar\"");

        let pair = syn::parse_str::<RawConfigPair>("boz = 123").unwrap();
        assert_eq!(pair.name, "boz");
        let value = pair.value.unwrap();
        assert_eq!(quote!(#value).to_string(), "123");
    }

    #[test]
    fn parse_config() {
        let config = syn::parse_str::<Config>("ignore").unwrap();
        assert_eq!(config.ignore, true);

        let config = syn::parse_str::<Config>("").unwrap();
        assert_eq!(config.ignore, false);
    }
}