auto_enums_core 0.1.2

This library provides an attribute macro for to allow multiple return types by automatically generated enum.
Documentation
use proc_macro2::{Ident, Span};
use smallvec::SmallVec;
use syn::{Attribute, Block, Expr, ExprBlock, ExprCall, ExprPath, Path, PathSegment, Stmt};

#[macro_use]
mod error;

pub(crate) use self::error::*;

pub(crate) type Stack<T> = SmallVec<[T; 8]>;

pub(crate) fn default<T: Default>() -> T {
    T::default()
}

pub(crate) trait VecExt<T> {
    fn find_remove<P>(&mut self, predicate: P) -> Option<T>
    where
        P: FnMut(&T) -> bool;
}

impl<T> VecExt<T> for Vec<T> {
    fn find_remove<P>(&mut self, predicate: P) -> Option<T>
    where
        P: FnMut(&T) -> bool,
    {
        fn remove<T>(v: &mut Vec<T>, index: usize) -> T {
            match v.len() {
                1 => v.pop().unwrap(),
                2 => v.swap_remove(index),
                _ => v.remove(index),
            }
        }

        self.iter().position(predicate).map(|i| remove(self, i))
    }
}

pub(crate) fn ident_call_site<S: AsRef<str>>(s: S) -> Ident {
    Ident::new(s.as_ref(), Span::call_site())
}

pub(crate) fn path<I: Iterator<Item = PathSegment>>(segments: I) -> Path {
    Path {
        leading_colon: None,
        segments: segments.collect(),
    }
}

pub(crate) fn block(stmts: Vec<Stmt>) -> Block {
    Block {
        brace_token: default(),
        stmts,
    }
}

pub(crate) fn expr_block(block: Block) -> Expr {
    Expr::Block(ExprBlock {
        attrs: Vec::with_capacity(0),
        label: None,
        block,
    })
}

pub(crate) fn expr_call(attrs: Vec<Attribute>, path: Path, args: Expr) -> Expr {
    Expr::Call(ExprCall {
        attrs,
        func: Box::new(Expr::Path(ExprPath {
            attrs: Vec::with_capacity(0),
            qself: None,
            path,
        })),
        paren_token: default(),
        args: Some(args).into_iter().collect(),
    })
}