diff --git a/qbittorrent-web-api-gen/src/generate/api_group.rs b/qbittorrent-web-api-gen/src/generate/api_group.rs index 3c73a19..0db717b 100644 --- a/qbittorrent-web-api-gen/src/generate/api_group.rs +++ b/qbittorrent-web-api-gen/src/generate/api_group.rs @@ -6,16 +6,22 @@ use quote::quote; use super::{group_method::GroupMethod, skeleton::auth_ident, util}; #[derive(Debug)] -pub struct GroupGeneration { +pub struct GroupGeneration<'a> { api_group: parser::ApiGroup, - response_derives: Vec, + struct_derives: &'a [&'a str], + enum_derives: &'a [&'a str], } -impl GroupGeneration { - pub fn new(api_group: parser::ApiGroup, response_derives: Vec) -> Self { +impl<'a> GroupGeneration<'a> { + pub fn new( + api_group: parser::ApiGroup, + struct_derives: &'a [&'a str], + enum_derives: &'a [&'a str], + ) -> Self { Self { api_group, - response_derives, + struct_derives, + enum_derives, } } @@ -104,10 +110,18 @@ impl GroupGeneration { self.name_camel() } - pub fn response_derives(&self, additional_derives: Vec<&str>) -> TokenStream { + pub fn struct_derives(&self) -> TokenStream { + self.derives(self.struct_derives, &[]) + } + + pub fn enum_derives(&self) -> TokenStream { + self.derives(self.enum_derives, &["PartialEq", "Eq"]) + } + + pub fn derives(&self, derives: &'a [&'a str], additional_derives: &[&str]) -> TokenStream { let derives = self - .all_derives() - .chain(additional_derives.into_iter()) + .all_derives(derives) + .chain(additional_derives.iter().copied()) .map(|s| syn::parse_str::(s).unwrap()) .map(|derive| quote! { #derive }); @@ -116,12 +130,11 @@ impl GroupGeneration { } } - fn all_derives(&self) -> impl Iterator { + fn all_derives(&self, derives: &'a [&'a str]) -> impl Iterator { let base = vec!["serde::Deserialize", "Debug"].into_iter(); - let additional = self - .response_derives + let additional = derives .iter() - .map(|s| s.as_str()) + .copied() .filter(|item| item != &"serde::Deserialize") .filter(|item| item != &"Debug"); diff --git a/qbittorrent-web-api-gen/src/generate/group.rs b/qbittorrent-web-api-gen/src/generate/group.rs index d26080e..01a5d25 100644 --- a/qbittorrent-web-api-gen/src/generate/group.rs +++ b/qbittorrent-web-api-gen/src/generate/group.rs @@ -5,12 +5,19 @@ use quote::quote; use super::{api_group::GroupGeneration, util}; -pub fn generate_groups(groups: Vec, resp_derives: Vec) -> TokenStream { +pub fn generate_groups( + groups: Vec, + struct_derives: Vec, + enum_derives: Vec, +) -> TokenStream { + let struct_derives_borrowed: Vec<&str> = struct_derives.iter().map(|s| s.as_str()).collect(); + let enum_derive_borrowed: Vec<&str> = enum_derives.iter().map(|s| s.as_str()).collect(); + let gr = groups .into_iter() // implemented manually .filter(|group| group.name != "authentication") - .map(|group| GroupGeneration::new(group, resp_derives.clone())) + .map(|group| GroupGeneration::new(group, &struct_derives_borrowed, &enum_derive_borrowed)) .map(generate_group); quote! { @@ -29,7 +36,7 @@ fn generate_group(group: GroupGeneration) -> TokenStream { #[derive(Debug)] pub struct StructGenerator<'a> { type_: &'a parser::TypeWithName, - group: &'a GroupGeneration, + group: &'a GroupGeneration<'a>, } impl<'a> StructGenerator<'a> { @@ -44,7 +51,7 @@ impl<'a> StructGenerator<'a> { .iter() .map(|obj| obj.generate_struct_field()); let name = util::to_ident(&self.type_.name); - let derives = self.group.response_derives(vec![]); + let derives = self.group.struct_derives(); quote! { #derives @@ -109,7 +116,7 @@ impl types::Type { #[derive(Debug)] pub struct EnumGeneration<'a> { enum_: &'a parser::Enum, - group: &'a GroupGeneration, + group: &'a GroupGeneration<'a>, } impl<'a> EnumGeneration<'a> { @@ -124,7 +131,7 @@ impl<'a> EnumGeneration<'a> { .iter() .map(|enum_value| enum_value.generate()); let name = util::to_ident(&self.enum_.name); - let derives = self.group.response_derives(vec!["PartialEq", "Eq"]); + let derives = self.group.enum_derives(); quote! { #[allow(clippy::enum_variant_names)] diff --git a/qbittorrent-web-api-gen/src/generate/group_method.rs b/qbittorrent-web-api-gen/src/generate/group_method.rs index d7686c6..c8b9461 100644 --- a/qbittorrent-web-api-gen/src/generate/group_method.rs +++ b/qbittorrent-web-api-gen/src/generate/group_method.rs @@ -10,7 +10,7 @@ use super::{ #[derive(Debug)] pub struct GroupMethod<'a> { - group: &'a GroupGeneration, + group: &'a GroupGeneration<'a>, method: &'a parser::ApiMethod, } @@ -116,7 +116,7 @@ impl<'a> GroupMethod<'a> { .iter() .map(|field| field.generate_struct_field()); - let derives = self.group.response_derives(vec![]); + let derives = self.group.struct_derives(); quote! { #derives diff --git a/qbittorrent-web-api-gen/src/generate/mod.rs b/qbittorrent-web-api-gen/src/generate/mod.rs index 4a1273b..a7a091d 100644 --- a/qbittorrent-web-api-gen/src/generate/mod.rs +++ b/qbittorrent-web-api-gen/src/generate/mod.rs @@ -15,13 +15,14 @@ use self::{group::generate_groups, skeleton::generate_skeleton}; pub fn generate(ast: &syn::DeriveInput, api_content: &str) -> TokenStream { let ident = &ast.ident; - let resp_derives = get_response_derives(ast); + let struct_derives = get_derives(ast, "struct_derives"); + let enum_derives = get_derives(ast, "enum_derives"); let token_tree = md_parser::TokenTreeFactory::create(api_content); let api_groups = parser::parse_api_groups(token_tree); let skeleton = generate_skeleton(ident); - let groups = generate_groups(api_groups, resp_derives); + let groups = generate_groups(api_groups, struct_derives, enum_derives); let impl_ident = syn::Ident::new(&format!("{}_impl", ident).to_snake(), ident.span()); quote! { @@ -32,7 +33,7 @@ pub fn generate(ast: &syn::DeriveInput, api_content: &str) -> TokenStream { } } -fn get_response_derives(ast: &syn::DeriveInput) -> Vec { +fn get_derives(ast: &syn::DeriveInput, name: &str) -> Vec { ast.attrs .iter() .find(|attr| { @@ -53,9 +54,18 @@ fn get_response_derives(ast: &syn::DeriveInput) -> Vec { _ => None, }) .filter_map(|value| match value { - syn::Meta::NameValue(name_value) => Some(name_value.lit), + syn::Meta::NameValue(name_value) => Some(name_value), _ => None, }) + .filter(|name_value| { + name_value + .path + .segments + .first() + .map(|seg| seg.ident == name) + .unwrap_or(false) + }) + .map(|name_value| name_value.lit) .filter_map(|lit| match lit { syn::Lit::Str(str) => Some(str.value().split(',').map(|s| s.trim()).collect()), _ => None,