synonym 0.1.6

Customizable derive macro to create newtypes. It peeks into the underlying type to choose which traits should be implemented.
Documentation
use crate::attrs::Attrs;
use crate::info::{Info, Kind};
use darling::FromDeriveInput;
use quote::ToTokens;
use syn::{Data, DeriveInput, Fields};

pub fn analyze(input: &DeriveInput) -> Option<Info> {
    if has_generics(input) {
        return None;
    }

    let mut info = Info {
        name: input.ident.clone(),
        kind: Kind::Other,
        typ: syn::Type::Never(syn::TypeNever {
            bang_token: syn::token::Not::default(),
        }),
        attrs: Attrs::from_derive_input(input).unwrap(),
    };

    match &input.data {
        Data::Struct(data) => match &data.fields {
            Fields::Unnamed(fields) => {
                if fields.unnamed.len() != 1 {
                    return None;
                }

                info.typ = fields.unnamed.first().unwrap().ty.clone();
                if let syn::Type::Group(g) = info.typ {
                    info.typ = *g.elem;
                }

                info.kind = match info
                    .typ
                    .to_token_stream()
                    .to_string()
                    .replace("std :: string :: ", "")
                    .replace("std :: num :: ", "")
                    .replace("std :: primitive :: ", "")
                    .replace("core :: primitive :: ", "")
                    .as_str()
                {
                    "u8" | "u16" | "u32" | "u64" | "u128" | "usize" | "i8" | "i16" | "i32"
                    | "i64" | "i128" | "isize" => Kind::Integer,
                    "NonZeroU8" | "NonZeroU16" | "NonZeroU32" | "NonZeroU64" | "NonZeroU128"
                    | "NonZeroUsize" | "NonZeroI8" | "NonZeroI16" | "NonZeroI32" | "NonZeroI64"
                    | "NonZeroI128" | "NonZeroIsize" => Kind::NonZeroInteger,
                    "f32" | "f64" => Kind::Float,
                    "String" => Kind::String,
                    "Box < str >" => Kind::BoxStr,
                    "& 'static str" => Kind::StaticStr,
                    "char" => Kind::Char,
                    _ => Kind::Other,
                };
            }
            _ => return None,
        },
        _ => return None,
    }

    Some(info)
}

fn has_generics(input: &DeriveInput) -> bool {
    input.generics.lt_token.is_some()
}