1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! Macrohelper
//!
//! This crate's goal of this crate is to make you not want to tear your hair out when working with
//! `syn` crate for Macro's1.1
//!
//! Some core enums from `syn` are re-exported that represent core types

#![feature(proc_macro, proc_macro_lib)]
extern crate proc_macro;
pub use proc_macro::TokenStream;

extern crate syn;
#[allow(unused_imports)]
pub use syn::{
    Lit,
    StrStyle,
    IntTy,
    FloatTy,
    Ty,
    Lifetime,
    ConstExpr
};
pub mod meta;
#[allow(unused_imports)]
pub use meta::HashTag;
pub mod bodykind;
#[allow(unused_imports)]
use bodykind::{
    BodyKind,
    Enumerator,
    Variant,
    Field,
    Fields,
    Structure
};

macro_rules! is_thing {
    ($name:ident, $ma: pat) => {
        #[inline(always)]
        #[allow(dead_code)]
        pub fn $name(&self) -> bool {
            match self {
                $ma => true,
                _ => false
            }
        }
    }
}

/// Input to a macro1.1 invocation
///
/// Macro1.1 compiler hook gives a string of tokens. That is converted to an AST by `syn`.
/// This crate then converts `syn`'s output into this type.
#[derive(Clone,Debug)]
#[allow(dead_code)]
pub struct MacroInput {
    /// Information about any and all `#[...]` headers
    pub attr: Vec<HashTag>,
    /// Name of the structure or enum
    pub id: String,
    /// Informatin about the body
    pub body: BodyKind
}
impl MacroInput {
    /// High level fake implemenation.
    ///
    /// Just converts `TokenStream` to a string, and called `from_str`
    pub fn from_tree(input: TokenStream) -> Result<MacroInput,String> {
        let s = input.to_string();
        MacroInput::from_str(&s)
    }
    /// Actual implementation of the conversion
    #[inline]
    pub fn from_str(s: &str) -> Result<MacroInput,String> {
        use std::mem;

        //parse the input
        let ast = syn::parse_macro_input(s)?;

        //build the return value
        let mut ret_val: MacroInput = unsafe{ mem::uninitialized() };
        ret_val.id = ast.ident.to_string();
        ret_val.attr = HashTag::complete( &ast.attrs);

        //return value
        Ok(ret_val)
    }
}
/// Derive traits for tests
///
/// Even tho `syn` has `PartialEq` and `Eq` derived for most types I'm getting massive
///
#[derive(Clone,Debug,PartialEq,Eq)]
pub enum FromLiteral {
    Str(String),
    ByteStr(Vec<u8>),
    Byte(u8),
    Int(u64),
    Float(String),
    Bool(bool),
    Char(char)
}
impl From<Lit> for FromLiteral {
    fn from(x: Lit) -> FromLiteral {
        match x {
            Lit::Str(w,_) => FromLiteral::Str(w),
            Lit::ByteStr(w,_) => FromLiteral::ByteStr(w),
            Lit::Byte(w) => FromLiteral::Byte(w),
            Lit::Int(w,_) => FromLiteral::Int(w),
            Lit::Char(w) => FromLiteral::Char(w),
            Lit::Bool(w) => FromLiteral::Bool(w),
            Lit::Float(w,_) => FromLiteral::Float(w)
        }
    }
}
impl<'a> From<&'a Lit> for FromLiteral {
    fn from(x: &'a Lit) -> FromLiteral {
        match x {
            &Lit::Str(ref w,_) => FromLiteral::Str(w.clone()),
            &Lit::ByteStr(ref w,_) => FromLiteral::ByteStr(w.clone()),
            &Lit::Byte(ref w) => FromLiteral::Byte(w.clone()),
            &Lit::Int(ref w,_) => FromLiteral::Int(w.clone()),
            &Lit::Char(ref w) => FromLiteral::Char(w.clone()),
            &Lit::Bool(ref w) => FromLiteral::Bool(w.clone()),
            &Lit::Float(ref w,_) => FromLiteral::Float(w.clone())
        }
    }
}
impl FromLiteral {
    is_thing!(is_str,&FromLiteral::Str(_));
    is_thing!(is_bytestr,&FromLiteral::ByteStr(_));
    is_thing!(is_byte,&FromLiteral::Byte(_));
    is_thing!(is_int,&FromLiteral::Int(_));
    is_thing!(is_float,&FromLiteral::Float(_));
    is_thing!(is_bool,&FromLiteral::Bool(_));
    is_thing!(is_char,&FromLiteral::Char(_));
}