Function derive_proc_macros

Source
pub fn derive_proc_macros()
Expand description

介绍:serde.rs

参阅 : https://github.com/ZhangHanDong/proc_codegen

过程宏三件套:

示例:封装 Diesel 方便 crud


    // find_by_or!{ Person -> people::[name:String || company_name:String]   }

    use super::*;

    pub struct DbOpByOrBy {
        pub model: Type,
        pub table: Ident,
        pub bracket_token: token::Bracket,
        pub content: FieldContentOr,
    }

    pub struct FieldContentOr {
        pub name1: Ident,
        pub ty1: Type,
        pub name2: Ident,
        pub ty2: Type,
    }

    impl Parse for DbOpByOrBy {
        fn parse(input: ParseStream) -> Result<Self> {
            let content;
            let model: Type = input.parse()?;
            input.parse::<Token![->]>()?;
            let table: Ident = input.parse()?;
            input.parse::<Token![::]>()?;
            let bracket_token = bracketed!(content in input);
            let content = content.parse()?;
            Ok(DbOpByOrBy {
                model,
                table,
                bracket_token,
                content,
            })
        }
    }

    impl Parse for FieldContentOr {
        fn parse(input: ParseStream) -> Result<Self> {
            let name1: Ident = input.parse()?;
            input.parse::<Token![:]>()?;
            let ty1: Type = input.parse()?;
            input.parse::<Token![||]>()?;
            let name2: Ident = input.parse()?;
            input.parse::<Token![:]>()?;
            let ty2: Type = input.parse()?;
            Ok(FieldContentOr {
                name1,
                ty1,
                name2,
                ty2,
            })
        }
    }

    // in lib.rs

    // find_by_or!{ Person -> people::[name:String || company_name:String]   }

    #[proc_macro]
    pub fn find_by_or(input: TokenStream) -> TokenStream {
        let DbOpByOrBy {
            model,
            table,
            bracket_token,
            content,
        } = parse_macro_input!(input as DbOpByOrBy);
        let (name1, name2) = (content.name1, content.name2);
        let (ty1, ty2) = (content.ty1, content.ty2);
        let fn_name = format!("find_by_{}_or_{}", name1, name2);
        let fn_name = Ident::new(&fn_name, proc_macro2::Span::call_site());

        let expanded = quote! {
            impl #model {
                pub fn #fn_name(conn: &PgConnection, #name1: #ty1, #name2: #ty2) -> QueryResult<#model> {
                    #table::table
                    .filter(#table::dsl::#name1.eq(#name1))
                    .or_filter(#table::dsl::#name2.eq(#name2))
                    .get_result(conn)
                }
            }
        };
        TokenStream::from(expanded)
    }

有用的第三方库: