throwing-macros 0.1.1

Create explicit errors easily with a handy macro
Documentation
use proc_macro2::Span;
use syn::{Ident, Path, Type};

pub fn type_to_variant(typ: &Type) -> Option<Ident> {
    match typ {
        Type::Path(path) => {
            if path.qself.is_none() {
                Some(path_to_variant(&path.path))
            } else {
                None
            }
        }
        Type::Paren(paren) => type_to_variant(&paren.elem),
        Type::Group(group) => type_to_variant(&group.elem),
        _ => None,
    }
}

fn path_to_variant(path: &Path) -> Ident {
    let mut name = String::new();

    for segment in &path.segments {
        snake_case_to_camel_case(&segment.ident, &mut name);
    }

    Ident::new(&name, Span::mixed_site())
}

pub fn fn_name_to_error(ident: &Ident) -> Ident {
    let mut name = String::new();
    snake_case_to_camel_case(ident, &mut name);
    name.push_str("Error");

    Ident::new(&name, Span::mixed_site())
}

pub fn snake_case_to_camel_case(ident: &Ident, name: &mut String) {
    let ident = ident.to_string();
    let segments = ident.split('_');

    for segment in segments {
        let mut chars = segment.chars();

        if let Some(c) = chars.next() {
            name.extend(c.to_uppercase());
        }

        name.extend(chars);
    }
}