diesel-crud-codegen 0.0.2

diesel-crud-codegen
Documentation
use std::borrow::Cow;
use std::collections::HashMap;

use syn::{Attribute, GenericArgument, PathArguments, Type};

pub fn get_diesel_type_name(ty: &Type) -> &'static str {
    match get_type_name(&ty).as_str() {
        "bool" => "Bool",
        "i32" => "Integer",
        "String" => "Text",
        "DateTime" | "UtcDateTime" => "Timestamptz",
        "LocaleDate" | "UtcDate" => "Date",
        "f64" => "Double",
        "f32" => "Float",
        "i64" => "BigInt",
        others => panic!("unsupported field type: {}, please add type support in derives", &others),
    }
}

pub fn get_struct_attributes(attrs: &Vec<Attribute>) -> HashMap<String, Option<String>> {
    attrs
        .iter()
        .map(|attr| {
            let name = attr.path.segments.iter().map(|f| f.ident.to_string()).collect::<Vec<_>>().join(".");
            let value = attr.clone().tokens.into_iter().collect::<Vec<_>>().get(1).map(|f| format!("{}", f).replace("\"", ""));
            (name, value)
        })
        .collect::<HashMap<_, _>>()
}

pub fn get_struct_attribute(attrs: &Vec<Attribute>, name: &str) -> Option<String> {
    match get_struct_attributes(attrs).get(name) {
        Some(Some(x)) => Some(x.clone()),
        _ => None,
    }
}

#[allow(dead_code)]
pub fn snake_to_camel(s: &str) -> Cow<str> {
    if s.contains("_") {
        let mut buffer = String::with_capacity(s.len());
        let mut under = false;
        for c in s.chars() {
            match c {
                '_' => under = true,
                _ => {
                    if under {
                        buffer.push_str(&c.to_uppercase().to_string());
                        under = false;
                    } else {
                        buffer.push(c)
                    }
                }
            }
        }
        Cow::Owned(buffer)
    } else {
        Cow::Borrowed(s)
    }
}

#[allow(dead_code)]
pub fn default_true() -> bool {
    true
}

pub fn is_optional(ty: &Type) -> bool {
    if let Type::Path(tp) = ty {
        if let Some(segment) = tp.path.segments.last() {
            let name = format!("{}", &segment.ident);
            return &name == "Option" || &name == "std::option::Option";
        }
    }
    return false;
}

pub fn unwrap_type(ty: &Type) -> Cow<Type> {
    if let Type::Path(tp) = ty {
        if let Some(segment) = tp.path.segments.last() {
            let ident = &segment.ident;
            let name = format!("{}", ident);
            if &name == "Option" {
                if let PathArguments::AngleBracketed(generic_arguments) = &segment.arguments {
                    if let Some(GenericArgument::Type(subty)) = generic_arguments.args.first() {
                        return Cow::Borrowed(subty);
                    }
                }
            }
        }
    }
    Cow::Borrowed(ty)
}

pub fn get_type_name(ty: &Type) -> String {
    if let syn::Type::Path(tp) = unwrap_type(&ty).into_owned() {
        tp.path.segments.iter().map(|seg| format!("{}", seg.ident)).collect::<Vec<_>>().join(".")
    } else {
        "".to_owned()
    }
}