fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
	let fns = decl.items.iter().filter_map(|i| match i {
		TraitItem::Method(ref m) => Some(&m.sig),
		_ => None,
	});

	let mut result = Vec::new();
	let trait_ = &decl.ident;
	let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);

	// Auxiliary function that is used to convert between types that use different block types.
	// The function expects that both a convertable by encoding the one and decoding the other.
	result.push(quote!(
		#[cfg(any(feature = "std", test))]
		fn convert_between_block_types
			<I: #crate_::runtime_api::Encode, R: #crate_::runtime_api::Decode>(
				input: &I, error_desc: &'static str,
			) -> ::std::result::Result<R, &'static str>
		{
			<R as #crate_::runtime_api::Decode>::decode(
				&mut &#crate_::runtime_api::Encode::encode(input)[..]
			).ok_or_else(|| error_desc)
		}
	));

	// Generate a native call generator for each function of the given trait.
	for fn_ in fns {
		let params = extract_parameter_names_types_and_borrows(&fn_.decl)?;
		let trait_fn_name = &fn_.ident;
		let fn_name = generate_native_call_generator_fn_name(&fn_.ident);
		let output = return_type_replace_block_with_node_block(fn_.decl.output.clone());
		let output_ty = return_type_extract_type(&output);
		let output = quote!( ::std::result::Result<#output_ty, &'static str> );

		// Every type that is using the `Block` generic parameter, we need to encode/decode,
		// to make it compatible between the runtime/node.
		let conversions = params.iter().filter(|v| type_is_using_block(&v.1)).map(|(n, t, _)| {
			let name_str = format!(
				"Could not convert parameter `{}` between node and runtime!", quote!(#n)
			);
			quote!(
				let #n: #t = convert_between_block_types(&#n, #name_str)?;
			)
		});
		// Same as for the input types, we need to check if we also need to convert the output,
		// before returning it.
		let output_conversion = if return_type_is_using_block(&fn_.decl.output) {
			quote!(
				convert_between_block_types(
					&res,
					"Could not convert return value from runtime to node!"
				)
			)
		} else {
			quote!( Ok(res) )
		};

		let input_names = params.iter().map(|v| &v.0);
		// If the type is using the block generic type, we will encode/decode it to make it
		// compatible. To ensure that we forward it by ref/value, we use the value given by the
		// the user. Otherwise if it is not using the block, we don't need to add anything.
		let input_borrows = params
			.iter()
			.map(|v| if type_is_using_block(&v.1) { v.2.clone() } else { quote!() });

		// Replace all `Block` with `NodeBlock`, add `'a` lifetime to references and collect
		// all the function inputs.
		let fn_inputs = fn_
			.decl
			.inputs
			.iter()
			.map(|v| fn_arg_replace_block_with_node_block(v.clone()))
			.map(|v| match v {
				FnArg::Captured(ref arg) => {
					let mut arg = arg.clone();
					if let Type::Reference(ref mut r) = arg.ty {
						r.lifetime = Some(parse_quote!( 'a ));
					}
					FnArg::Captured(arg)
				},
				r => r.clone(),
			});

		let (impl_generics, ty_generics, where_clause) = decl.generics.split_for_impl();
		// We need to parse them again, to get an easy access to the actual parameters.
		let impl_generics: Generics = parse_quote!( #impl_generics );
		let impl_generics_params = impl_generics.params.iter().map(|p| {
			match p {
				GenericParam::Type(ref ty) => {
					let mut ty = ty.clone();
					ty.bounds.push(parse_quote!( 'a ));
					GenericParam::Type(ty)
				},
				// We should not see anything different than type params here.
				r => r.clone(),
			}
		});

		// Generate the generator function
		result.push(quote!(
			#[cfg(any(feature = "std", test))]
			pub fn #fn_name<
				'a, ApiImpl: #trait_ #ty_generics, NodeBlock: #crate_::runtime_api::BlockT
				#(, #impl_generics_params)*
			>(
				#( #fn_inputs ),*
			) -> impl FnOnce() -> #output + 'a #where_clause {
				move || {
					#( #conversions )*
					let res = ApiImpl::#trait_fn_name(#( #input_borrows #input_names ),*);
					#output_conversion
				}
			}
		));
	}

	Ok(quote!( #( #result )* ))
}
/// Generate the functions that generate the native call closure for each trait method.
Generate the functions that generate the native call closure for each trait method.
Generate the functions that generate the native call closure for each trait method .
fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
	let fns = decl.items.iter().filter_map(|i| match i {
		TraitItem::Method(ref m) => Some(&m.sig),
		_ => None,
	});
	let mut result = Vec::new();
	let trait_ = &decl.ident;
	let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);
	// Auxiliary function that is used to convert between types that use different block types.
	// The function expects that both a convertable by encoding the one and decoding the other.
	result.push(quote!(
		#[cfg(any(feature = "std", test))]
		fn convert_between_block_types
			<I: #crate_::runtime_api::Encode, R: #crate_::runtime_api::Decode>(
				input: &I, error_desc: &'static str,
			) -> ::std::result::Result<R, &'static str>
		{
			<R as #crate_::runtime_api::Decode>::decode(
				&mut &#crate_::runtime_api::Encode::encode(input)[..]
			).ok_or_else(|| error_desc)
		}
	));
	// Generate a native call generator for each function of the given trait.
	for fn_ in fns {
		let params = extract_parameter_names_types_and_borrows(&fn_.decl)?;
		let trait_fn_name = &fn_.ident;
		let fn_name = generate_native_call_generator_fn_name(&fn_.ident);
		let output = return_type_replace_block_with_node_block(fn_.decl.output.clone());
		let output_ty = return_type_extract_type(&output);
		let output = quote!( ::std::result::Result<#output_ty, &'static str> );
		// Every type that is using the `Block` generic parameter, we need to encode/decode,
		// to make it compatible between the runtime/node.
		let conversions = params.iter().filter(|v| type_is_using_block(&v.1)).map(|(n, t, _)| {
			let name_str = format!(
				"Could not convert parameter `{}` between node and runtime!", quote!(#n)
			);
			quote!(
				let #n: #t = convert_between_block_types(&#n, #name_str)?;
			)
		});
		// Same as for the input types, we need to check if we also need to convert the output,
		// before returning it.
		let output_conversion = if return_type_is_using_block(&fn_.decl.output) {
			quote!(
				convert_between_block_types(
					&res,
					"Could not convert return value from runtime to node!"
				)
			)
		} else {
			quote!( Ok(res) )
		};
		let input_names = params.iter().map(|v| &v.0);
		// If the type is using the block generic type, we will encode/decode it to make it
		// compatible. To ensure that we forward it by ref/value, we use the value given by the
		// the user. Otherwise if it is not using the block, we don't need to add anything.
		let input_borrows = params
			.iter()
			.map(|v| if type_is_using_block(&v.1) { v.2.clone() } else { quote!() });
		// Replace all `Block` with `NodeBlock`, add `'a` lifetime to references and collect
		// all the function inputs.
		let fn_inputs = fn_
			.decl
			.inputs
			.iter()
			.map(|v| fn_arg_replace_block_with_node_block(v.clone()))
			.map(|v| match v {
				FnArg::Captured(ref arg) => {
					let mut arg = arg.clone();
					if let Type::Reference(ref mut r) = arg.ty {
						r.lifetime = Some(parse_quote!( 'a ));
					}
					FnArg::Captured(arg)
				},
				r => r.clone(),
			});
		let (impl_generics, ty_generics, where_clause) = decl.generics.split_for_impl();
		// We need to parse them again, to get an easy access to the actual parameters.
		let impl_generics: Generics = parse_quote!( #impl_generics );
		let impl_generics_params = impl_generics.params.iter().map(|p| {
			match p {
				GenericParam::Type(ref ty) => {
					let mut ty = ty.clone();
					ty.bounds.push(parse_quote!( 'a ));
					GenericParam::Type(ty)
				},
				// We should not see anything different than type params here.
				r => r.clone(),
			}
		});
		// Generate the generator function
		result.push(quote!(
			#[cfg(any(feature = "std", test))]
			pub fn #fn_name<
				'a, ApiImpl: #trait_ #ty_generics, NodeBlock: #crate_::runtime_api::BlockT
				#(, #impl_generics_params)*
			>(
				#( #fn_inputs ),*
			) -> impl FnOnce() -> #output + 'a #where_clause {
				move || {
					#( #conversions )*
					let res = ApiImpl::#trait_fn_name(#( #input_borrows #input_names ),*);
					#output_conversion
				}
			}
		));
	}
	Ok(quote!( #( #result )* ))
}
fn generate_native_call_generators ( decl : & ItemTrait ) -> Result < TokenStream > { let fns = decl . items . iter ( ) . filter_map ( | i | match i { TraitItem :: Method ( ref m ) => Some ( & m . sig ) , _ => None , } ) ; let mut result = Vec :: new ( ) ; let trait_ = & decl . ident ; let crate_ = generate_crate_access ( HIDDEN_INCLUDES_ID ) ; // Auxiliary function that is used to convert between types that use different block types. // The function expects that both a convertable by encoding the one and decoding the other. result . push ( quote ! ( [ cfg ( any ( feature " " test ) ) ] fn convert_between_block_types I crate_ runtime_api Encode R crate_ runtime_api Decode ( input I error_desc ' static str ) std result Result R ' static str { R as crate_ runtime_api Decode decode ( mut crate_ runtime_api Encode encode ( input ) [ ] ) ok_or_else ( error_desc ) } ) ) ; // Generate a native call generator for each function of the given trait. for fn_ in fns { let params = extract_parameter_names_types_and_borrows ( & fn_ . decl ) ? ; let trait_fn_name = & fn_ . ident ; let fn_name = generate_native_call_generator_fn_name ( & fn_ . ident ) ; let output = return_type_replace_block_with_node_block ( fn_ . decl . output . clone ( ) ) ; let output_ty = return_type_extract_type ( & output ) ; let output = quote ! ( std result Result output_ty ' static str ) ; // Every type that is using the `Block` generic parameter, we need to encode/decode, // to make it compatible between the runtime/node. let conversions = params . iter ( ) . filter ( | v | type_is_using_block ( & v . 1 ) ) . map ( | ( n , t , _ ) | { let name_str = format ! ( " " quote ( n ) ) ; quote ! ( let n t convert_between_block_types ( n name_str ) ) } ) ; // Same as for the input types, we need to check if we also need to convert the output, // before returning it. let output_conversion = if return_type_is_using_block ( & fn_ . decl . output ) { quote ! ( convert_between_block_types ( res " " ) ) } else { quote ! ( Ok ( res ) ) } ; let input_names = params . iter ( ) . map ( | v | & v . 0 ) ; // If the type is using the block generic type, we will encode/decode it to make it // compatible. To ensure that we forward it by ref/value, we use the value given by the // the user. Otherwise if it is not using the block, we don't need to add anything. let input_borrows = params . iter ( ) . map ( | v | if type_is_using_block ( & v . 1 ) { v . 2 . clone ( ) } else { quote ! ( ) } ) ; // Replace all `Block` with `NodeBlock`, add `'a` lifetime to references and collect // all the function inputs. let fn_inputs = fn_ . decl . inputs . iter ( ) . map ( | v | fn_arg_replace_block_with_node_block ( v . clone ( ) ) ) . map ( | v | match v { FnArg :: Captured ( ref arg ) => { let mut arg = arg . clone ( ) ; if let Type :: Reference ( ref mut r ) = arg . ty { r . lifetime = Some ( parse_quote ! ( ' a ) ) ; } FnArg :: Captured ( arg ) } , r => r . clone ( ) , } ) ; let ( impl_generics , ty_generics , where_clause ) = decl . generics . split_for_impl ( ) ; // We need to parse them again, to get an easy access to the actual parameters. let impl_generics : Generics = parse_quote ! ( impl_generics ) ; let impl_generics_params = impl_generics . params . iter ( ) . map ( | p | { match p { GenericParam :: Type ( ref ty ) => { let mut ty = ty . clone ( ) ; ty . bounds . push ( parse_quote ! ( ' a ) ) ; GenericParam :: Type ( ty ) } , // We should not see anything different than type params here. r => r . clone ( ) , } } ) ; // Generate the generator function result . push ( quote ! ( [ cfg ( any ( feature " " test ) ) ] pub fn fn_name ' a ApiImpl trait_ ty_generics NodeBlock crate_ runtime_api BlockT ( impl_generics_params ) ( ( fn_inputs ) ) impl FnOnce ( ) output ' a where_clause { move { ( conversions ) let res ApiImpl trait_fn_name ( ( input_borrows input_names ) ) output_conversion } } ) ) ; } Ok ( quote ! ( ( result ) ) ) }
Generate the functions that generate the native call closure for each trait method.
Generate the functions that generate the native call closure for each trait method .
decl
&ItemTrait
decl
&ItemTrait