from-sqlite-row-macro 1.0.0

from-sqlite-row-macro 是一个配套dev-tool crate,对自定义的结构体进行从row转为自定义结构的简化编写方式。
Documentation
use proc_macro::TokenStream;
use quote::quote;
use syn::{DeriveInput, parse_macro_input, Fields, Type};

/// 定义派生宏:#[derive(FromSqliteRow)]
/// 
/// 用于展开代码,为结构体实现 `dev_tool::sqlite_util::FromSqliteRow` trait
#[proc_macro_derive(FromSqliteRow)]
pub fn derive_from_sqlite_row(input: TokenStream) -> TokenStream {
    // 解析输入的结构体定义
    let input = parse_macro_input!(input as DeriveInput);
    let name = input.ident; // 获取结构体名称

    // 提取结构体字段(只处理命名字段的结构体,如 struct User { id: i32, name: String })
    let fields = match input.data {
        syn::Data::Struct(s) => s.fields,
        _ => panic!("FromSqliteRow 只能用于结构体"),
    };

    // 为每个字段生成从 sqlite::Row 读取的代码
    let field_initializers = match fields {
        Fields::Named(fields) => {
                let field_names = fields.named.clone();
                field_names.into_iter().map(|field| {
                // 获取字段名(如 id、name)
                let ident = field.ident.as_ref().unwrap();
                // 将字段名转换为字符串(用于作为SQL列名)
                let ident_str = ident.to_string();
                // 获取字段类型
                let field_type = &field.ty;

                let field_get_code = if let Type::Path(path) = field_type {
                    // 获取字段类型最后一层的名字
                    if let Some(seg) = path.path.segments.last() {
                        if seg.ident == "String" {
                            // 如果是 String 类型
                            quote! { row.read::<&str, _>(#ident_str).to_string() }
                        } else {
                            // 其他类型
                            quote! { row.read(#ident_str) }
                        }
                    } else {
                        quote! { row.read(#ident_str) }
                    }
                } else {
                    quote! { row.read(#ident_str) }
                };

                // 生成代码:#ident: <根据字段类型生成的获取代码>
                quote! {
                    #ident: #field_get_code
                }
            })
        },
        _ => panic!("FromSqliteRow 只支持带命名字段的结构体"),
    };

    // 生成完整的实现代码
    let expanded = quote! {
        impl FromSqliteRow for #name {
            fn from_row(row: &sqlite::Row) -> Self {
                Self {
                    #(#field_initializers),*
                }
            }
        }
    };

    TokenStream::from(expanded)
}