codgenhelp 0.0.1

Simplifies structure and enum parsing in Macros1.1
Documentation

use super::FromLiteral;
use super::syn::{
    Attribute,
    MetaItem,
    NestedMetaItem
};
use super::Lit;
macro_rules! is_thing {
    ($name:ident, $ma: pat) => {
        #[inline(always)]
        #[allow(dead_code)]
        pub fn $name(&self) -> bool {
            match self {
                $ma => true,
                _ => false
            }
        }
    }
}

/// For arguments within `#[derive ...]` tag
#[derive(Clone,Debug)]
pub enum HashTag {
    ///The name of a MetaItem.
    ///
    ///`#[test]` will return `MetaItem::Word("Test")`
    Word(String),
    /// A list of values
    ///
    ///`#[derive(Copy,Clone)]` will return
    ///`MetaItem::List("derive",vec![Box::new(MetaItem::Word("Copy")),Box::new(MetaItem::Word("Clone"))])`
    List(String,Vec<Box<HashTag>>),
    /// An assigned value
    ///
    /// `#[feature = "thing"]` will return `MetaItem::NameValue("feature", Literal::Str)`
    NameValue(String,Lit),
    /// A literal
    ///
    /// This isn't a _first level_ item. It can be encountered within
    /// `MetaItem::List(_, vec![])` part. It is included to prevent
    /// defining a whole extra type like `syn` does.
    Literal(Lit),
}

/// Take care of Nested Items
fn mapper( x: &NestedMetaItem) -> Box<HashTag> {
    let tag = match x {
        &NestedMetaItem::Literal(ref x) => HashTag::Literal(x.clone()),
        &NestedMetaItem::MetaItem(ref x) => HashTag::new(x),
    };
    Box::new(tag)
}

impl HashTag {
    /// Build a hashtag from a metatime
    pub fn new(x: &MetaItem) -> HashTag {
        match x {
            &MetaItem::Word(ref i) => HashTag::Word(i.to_string()),
            &MetaItem::List(ref i,ref arr) => {
                let mut v = Vec::with_capacity(arr.len());
                for item in arr {
                    v.push(mapper(&item));
                }
                HashTag::List(i.to_string(), v)
            },
            &MetaItem::NameValue(ref i, ref lit) => HashTag::NameValue(i.to_string(), lit.clone())
        }
    }
    /// Borrow Attribute value and parse
    pub fn complete(x: &[Attribute]) -> Vec<HashTag> {
        let mut v = Vec::with_capacity(x.len());
        for item in x {
            v.push(HashTag::new(&item.value));
        }
        v
    }
    is_thing!(is_word,&HashTag::Word(_));
    is_thing!(is_list,&HashTag::List(_,_));
    is_thing!(is_name_value,&HashTag::NameValue(_,_));
    is_thing!(is_literal,&HashTag::Word(_));
    /// Returns the name of the `#[...]` value
    ///
    /// The `literal` exists so this can technically fail
    /// to return some
    pub fn get_name<'a>(&'a self) -> Option<&'a str> {
        match self {
            &HashTag::Word(ref w) |
            &HashTag::List(ref w, _) |
            &HashTag::NameValue(ref w, _) => Some(w),
            _ => None
        }
    }
    /// Get Assignment
    ///
    /// When `#[hashtag = value]` is used
    /// this function will return the `value`
    /// half
    pub fn get_name_value<'a>(&'a self) -> Option<&'a Lit> {
        match self {
            &HashTag::NameValue(_, ref l) => Some(l),
            _ => None
        }
    }
    /// Get List
    ///
    /// Fetches the internal list if a hashtag
    /// like `#[derive(Clone,Copy)]` Which will
    /// return an array of the `[Clone,Copy]`
    pub fn get_arg_list<'a>(&'a self) -> Option<&'a [Box<HashTag>]> {
        match self {
            &HashTag::List(_,ref l) => Some(l),
            _ => None
        }
    }
    /// Get Literal
    ///
    /// If the hashtag has an associated literal be it
    /// `NameValue` or `Literal` this will return that
    /// value
    pub fn get_literal<'a>(&'a self) -> Option<&'a Lit> {
        match self {
            &HashTag::Literal(ref l) |
            &HashTag::NameValue(_, ref l) => Some(l),
            _ => None
        }
    }

    /// Get From Literal
///
/// Pre-Perform the conversion
pub fn from_literal(&self) -> Option<FromLiteral> {
    match self.get_literal() {
        Option::Some(x) => Some(FromLiteral::from(x)),
        _ => None
    }
}
}