fixed rust could not infer types

This commit is contained in:
p0lunin 2020-06-24 19:13:56 +03:00
parent 87cbcf1140
commit 9fa60a7596

View file

@ -2,7 +2,7 @@ extern crate quote;
use quote::__private::Span; use quote::__private::Span;
use quote::{quote, ToTokens}; use quote::{quote, ToTokens};
use syn::{FieldsNamed, FieldsUnnamed}; use syn::{FieldsNamed, FieldsUnnamed, Type};
#[derive(Debug)] #[derive(Debug)]
pub enum ParserType { pub enum ParserType {
@ -26,7 +26,7 @@ pub fn impl_parse_args_unnamed(
variant: impl ToTokens, variant: impl ToTokens,
parser_type: &ParserType, parser_type: &ParserType,
) -> quote::__private::TokenStream { ) -> quote::__private::TokenStream {
let get_arguments = create_parser(parser_type, data.unnamed.len()); let get_arguments = create_parser(parser_type, data.unnamed.iter().map(|f| &f.ty), data.unnamed.len());
let iter = 0..data.unnamed.len(); let iter = 0..data.unnamed.len();
let mut initialization = quote! {}; let mut initialization = quote! {};
for i in iter { for i in iter {
@ -46,7 +46,7 @@ pub fn impl_parse_args_named(
variant: impl ToTokens, variant: impl ToTokens,
parser_type: &ParserType, parser_type: &ParserType,
) -> quote::__private::TokenStream { ) -> quote::__private::TokenStream {
let get_arguments = create_parser(parser_type, data.named.len()); let get_arguments = create_parser(parser_type, data.named.iter().map(|f| &f.ty), data.named.len());
let i = 0..data.named.len(); let i = 0..data.named.len();
let name = data.named.iter().map(|f| f.ident.as_ref().unwrap()); let name = data.named.iter().map(|f| f.ident.as_ref().unwrap());
let res = quote! { let res = quote! {
@ -58,16 +58,16 @@ pub fn impl_parse_args_named(
res res
} }
fn create_parser(parser_type: &ParserType, count_args: usize) -> quote::__private::TokenStream { fn create_parser<'a>(parser_type: &ParserType, types: impl Iterator<Item = &'a Type>, count_args: usize) -> quote::__private::TokenStream {
let function_to_parse = match parser_type { let function_to_parse = match parser_type {
ParserType::Default => match count_args { ParserType::Default => match count_args {
1 => { 1 => {
quote! { (|s: String| Ok((FromStr::from_str(&s).map_err(|_|ParseError::IncorrectFormat)?,)) ) } quote! { (|s: String| Ok((s,))) }
} }
_ => quote! { compile_error!("Expected 1 argument") }, _ => quote! { compile_error!("Expected 1 argument") },
}, },
ParserType::Split { separator } => { ParserType::Split { separator } => {
parser_with_separator(&separator.clone().unwrap_or(" ".to_owned()), count_args) parser_with_separator(&separator.clone().unwrap_or(" ".to_owned()), types, count_args)
} }
ParserType::Custom(s) => { ParserType::Custom(s) => {
let ident = syn::Ident::new(&s, Span::call_site()); let ident = syn::Ident::new(&s, Span::call_site());
@ -79,18 +79,17 @@ fn create_parser(parser_type: &ParserType, count_args: usize) -> quote::__privat
} }
} }
fn parser_with_separator(separator: &str, count_args: usize) -> quote::__private::TokenStream { fn parser_with_separator<'a>(separator: &str, types: impl Iterator<Item = &'a Type>, count_args: usize) -> quote::__private::TokenStream {
let inner = quote! { let mut splited = s.split(#separator); }; let inner = quote! { let mut splited = s.split(#separator); };
let mut inner2 = quote! {}; let i = 0..count_args;
for i in 0..count_args { let inner2 =
inner2.extend( quote! {
quote! { FromStr::from_str(splited.next().ok_or(ParseError::TooFewArguments { #(#types::from_str(splited.next().ok_or(ParseError::TooFewArguments {
expected: #count_args, expected: #count_args,
found: #i, found: #i,
message: format!("Expected but not found arg number {}", #i + 1), message: format!("Expected but not found arg number {}", #i + 1),
})?).map_err(|_|ParseError::IncorrectFormat)?, }, })?).map_err(|e|ParseError::IncorrectFormat({ let e: Box<dyn std::error::Error> = e.into(); e }))?,)*
) };
}
let res = quote! { let res = quote! {
(|s: String| { (|s: String| {
#inner #inner