iter_tuple/
lib.rs

1#![doc(html_root_url = "https://docs.rs/iter-tuple/0.3.8")]
2//! Rust iterator for tuple through proc-macro2 struct Vec AnyValue of polars DataFrame
3//!
4//! # Sample
5//!
6//! - [https://crates.io/crates/egui-dataframe-sample](https://crates.io/crates/egui-dataframe-sample)
7//! - [https://github.com/nomissbowling/egui-dataframe-sample](https://github.com/nomissbowling/egui-dataframe-sample)
8//!
9//! # Requirements
10//!
11//! - [https://github.com/pola-rs/polars](https://github.com/pola-rs/polars)
12//! - [polars](https://crates.io/crates/polars)
13//! - [polars-utils](https://crates.io/crates/polars-utils)
14//!
15//! # Optional
16//! - [https://crates.io/crates/sqlite](https://crates.io/crates/sqlite)
17//! - [https://crates.io/crates/polars-sqlite](https://crates.io/crates/polars-sqlite)
18//! - [https://crates.io/crates/anyvalue-dataframe](https://crates.io/crates/anyvalue-dataframe)
19//!
20
21use proc_macro::TokenStream;
22use proc_macro2::TokenStream as PM2TS;
23use proc_macro2::{TokenTree, Ident, Literal}; // Group, Punct
24use proc_macro2::{Span}; // Delimiter, Spacing
25use quote::{quote, ToTokens}; // quote::ToTokens in proc_macro2
26use syn; // syn::{parse_macro_input, ItemFn};
27use std::ops::Deref;
28
29/// concat ident to pre ast (before parse as syn::Ident)
30/// - a: true: as is, false: to lowercase
31fn pre_ast_ident(pre: &str, id: &Ident, post: &str, a: bool) -> TokenStream {
32//  let ast_id: syn::Ident = syn::parse_quote! { XXX#id }; // unknown prefix
33//  let id: TokenStream = quote! { XXX#id }.into(); // unknown prefix
34  let mut s = id.to_string();
35  if !a { s = s.to_lowercase(); }
36  let str_id = &format!("{}{}{}", pre, s, post);
37  let mut ts: PM2TS = PM2TS::new(); // proc_macro2::TokenStream
38  Ident::new(str_id, Span::call_site()).to_tokens(&mut ts);
39  ts.into()
40}
41
42/// concat string literal to pre ast (before prepare as Literal)
43/// - a: true: as is, false: to lowercase
44fn pre_ast_string(pre: &str, id: &Ident, post: &str, a: bool) -> TokenStream {
45  let mut s = id.to_string();
46  if !a { s = s.to_lowercase(); }
47  let str_id = &format!("{}{}{}", pre, s, post);
48  let mut ts: PM2TS = PM2TS::new(); // proc_macro2::TokenStream
49  Literal::string(str_id).to_tokens(&mut ts);
50  ts.into()
51}
52
53/// usize to pre ast (before parse as Literal)
54fn pre_ast_usize(n: usize) -> TokenStream {
55  let mut ts: PM2TS = PM2TS::new(); // proc_macro2::TokenStream
56  Literal::usize_unsuffixed(n).to_tokens(&mut ts); // #n is usize_suffixed
57  ts.into()
58}
59
60/// from polars DataType to primitive type (proc_macro2::TokenStream)
61fn ast_dtype(dt: &Ident) -> PM2TS {
62  match dt.to_string().as_str() {
63  "Int64" => quote! { i64 },
64  "Int32" => quote! { i32 },
65  "Int16" => quote! { i16 },
66  "Int8" => quote! { i8 },
67  "UInt64" => quote! { u64 },
68  "UInt32" => quote! { u32 },
69  "UInt16" => quote! { u16 },
70  "UInt8" => quote! { u8 },
71  "Float64" => quote! { f64 }, // Decimal in polars latest
72  "Float32" => quote! { f32 }, // Decimal in polars latest
73  "Utf8" => quote! { &'a str }, // polars version 0.25.1
74  "String" => quote! { &'a str }, // polars latest
75  "Boolean" => quote! { bool },
76  "Binary" => quote! { Vec<u8> },
77  "Null" => quote! { i64 }, // must check later
78  "Unknown" => quote! { i64 }, // must check later
79  _ => quote! { i64 } // must check later
80  }
81}
82
83/// from polars DataType to primitive value (proc_macro2::TokenStream)
84fn ast_dtype_from_anyvalue_col(dt: &Ident, n: &Literal) -> PM2TS {
85/*
86  match dt.to_string().as_str() {
87  "Int64" => quote! { match v[#n] {AnyValue::Int64(i) => i, _ => 0} },
88  "Int32" => quote! { match v[#n] {AnyValue::Int32(i) => i, _ => 0} },
89  "Int16" => quote! { match v[#n] {AnyValue::Int16(i) => i, _ => 0} },
90  "Int8" => quote! { match v[#n] {AnyValue::Int8(i) => i, _ => 0} },
91  "UInt64" => quote! { match v[#n] {AnyValue::UInt64(u) => u, _ => 0} },
92  "UInt32" => quote! { match v[#n] {AnyValue::UInt32(u) => u, _ => 0} },
93  "UInt16" => quote! { match v[#n] {AnyValue::UInt16(u) => u, _ => 0} },
94  "UInt8" => quote! { match v[#n] {AnyValue::UInt8(u) => u, _ => 0} },
95  "Float64" => quote! { match v[#n] {AnyValue::Float64(f) => f, _ => 0.0} },
96  "Float32" => quote! { match v[#n] {AnyValue::Float32(f) => f, _ => 0.0} },
97  "Utf8" => quote! { match v[#n] {
98    AnyValue::Utf8(s) => s, // polars 0.25.1
99    _ => ""
100  } },
101  "String" => quote! { match v[#n] {
102    AnyValue::String(s) => s, // polars latest
103    _ => "".to_string()
104  } },
105  "Boolean" => quote! { match v[#n] {AnyValue::Boolean(b) => b, _ => false} },
106  "Binary" => quote! { match &v[#n] { // must match with reference
107    AnyValue::BinaryOwned(u) => u.clone(),
108    AnyValue::Binary(u) => u.to_vec(),
109    _ => vec![]
110  } },
111  "Null" => quote! { match v[#n] { _ => 0} }, // must check later
112  "Unknown" => quote! { match v[#n] { _ => 0} }, // must check later
113  _ => quote! { match v[#n] { _ => 0} } // must check later
114  }
115*/
116  quote! { from_any!(v[#n], DataType::#dt) }
117}
118
119/// from polars DataType to sqlite3 type WR (proc_macro2::TokenStream)
120fn ast_dtype_to_sqlite3_vec(dt: &Ident, ast_id: &Ident) -> PM2TS {
121  match dt.to_string().as_str() {
122  "Int64" => quote! { self.#ast_id },
123  "Int32" => quote! { (self.#ast_id as i64) },
124  "Int16" => quote! { (self.#ast_id as i64) },
125  "Int8" => quote! { (self.#ast_id as i64) },
126  "UInt64" => quote! { (self.#ast_id as i64) },
127  "UInt32" => quote! { (self.#ast_id as i64) },
128  "UInt16" => quote! { (self.#ast_id as i64) },
129  "UInt8" => quote! { (self.#ast_id as i64) },
130  "Float64" => quote! { self.#ast_id }, // Decimal in polars latest
131  "Float32" => quote! { (self.#ast_id as f64) }, // Decimal in polars latest
132  "Utf8" => quote! { self.#ast_id }, // polars version 0.25.1
133  "String" => quote! { self.#ast_id }, // polars latest
134  "Boolean" => quote! { (if self.#ast_id {"T"} else {"F"}) },
135  "Binary" => quote! { (&self.#ast_id[..]) },
136  "Null" => quote! { self.#ast_id }, // must check later
137  "Unknown" => quote! { self.#ast_id }, // must check later
138  _ => quote! { self.#ast_id } // must check later
139  }
140}
141
142/// from polars DataType to sqlite3 type RD (tuple of proc_macro2::TokenStream)
143fn ast_dtype_sqlite3_col(dt: &Ident) -> (PM2TS, PM2TS) {
144  match dt.to_string().as_str() {
145  "Int64" => (quote! { i64 }, quote! {}),
146  "Int32" => (quote! { i64 }, quote! { as i32 }),
147  "Int16" => (quote! { i64 }, quote! { as i16 }),
148  "Int8" => (quote! { i64 }, quote! { as i8 }),
149  "UInt64" => (quote! { i64 }, quote! { as u64 }),
150  "UInt32" => (quote! { i64 }, quote! { as u32 }),
151  "UInt16" => (quote! { i64 }, quote! { as u16 }),
152  "UInt8" => (quote! { i64 }, quote! { as u8 }),
153  "Float64" => (quote! { f64 }, quote! {}), // Decimal in polars latest
154  "Float32" => (quote! { f64 }, quote! { as f32 }), // Decimal in polars latest
155  "Utf8" => (quote! { &'a str }, quote! {}), // polars version 0.25.1
156  "String" => (quote! { &'a str }, quote! {}), // polars latest
157  "Boolean" => (quote! { &'a str }, quote! { == "T" }), // not impl. trait From
158  "Binary" => (quote! { &[u8] }, quote! { .to_vec() }), // not impl. trait From
159  "Null" => (quote! { i64 }, quote! {}), // must check later
160  "Unknown" => (quote! { i64 }, quote! {}), // must check later
161  _ => (quote! { i64 }, quote! {}) // must check later
162  }
163}
164
165/// from attr to tuple of sqlite3 cols
166fn sqlite3_cols(attr: PM2TS, n: &mut usize) -> TokenStream {
167  let mut cols = quote! {};
168  for tt in attr { // not use .into_iter().enumerate() to count skip Punct ','
169    match tt {
170    TokenTree::Ident(dt) => { // match only Ident
171//      println!("{}: {:?}", n, dt);
172      let i = pre_ast_usize(*n); // outside of macro call
173      let ast_i = syn::parse_macro_input!(i as Literal);
174      let (t, p) = ast_dtype_sqlite3_col(&dt);
175      cols = quote! {
176        #cols
177        row.read::<#t, _>(#ast_i) #p,
178      };
179      *n += 1;
180    },
181    _ => {} // skip Punct ',' etc
182    }
183  }
184  quote! { (#cols) }.into()
185}
186
187/// from attr to vec of cols type
188fn type_cols(attr: PM2TS) -> TokenStream {
189  let mut cols = quote! {};
190  for tt in attr { // not use .into_iter().enumerate() to count skip Punct ','
191    match tt {
192    TokenTree::Ident(dt) => { // match only Ident
193//      println!("{:?}", dt);
194      cols = quote! {
195        #cols
196        DataType::#dt,
197      };
198    },
199    _ => {} // skip Punct ',' etc
200    }
201  }
202  quote! { vec![#cols] }.into()
203}
204
205/// from attr to vec of cols
206fn vec_cols(attr: PM2TS, n: &mut usize) -> TokenStream {
207  let mut cols = quote! {};
208  for tt in attr { // not use .into_iter().enumerate() to count skip Punct ','
209    match tt {
210    TokenTree::Ident(dt) => { // match only Ident
211//      println!("{}: {:?}", n, dt);
212      let i = pre_ast_usize(*n); // outside of macro call
213      let ast_i = syn::parse_macro_input!(i as Literal);
214      let v = match dt.to_string().as_str() {
215      // vec_cols through "Boolean" => ...
216      // "Binary" => quote! { &t.#ast_i }, // use below (can't use .to_owned())
217      "Binary" => quote! { to_any!(t.#ast_i, DataType::BinaryOwned) },
218      // _ => quote! { t.#ast_i } // skip (use below) for support BinaryOwned
219      _ => quote! { to_any!(t.#ast_i, DataType::#dt) }
220      };
221      cols = quote! {
222        #cols
223        // #v.into(), // it is not whole implemented in some version of polars
224        // AnyValue::#dt(#v), // same as below
225        // to_any!(#v, DataType::#dt), // skip (use below) for Binary Owned
226        #v,
227      };
228      *n += 1;
229    },
230    _ => {} // skip Punct ',' etc
231    }
232  }
233  quote! { let v = vec![#cols]; }.into()
234}
235
236/// from attr to sqlite3 vec of member tuple
237fn to_sqlite3_vec(mns: &Vec<Ident>, dts: &Vec<Ident>) -> TokenStream {
238  let mut members = quote! {};
239  for (i, n) in mns.iter().enumerate() {
240    let tag = pre_ast_string(":", n, "", true);
241    let ast_tag = syn::parse_macro_input!(tag as Literal); // be TokenStream
242    let id = pre_ast_ident("", n, "", true);
243    let ast_id = syn::parse_macro_input!(id as syn::Ident); // be TokenStream
244    let v = ast_dtype_to_sqlite3_vec(&dts[i], &ast_id);
245    members = quote! {
246      #members
247      (#ast_tag, #v.into()),
248    }
249  }
250  quote! { vec![#members] }.into() // be TokenStream
251}
252
253/// from attr to list of value
254fn from_anyvalue_col(dts: &Vec<Ident>) -> TokenStream {
255  let mut members = quote! {};
256  for (i, dt) in dts.iter().enumerate() {
257    let u = pre_ast_usize(i); // outside of macro call
258    let ast_i = syn::parse_macro_input!(u as Literal);
259    let v = ast_dtype_from_anyvalue_col(dt, &ast_i);
260    members = quote! {
261      #members
262      #v,
263    };
264  }
265  quote! { (#members) }.into() // be TokenStream
266}
267
268/// from attr to from_tuple of member
269fn from_tuple_members(mns: &Vec<Ident>) -> TokenStream {
270  let mut members = quote! {};
271  for (i, n) in mns.iter().enumerate() {
272    let id = pre_ast_ident("", n, "", true);
273    let ast_id = syn::parse_macro_input!(id as syn::Ident); // be TokenStream
274    let u = pre_ast_usize(i); // outside of macro call
275    let ast_i = syn::parse_macro_input!(u as Literal);
276    members = quote! {
277      #members
278      #ast_id: t.#ast_i,
279    };
280  }
281  members.into() // be TokenStream
282}
283
284/// from attr to to_tuple of member
285fn to_tuple_members(mns: &Vec<Ident>, dts: &Vec<Ident>) -> TokenStream {
286  let mut members = quote! {};
287  for (i, n) in mns.iter().enumerate() {
288    let id = pre_ast_ident("", n, "", true);
289    let ast_id = syn::parse_macro_input!(id as syn::Ident); // be TokenStream
290    let v = match dts[i].to_string().as_str() {
291    // to_tuple_members through "Boolean" => ...
292    "Binary" => quote! { self.#ast_id.clone() },
293    _ => quote! { self.#ast_id }
294    };
295    members = quote! {
296      #members
297      #v,
298    };
299  }
300  quote! { (#members) }.into() // be TokenStream
301}
302
303/// from attr to list of DataType
304fn type_members(dts: &Vec<Ident>) -> TokenStream {
305  let mut members = quote! {};
306  for dt in dts.iter() {
307    members = quote! {
308      #members
309      DataType::#dt,
310    };
311  }
312  quote! { vec![#members] }.into() // be TokenStream
313}
314
315/// from attr to list of member stringify
316fn str_members(mns: &Vec<Ident>) -> TokenStream {
317  let mut members = quote! {};
318  for n in mns.iter() {
319    let id = pre_ast_ident("", n, "", true);
320    let ast_id = syn::parse_macro_input!(id as syn::Ident); // be TokenStream
321    members = quote! {
322      #members
323      stringify!(#ast_id),
324    };
325  }
326  quote! { vec![#members] }.into() // be TokenStream
327}
328
329/// from attr to list of member and DataType
330fn list_members(mns: &Vec<Ident>, dts: &Vec<Ident>) -> TokenStream {
331  let mut members = quote! {};
332  for (i, n) in mns.iter().enumerate() {
333    let id = pre_ast_ident("", n, "", true);
334    let ast_id = syn::parse_macro_input!(id as syn::Ident); // be TokenStream
335    let dt = ast_dtype(&dts[i]);
336    members = quote! {
337      #members
338      ///
339      pub #ast_id: #dt,
340    };
341  }
342  members.into() // be TokenStream
343}
344
345/// from attr to tuple of Vec member name and Vec DataType
346fn parse_attr(attr: PM2TS) -> (Vec<Ident>, Vec<Ident>) {
347  let (mut mns, mut dts) = (Vec::<Ident>::new(), Vec::<Ident>::new());
348  let mut i = 0usize;
349  for tt in attr { // not use .into_iter().enumerate() to count skip Punct ','
350    match tt {
351    TokenTree::Group(gp) => { // match only Group
352      for t in gp.stream() {
353        match t {
354        TokenTree::Ident(dt) => { // match only Ident
355//          println!("{}: {:?}", n, dt);
356          if i == 0 { mns.push(dt); } else { dts.push(dt); }
357        },
358        _ => {} // skip Punct ',' etc
359        }
360      }
361      i += 1;
362    },
363    _ => {} // skip Punct ',' etc
364    }
365  }
366  (mns, dts)
367}
368
369/// check type is tuple and elem length (pipeline for TokenStream)
370fn tuple_check(item: TokenStream, n: usize, f: &str) -> TokenStream {
371  let ast = syn::parse_macro_input!(item as syn::ItemType);
372//  dbg!(ast.clone());
373  let ty = &ast.ty; // syn::Type::Tuple (syn::ItemType -> ty: Box<syn::Type>)
374//  println!("{:?}", ty);
375  let elem_len = match ty.deref() {
376  syn::Type::Tuple(typetuple) => { // syn::TypeTuple != syn::Type::Tuple
377//    println!("{:?}", typetuple);
378    typetuple.elems.len()
379  },
380  _ => { panic!("{} requires type alias of tuple", f); }
381  };
382//  println!("{}", elem_len);
383  if elem_len != n { panic!("{} attributes not match with tuple", f); }
384  ast.into_token_stream().into()
385}
386
387/// struct_derive
388/// - (optional)
389#[proc_macro_attribute]
390pub fn struct_derive(attr: TokenStream, item: TokenStream) -> TokenStream {
391//  println!("{:?}", attr);
392  let (mns, dts) = parse_attr(attr.into());
393  let (m, n) = (mns.len(), dts.len());
394  if m != n { panic!("struct_derive attributes not same length"); }
395  let ast_type_members: PM2TS = type_members(&dts).into();
396//  dbg!(ast_type_members.clone());
397  let ast_str_members: PM2TS = str_members(&mns).into();
398//  dbg!(ast_str_members.clone());
399  let ast_list_members: PM2TS = list_members(&mns, &dts).into();
400//  dbg!(ast_list_members.clone());
401  let ast_to_tuple_members: PM2TS = to_tuple_members(&mns, &dts).into();
402//  dbg!(ast_to_tuple_members.clone());
403  let ast_from_tuple_members: PM2TS = from_tuple_members(&mns).into();
404//  dbg!(ast_from_tuple_members.clone());
405  let ast_to_sqlite3_vec: PM2TS = to_sqlite3_vec(&mns, &dts).into();
406//  dbg!(ast_to_sqlite3_vec.clone());
407  let ast_from_anyvalue_col: PM2TS = from_anyvalue_col(&dts).into();
408//  dbg!(ast_from_anyvalue_col.clone());
409
410  let tp = tuple_check(item, n, "struct_derive");
411  let ast = syn::parse_macro_input!(tp as syn::ItemType);
412
413  let tpl_id = &ast.ident;
414//  println!("{:?}", tpl_id);
415  let st_id = pre_ast_ident("St", tpl_id, "", true); // outside of macro call
416  let ast_st_id = syn::parse_macro_input!(st_id as syn::Ident);
417//  dbg!(ast_st_id.clone());
418  let fnc_id = pre_ast_ident("to_", tpl_id, "", false); // to lowercase
419  let ast_fnc_id = syn::parse_macro_input!(fnc_id as syn::Ident);
420//  dbg!(ast_fnc_id.clone());
421  let rec_id = pre_ast_ident("Rec", tpl_id, "", true); // outside of macro call
422  let ast_rec_id = syn::parse_macro_input!(rec_id as syn::Ident);
423//  dbg!(ast_rec_id.clone());
424
425  quote! {
426#ast
427///
428pub struct #ast_st_id<'a> {
429  #ast_list_members
430}
431///
432impl<'a> #ast_st_id<'a> {
433  ///
434  pub fn members() -> Vec<&'a str> {
435    #ast_str_members
436  }
437  ///
438  pub fn types() -> Vec<DataType> {
439    #ast_type_members
440  }
441  ///
442  pub fn #ast_fnc_id(&self) -> #tpl_id<'_> {
443    #ast_to_tuple_members
444  }
445}
446///
447impl<'a> IntoAnyValueVec<'a> for #ast_st_id<'a> {
448  ///
449  fn into_vec(self) -> Vec<AnyValue<'a>> {
450//    #ast_rec_id::from(self.#ast_fnc_id()).v // can't reference to data owned
451    #ast_rec_id::from(#ast_to_tuple_members).v
452  }
453}
454///
455impl<'a> ToSqlite3ValueVec for #ast_st_id<'a> {
456  ///
457  fn to_sqlite3_vec(&self) -> Vec<(&'_ str, sqlite::Value)> {
458    #ast_to_sqlite3_vec
459  }
460}
461///
462impl<'a> From<#tpl_id<'a>> for #ast_st_id<'a> {
463  ///
464  fn from(t: #tpl_id<'a>) -> #ast_st_id<'_> {
465    #ast_st_id{#ast_from_tuple_members}
466  }
467}
468///
469impl<'a> From<&'a sqlite::Row> for #ast_st_id<'a> {
470  ///
471  fn from(row: &'a sqlite::Row) -> #ast_st_id<'_> {
472    #ast_st_id::from(#ast_fnc_id(row))
473  }
474}
475///
476impl<'a> From<&'a Vec<AnyValue<'a>>> for #ast_st_id<'a> {
477  ///
478  fn from(v: &'a Vec<AnyValue<'a>>) -> #ast_st_id<'_> {
479    #ast_st_id::from(#ast_from_anyvalue_col)
480  }
481}
482  }.into()
483/*
484  dbg!(ast.clone());
485  ast.into_token_stream().into()
486*/
487}
488
489/// tuple_sqlite3
490/// - (optional) see crate sqlite https://crates.io/crates/sqlite
491#[proc_macro_attribute]
492pub fn tuple_sqlite3(attr: TokenStream, item: TokenStream) -> TokenStream {
493//  println!("{:?}", attr);
494  let mut n = 0usize;
495  let ts_cols = sqlite3_cols(attr.into(), &mut n); // outside of macro call
496  let ast_cols = syn::parse_macro_input!(ts_cols as syn::Expr);
497//  dbg!(ast_cols.clone());
498
499  let tp = tuple_check(item, n, "tuple_sqlite3");
500  let ast = syn::parse_macro_input!(tp as syn::ItemType);
501
502  let tpl_id = &ast.ident;
503//  println!("{:?}", tpl_id);
504  let rec_id = pre_ast_ident("Rec", tpl_id, "", true); // outside of macro call
505  let ast_rec_id = syn::parse_macro_input!(rec_id as syn::Ident);
506//  dbg!(ast_rec_id.clone());
507  let fnc_id = pre_ast_ident("to_", tpl_id, "", false); // to lowercase
508  let ast_fnc_id = syn::parse_macro_input!(fnc_id as syn::Ident);
509//  dbg!(ast_fnc_id.clone());
510
511  quote! {
512#ast
513///
514pub fn #ast_fnc_id<'a>(row: &'a sqlite::Row) -> #tpl_id<'_> {
515  #ast_cols
516}
517///
518impl<'a> From<&'a sqlite::Row> for #ast_rec_id<'a> {
519  ///
520  fn from(row: &'a sqlite::Row) -> #ast_rec_id<'_> {
521    #ast_rec_id::from(#ast_fnc_id(row))
522  }
523}
524  }.into()
525/*
526  dbg!(ast.clone());
527  ast.into_token_stream().into()
528*/
529}
530
531/// tuple_derive
532/// - Utf8, UInt64, Int64, UInt32, Int32, Float64, Float32, Boolean, Binary, ...
533/// - see Enum polars::datatypes::DataType
534#[proc_macro_attribute]
535pub fn tuple_derive(attr: TokenStream, item: TokenStream) -> TokenStream {
536//  println!("{:?}", attr);
537  let type_cols = type_cols(attr.clone().into()); // outside of macro call
538  let ast_type_members = syn::parse_macro_input!(type_cols as syn::Expr);
539//  dbg!(ast_type_members.clone());
540
541  let mut n = 0usize;
542  let ts_cols = vec_cols(attr.into(), &mut n); // outside of macro call
543  let ast_cols = syn::parse_macro_input!(ts_cols as syn::Stmt);
544//  dbg!(ast_cols.clone());
545
546  let tp = tuple_check(item, n, "tuple_derive");
547  let ast = syn::parse_macro_input!(tp as syn::ItemType);
548
549  let tpl_id = &ast.ident;
550//  println!("{:?}", tpl_id);
551  let rec_id = pre_ast_ident("Rec", tpl_id, "", true); // outside of macro call
552  let ast_rec_id = syn::parse_macro_input!(rec_id as syn::Ident);
553//  dbg!(ast_rec_id.clone());
554
555  quote! {
556#ast
557///
558pub struct #ast_rec_id<'a> {
559  ///
560  pub v: Vec<AnyValue<'a>>
561}
562///
563impl<'a> IntoIterator for #ast_rec_id<'a> {
564  ///
565  type Item = AnyValue<'a>;
566  ///
567  type IntoIter = std::vec::IntoIter<Self::Item>;
568  //type IntoIter: Iterator<Item = Self::Item>;
569  ///
570  fn into_iter(self) -> Self::IntoIter {
571    self.v.into_iter()
572  }
573}
574///
575impl<'a> From<#tpl_id<'a>> for #ast_rec_id<'a> {
576  ///
577  fn from(t: #tpl_id<'a>) -> #ast_rec_id<'_> {
578    #ast_cols
579    #ast_rec_id{v}
580  }
581}
582///
583impl<'a> #ast_rec_id<'a> {
584  ///
585  pub fn types() -> Vec<DataType> {
586    #ast_type_members
587  }
588  ///
589  pub fn into_iter(t: #tpl_id<'a>) -> std::vec::IntoIter<AnyValue<'_>> {
590    #ast_rec_id::from(t).into_iter()
591  }
592}
593  }.into()
594/*
595  dbg!(ast.clone());
596  ast.into_token_stream().into()
597*/
598}
599
600/// tests
601#[cfg(test)]
602mod tests {
603//  use super::*;
604
605  /// [-- --nocapture] [-- --show-output]
606  /// can't use a procedural macro from the same crate that defines it
607  #[test]
608  fn test_iter_tuple() {
609    assert_eq!(true, true);
610  }
611}