scylla_macros/
from_user_type.rsuse proc_macro::TokenStream;
use quote::{quote, quote_spanned};
use syn::{spanned::Spanned, DeriveInput};
pub fn from_user_type_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, "FromUserType")?;
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: <#field_type as FromCqlVal<::std::option::Option<CqlValue>>>::from_cql(
{
let received_field_name: Option<&::std::string::String> = fields_iter
.peek()
.map(|(ref name, _)| name);
if let Some(received_field_name) = received_field_name {
if received_field_name == stringify!(#field_name) {
let (_, value) = fields_iter.next().unwrap();
value
} else {
None
}
} else {
None
}
}
) ?,
}
});
let generated = quote! {
impl #impl_generics #path::FromCqlVal<#path::CqlValue> for #struct_name #ty_generics #where_clause {
fn from_cql(cql_val: #path::CqlValue)
-> ::std::result::Result<Self, #path::FromCqlValError> {
use ::std::collections::BTreeMap;
use ::std::option::Option::{self, Some, None};
use ::std::result::Result::{Ok, Err};
use #path::{FromCqlVal, FromCqlValError, CqlValue};
use ::std::iter::{Iterator, IntoIterator};
let mut fields_iter = match cql_val {
CqlValue::UserDefinedType{fields, ..} => fields.into_iter().peekable(),
_ => return Err(FromCqlValError::BadCqlType),
};
let result = #struct_name {
#(#set_fields_code)*
};
if fields_iter.next().is_some() {
return Err(FromCqlValError::BadCqlType);
}
return Ok(result);
}
}
};
Ok(TokenStream::from(generated))
}