scylla_macros/
from_row.rsuse proc_macro::TokenStream;
use quote::{quote, quote_spanned};
use syn::{spanned::Spanned, DeriveInput};
pub fn from_row_derive(tokens_input: TokenStream) -> Result<TokenStream, syn::Error> {
let item = syn::parse::<DeriveInput>(tokens_input)?;
let path = crate::parser::get_path(&item)?;
let struct_fields = crate::parser::parse_named_fields(&item, "FromRow")?;
let struct_name = &item.ident;
let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
let set_fields_code = struct_fields.named.iter().map(|field| {
let field_name = &field.ident;
let field_type = &field.ty;
quote_spanned! {field.span() =>
#field_name: {
let (col_ix, col_value) = vals_iter
.next()
.unwrap(); <#field_type as FromCqlVal<::std::option::Option<CqlValue>>>::from_cql(col_value)
.map_err(|e| FromRowError::BadCqlVal {
err: e,
column: col_ix,
})?
},
}
});
let fields_count = struct_fields.named.len();
let generated = quote! {
impl #impl_generics #path::FromRow for #struct_name #ty_generics #where_clause {
fn from_row(row: #path::Row)
-> ::std::result::Result<Self, #path::FromRowError> {
use #path::{CqlValue, FromCqlVal, FromRow, FromRowError};
use ::std::result::Result::{Ok, Err};
use ::std::iter::{Iterator, IntoIterator};
if #fields_count != row.columns.len() {
return Err(FromRowError::WrongRowSize {
expected: #fields_count,
actual: row.columns.len(),
});
}
let mut vals_iter = row.columns.into_iter().enumerate();
Ok(#struct_name {
#(#set_fields_code)*
})
}
}
};
Ok(TokenStream::from(generated))
}