Skip to main content

diesel_sqlite_enum_integer/
lib.rs

1use proc_macro::{TokenStream};
2use syn::{parse_macro_input, Data, DeriveInput, Ident};
3use quote::{quote, ToTokens};
4
5#[proc_macro_attribute]
6pub fn enum_to_diesel_integer(_args: TokenStream, input: TokenStream) -> TokenStream {
7    let input = parse_macro_input!(input as DeriveInput);
8    let name = &input.ident;
9
10    let enum_names : Vec<Ident> = if let Data::Enum(data) = &input.data {
11        data.variants.iter().map(|x| x.ident.clone()).collect()
12    } else {
13        panic!("Only enums are supported.");
14    };
15
16
17    let mut to_sql_tokens: proc_macro2::TokenStream = quote! {};
18    let mut from_sql_tokens: proc_macro2::TokenStream = quote! {};
19
20    enum_names.iter()
21        .enumerate()
22        .for_each(|(i, e)| {
23            let i: i32 = i as i32;
24
25            quote! {
26                #name::#e=> diesel::serialize::ToSql::<diesel::sql_types::Integer, diesel::sqlite::Sqlite>::to_sql(&#i, out),
27            }.to_tokens(&mut to_sql_tokens);
28
29            quote! {
30                #i => Ok(#name::#e),
31            }.to_tokens(&mut from_sql_tokens);
32        });
33    
34
35    return quote!{
36        #[repr(i32)]
37        #[derive(Debug, PartialEq, diesel::FromSqlRow, diesel::AsExpression, Eq, Clone)]
38        #[diesel(sql_type = diesel::sql_types::Integer)]
39        #input
40
41        impl diesel::serialize::ToSql<diesel::sql_types::Integer, diesel::sqlite::Sqlite> for #name {
42            fn to_sql<'b>(&'b self, out: &mut diesel::serialize::Output<'b, '_, diesel::sqlite::Sqlite>) -> diesel::serialize::Result {
43                match self {
44                    #to_sql_tokens
45                    
46                }
47            }
48        }
49
50        impl diesel::deserialize::FromSql<diesel::sql_types::Integer, diesel::sqlite::Sqlite> for #name {
51            fn from_sql(bytes: diesel::sqlite::SqliteValue<'_, '_, '_>) -> diesel::deserialize::Result<Self> {
52                match <i32 as diesel::deserialize::FromSql<diesel::sql_types::Integer, diesel::sqlite::Sqlite>>::from_sql(bytes)? {
53                    #from_sql_tokens
54                    _ => Err("Unrecognized enum variant".into()),
55                }
56            }
57        }
58    }.into();
59}