aboutsummaryrefslogtreecommitdiff
path: root/tosin-macros/src
diff options
context:
space:
mode:
Diffstat (limited to 'tosin-macros/src')
-rw-r--r--tosin-macros/src/lib.rs50
1 files changed, 39 insertions, 11 deletions
diff --git a/tosin-macros/src/lib.rs b/tosin-macros/src/lib.rs
index 7028274..c9e352c 100644
--- a/tosin-macros/src/lib.rs
+++ b/tosin-macros/src/lib.rs
@@ -18,7 +18,9 @@ pub fn model_derive(input: TokenStream) -> TokenStream {
impl_model(&ast)
}
-fn to_field_spec(field: &syn::Field) -> impl quote::ToTokens {
+// TODO clean all this shit up
+
+fn to_field_spec(field: &syn::Field) -> (impl quote::ToTokens, impl quote::ToTokens) {
fn parse_type(ty: &str) -> syn::Type {
syn::parse_str(ty).unwrap()
}
@@ -39,24 +41,42 @@ fn to_field_spec(field: &syn::Field) -> impl quote::ToTokens {
})
.collect();
if field_type == &parse_type("Option<Id>") {
- quote! { ::tosin::db::models::Field::IntField { name: stringify!(#field_name) } }
+ (
+ quote! { ::tosin::db::models::Field::IntField { name: stringify!(#field_name) } },
+ quote! { #field_name -> Integer }
+ )
} else if field_type == &parse_type("Id") {
// TODO foreign key constraint
- quote! { ::tosin::db::models::Field::IntField { name: stringify!(#field_name) } }
+ (
+ quote! { ::tosin::db::models::Field::IntField { name: stringify!(#field_name) } },
+ quote! { #field_name -> Integer }
+ )
} else if field_type == &parse_type("usize") {
// TODO default
- quote! { ::tosin::db::models::Field::IntField { name: stringify!(#field_name) } }
+ (
+ quote! { ::tosin::db::models::Field::IntField { name: stringify!(#field_name) } },
+ quote! { #field_name -> Integer }
+ )
} else if field_type == &parse_type("String") {
let max_length = model_options.iter()
.find(|(name, _value)| name.get_ident().map_or(false, |path| path == "max_length"))
.map(|(_name, value)| value);
if let Some(max_length) = max_length {
- quote! { ::tosin::db::models::Field::CharField { name: stringify!(#field_name), max_length: Some(#max_length) } }
+ (
+ quote! { ::tosin::db::models::Field::CharField { name: stringify!(#field_name), max_length: Some(#max_length) } },
+ quote! { #field_name -> Text }
+ )
} else {
- quote! { ::tosin::db::models::Field::CharField { name: stringify!(#field_name), max_length: None } }
+ (
+ quote! { ::tosin::db::models::Field::CharField { name: stringify!(#field_name), max_length: None } },
+ quote! { #field_name -> Text }
+ )
}
} else if field_type == &parse_type("time::PrimitiveDateTime") {
- quote! { ::tosin::db::models::Field::DateTimeField { name: stringify!(#field_name) } }
+ (
+ quote! { ::tosin::db::models::Field::DateTimeField { name: stringify!(#field_name) } },
+ quote! { #field_name -> Timestamp }
+ )
} else {
use quote::ToTokens;
panic!("can't handle {}", field.to_token_stream())
@@ -65,19 +85,27 @@ fn to_field_spec(field: &syn::Field) -> impl quote::ToTokens {
fn impl_model(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
- let fields = if let syn::Data::Struct(ast) = &ast.data {
- ast.fields.iter()
- .map(to_field_spec)
+ let lowercase_name = quote::format_ident!("{}", name.to_string().to_lowercase());
+ let ast_data = if let syn::Data::Struct(ast_data) = &ast.data {
+ ast_data
} else {
panic!("not on a struct");
};
+ let (tosin_fields, diesel_columns): (Vec<_>, Vec<_>) = ast_data.fields.iter().map(to_field_spec).unzip();
let gen = quote! {
impl #name {
pub const META: ::tosin::db::models::ModelMeta = ::tosin::db::models::ModelMeta {
name: stringify!(#name),
- fields: &[ #(#fields),* ],
+ fields: &[ #(#tosin_fields),* ],
};
}
+
+ // this means users need #[macro_use] extern crate diesel; but fuck doing it ourselves
+ table! {
+ #lowercase_name {
+ #(#diesel_columns,)*
+ }
+ }
};
gen.into()
}