traitlit 0.2.0

This crate exposes an atribute for implementing traits for integer and float types.
Documentation
use syn::Attribute;
use syn::Type;
use syn::TypePath;
use syn::Ident;
use syn::parse::{ self, Parse, ParseStream };
use syn::punctuated::Punctuated;
use syn::Token;
use syn::bracketed;
use syn::token::Bracket;
use syn::punctuated::IntoIter;
use std::slice::Iter;
use proc_macro2::Span;

pub struct WithAttr<T>(pub Vec<Attribute>, pub T);

impl<T: Parse> Parse for WithAttr<T> {
    fn parse(input: ParseStream) -> parse::Result<Self> {
        Ok(WithAttr(input.call(Attribute::parse_outer)?, input.parse()?))
    }
}

enum LitSet {
    Named(Ident),
    Set(Bracket, Punctuated<WithAttr<Type>, Token!(,)>)
}

impl Parse for LitSet {
    fn parse(input: ParseStream) -> parse::Result<Self> {
        if input.peek(Ident) {
            input.parse().map(LitSet::Named)
        } else {
            let content;
            Ok(LitSet::Set(bracketed!(content in input), Punctuated::parse_terminated(&content)?))
        }
    }
}

impl IntoIterator for WithAttr<LitSet> {
    type Item = WithAttr<Type>;
    type IntoIter = SetIterator;
    fn into_iter(self) -> SetIterator {
        match self {
            WithAttr(attrs, LitSet::Named(ident)) => {
                if ident == "u_" {
                    SetIterator::Named(attrs, ident.span(), UINT.iter())
                } else if ident == "i_" {
                    SetIterator::Named(attrs, ident.span(), INT.iter())
                } else if ident == "f_" {
                    SetIterator::Named(attrs, ident.span(), FLOAT.iter())
                } else {
                    ident.span().unwrap().error("Unknown type set").emit();
                    SetIterator::Set(attrs, Punctuated::new().into_iter())
                }
            },
            WithAttr(attrs, LitSet::Set(_, types)) => SetIterator::Set(attrs, types.into_iter()),
        }
    }
}

const UINT: [&'static str; 6] = ["u8", "u16", "u32", "u64", "u128", "usize"];
const INT: [&'static str; 6] = ["i8", "i16", "i32", "i64", "i128", "isize"];
const FLOAT: [&'static str; 2] = ["f32", "f64"];

enum SetIterator {
    Named(Vec<Attribute>, Span, Iter<'static, &'static str>),
    Set(Vec<Attribute>, IntoIter<WithAttr<Type>, Token!(,)>),
}

impl Iterator for SetIterator {
    type Item = WithAttr<Type>;
    fn next(&mut self) -> Option<Self::Item> {
        match self {
            SetIterator::Set(attrs, types) => types.next().map(|WithAttr(a, t)|WithAttr({let mut attrs = attrs.clone(); attrs.extend(a); attrs}, t)),
            SetIterator::Named(attrs, span, iter) => iter.next().map(|n|WithAttr(attrs.clone(), Type::Path(TypePath { qself: None, path: Ident::new(n, *span).into() }))),
        }
    }
}

pub struct Args {
    pub ident: Ident,
    _equal: Token!(=),
    pub types: Vec<WithAttr<Type>>,
}

impl Parse for Args {
    fn parse(input: ParseStream) -> parse::Result<Self> {
        Ok(Args {
            ident: input.parse()?,
            _equal: input.parse()?,
            types: Punctuated::<WithAttr<LitSet>, Token!(+)>::parse_separated_nonempty(input)?.into_iter().flatten().collect()
        })
    }
}