extendr_macros/
dataframe.rs
1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, Data, DataStruct, DeriveInput};
4
5fn parse_struct(input: &DeriveInput, datastruct: &DataStruct) -> TokenStream {
6 let structname = &input.ident;
7 let mut a = Vec::new();
8 for f in &datastruct.fields {
9 a.push(f.ident.clone());
10 }
11 quote! {
12 impl extendr_api::wrapper::IntoDataFrameRow<#structname> for Vec<#structname>
13 {
14 fn into_dataframe(self) -> extendr_api::Result<extendr_api::wrapper::Dataframe<#structname>> {
15 #(let mut #a = Vec::with_capacity(self.len());)*
16 for val in self {
17 #(#a.push(val.#a);)*
18 }
19 let caller = extendr_api::functions::eval_string("data.frame")?;
20 let res = caller.call(extendr_api::wrapper::Pairlist::from_pairs(&[
21 #((stringify!(#a), extendr_api::robj::Robj::from(#a))),*
22 ]))?;
23 res.try_into()
24 }
25 }
26
27 impl<I> extendr_api::wrapper::IntoDataFrameRow<#structname> for (I,)
28 where
29 I : ExactSizeIterator<Item=#structname>,
30 {
31 fn into_dataframe(self) -> extendr_api::Result<extendr_api::wrapper::Dataframe<#structname>> {
33 #(let mut #a = Vec::with_capacity(self.0.len());)*
34 for val in self.0 {
35 #(#a.push(val.#a);)*
36 }
37 let caller = extendr_api::functions::eval_string("data.frame")?;
38 let res = caller.call(extendr_api::wrapper::Pairlist::from_pairs(&[
39 #((stringify!(#a), extendr_api::robj::Robj::from(#a))),*
40 ]))?;
41 res.try_into()
42 }
43 }
44 }
45 .into()
46}
47
48pub fn derive_into_dataframe(item: TokenStream) -> TokenStream {
49 let input: DeriveInput = parse_macro_input!(item as DeriveInput);
50
51 match &input.data {
52 Data::Struct(datastruct) => parse_struct(&input, datastruct),
53 _ => quote!(compile_error("IntoDataFrameRow expected a struct.")).into(),
54 }
55}