From 51e8d04c2299e6468213d8ee4f9e15d783094379 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sun, 17 Jul 2022 14:55:41 +0200 Subject: refactor: reorganize and improve macros --- syrette_macros/src/factory_type_alias.rs | 83 ++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 syrette_macros/src/factory_type_alias.rs (limited to 'syrette_macros/src/factory_type_alias.rs') diff --git a/syrette_macros/src/factory_type_alias.rs b/syrette_macros/src/factory_type_alias.rs new file mode 100644 index 0000000..82e2315 --- /dev/null +++ b/syrette_macros/src/factory_type_alias.rs @@ -0,0 +1,83 @@ +use syn::parse::{Parse, ParseStream}; +use syn::{GenericArgument, ItemType, Path, Type, TypeParamBound, TypeTuple}; + +pub struct FactoryTypeAlias +{ + pub type_alias: ItemType, + pub factory_interface: Path, + pub arg_types: TypeTuple, + pub return_type: Type, +} + +impl Parse for FactoryTypeAlias +{ + fn parse(input: ParseStream) -> syn::Result + { + let type_alias = match input.parse::() { + Ok(type_alias) => Ok(type_alias), + Err(_) => Err(input.error("Expected a type alias")), + }?; + + let aliased_trait = match &type_alias.ty.as_ref() { + Type::TraitObject(alias_type) => Ok(alias_type), + &_ => Err(input.error("Expected the aliased type to be a trait")), + }?; + + if aliased_trait.bounds.len() != 1 { + return Err(input.error("Expected the aliased trait to have a single bound.")); + } + + let bound_path = &match aliased_trait.bounds.first().unwrap() { + TypeParamBound::Trait(trait_bound) => Ok(trait_bound), + &_ => { + Err(input.error("Expected the bound of the aliased trait to be a trait")) + } + }? + .path; + + if bound_path.segments.is_empty() + || bound_path.segments.last().unwrap().ident != "IFactory" + { + return Err(input + .error("Expected the bound of the aliased trait to be 'dyn IFactory'")); + } + + let angle_bracketed_args = match &bound_path.segments.last().unwrap().arguments { + syn::PathArguments::AngleBracketed(angle_bracketed_args) => { + Ok(angle_bracketed_args) + } + &_ => { + Err(input.error("Expected angle bracketed arguments for 'dyn IFactory'")) + } + }?; + + let arg_types = match &angle_bracketed_args.args[0] { + GenericArgument::Type(arg_types_type) => match arg_types_type { + Type::Tuple(arg_types) => Ok(arg_types), + &_ => Err(input.error(concat!( + "Expected the first angle bracketed argument ", + "of 'dyn IFactory' to be a type tuple" + ))), + }, + &_ => Err(input.error(concat!( + "Expected the first angle bracketed argument ", + "of 'dyn IFactory' to be a type" + ))), + }?; + + let return_type = match &angle_bracketed_args.args[1] { + GenericArgument::Type(arg_type) => Ok(arg_type), + &_ => Err(input.error(concat!( + "Expected the second angle bracketed argument ", + "of 'dyn IFactory' to be a type" + ))), + }?; + + Ok(Self { + type_alias: type_alias.clone(), + factory_interface: bound_path.clone(), + arg_types: arg_types.clone(), + return_type: return_type.clone(), + }) + } +} -- cgit v1.2.3-18-g5258