diesel_sqlite_enum_integer/
lib.rs1use 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}