diff options
Diffstat (limited to 'tosin-macros')
| -rw-r--r-- | tosin-macros/src/lib.rs | 50 | 
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()  }  |