From 8259ed7ccaa921245f34918f42cdd653be64cb54 Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Mon, 16 Dec 2024 13:45:16 +0100 Subject: [PATCH 01/10] impl some macros --- tools/macro-utils/Cargo.toml | 12 +++++ tools/macro-utils/src/field_utils.rs | 75 +++++++++++++++++++++++++++ tools/macro-utils/src/lib.rs | 63 ++++++++++++++++++++++ tools/macro-utils/src/struct_utils.rs | 71 +++++++++++++++++++++++++ 4 files changed, 221 insertions(+) create mode 100644 tools/macro-utils/Cargo.toml create mode 100644 tools/macro-utils/src/field_utils.rs create mode 100644 tools/macro-utils/src/lib.rs create mode 100644 tools/macro-utils/src/struct_utils.rs diff --git a/tools/macro-utils/Cargo.toml b/tools/macro-utils/Cargo.toml new file mode 100644 index 000000000..e7bb8ba77 --- /dev/null +++ b/tools/macro-utils/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "macro_utils" +version = "0.1.0" +edition = "2021" + +[dependencies] +syn = { version = "2.0.87", features = ["derive", "full"] } +quote = "1.0.37" +proc-macro2 = "1.0.89" + +[lib] +proc-macro = true \ No newline at end of file diff --git a/tools/macro-utils/src/field_utils.rs b/tools/macro-utils/src/field_utils.rs new file mode 100644 index 000000000..1c034095a --- /dev/null +++ b/tools/macro-utils/src/field_utils.rs @@ -0,0 +1,75 @@ +use proc_macro::TokenStream; +use quote::{quote, ToTokens}; +use syn::{parse, Data, DeriveInput, Result}; + +pub fn expand(input: TokenStream) -> Result { + let input: DeriveInput = parse(input)?; + let name = &input.ident; + + let expanded = match input.data { + Data::Struct(data_struct) => { + let fields: Vec<_> = data_struct + .fields + .iter() + .filter(|f| { + f.attrs + .iter() + .find(|attr| attr.path().is_ident("skip_field")) + .is_none() + }) + .map(|f| { + let field = f.ident.as_ref().map(|i| i.to_string()).unwrap_or_default(); + let type_str = f.ty.to_token_stream().to_string(); + quote! { + (#field, #type_str) + } + }) + .collect::>(); + quote! { + impl #name { + pub fn fields() -> &'static[(&'static str, &'static str)] { + &[ #(#fields),* ] + } + } + } + } + Data::Enum(data_enum) => { + let variants: Vec<_> = data_enum.variants.into_iter().map(|v| v.ident).collect(); + quote! { + impl #name { + pub fn values() -> &'static[#name] { + &[ #(#name::#variants),* ] + } + } + } + } + Data::Union(data_union) => { + let fields: Vec<_> = data_union + .fields + .named + .iter() + .filter(|f| { + f.attrs + .iter() + .find(|attr| attr.path().is_ident("skip_field")) + .is_none() + }) + .map(|f| { + let field = f.ident.as_ref().map(|i| i.to_string()).unwrap_or_default(); + let type_str = f.ty.to_token_stream().to_string(); + quote! { + (#field, #type_str) + } + }) + .collect::>(); + quote! { + impl #name { + pub fn fields() -> &'static[(&'static str, &'static str)] { + &[ #(#fields),* ] + } + } + } + } + }; + Ok(TokenStream::from(expanded)) +} diff --git a/tools/macro-utils/src/lib.rs b/tools/macro-utils/src/lib.rs new file mode 100644 index 000000000..c412cc7b7 --- /dev/null +++ b/tools/macro-utils/src/lib.rs @@ -0,0 +1,63 @@ +extern crate proc_macro2; + +use proc_macro::TokenStream; + +mod field_utils; +mod struct_utils; + +/// Implements either: +/// #values() -> &'static[#Enum] for enums that returns all defined values in the enum. +/// #fields() -> &'static[(field_name, field_type_definition)] for struct and union types that returns all defined fields. +/// E.g. +/// ``` +/// use macro_utils::VariantExport; +/// #[derive(VariantExport, PartialEq, Debug)] +/// pub enum SomeEnum { +/// SomeValue1, +/// SomeValue2 +/// } +/// +/// assert_eq!([SomeEnum::SomeValue1, SomeEnum::SomeValue2], SomeEnum::values()); +/// +/// #[derive(VariantExport, PartialEq, Debug)] +/// pub struct B; +/// +/// pub struct A { +/// x: i64, +/// y: i128, +/// z: B +/// } +/// +/// assert_eq!([("x", "i64"), ("y", "i128"), ("z", "B")], A::fields()); +/// ``` +#[proc_macro_derive(VariantExport)] +pub fn field_values(input: TokenStream) -> TokenStream { + field_utils::expand(input) + .unwrap_or_else(|e| e.into_compile_error().into()) + .into() +} + +/// Implements a way to fetch all public implemented method for a given struct. +/// It returns a tuple where the first element is the functions name and the second if its async +/// E.g. +/// ``` +/// use macro_utils::impl_funcs; +/// +/// pub struct A; +/// +/// #[impl_funcs(name="get_all_impls")] /// Optional name parameter. If not present will be called functions +/// impl A { +/// fn some_method_a() {} +/// +/// fn some_method_b() {} +/// +/// async fn some_async_method_c() {} +/// } +/// assert_eq!([("some_method_a", false), ("some_method_b", false), ("some_async_method_c", true)], A::get_all_impls()); +/// ``` +#[proc_macro_attribute] +pub fn impl_funcs(attr: TokenStream, input: TokenStream) -> TokenStream { + struct_utils::expand(attr, input) + .unwrap_or_else(|e| e.into_compile_error().into()) + .into() +} \ No newline at end of file diff --git a/tools/macro-utils/src/struct_utils.rs b/tools/macro-utils/src/struct_utils.rs new file mode 100644 index 000000000..8c4ac8547 --- /dev/null +++ b/tools/macro-utils/src/struct_utils.rs @@ -0,0 +1,71 @@ +use proc_macro::TokenStream; +use quote::{format_ident, quote}; +use syn::{ + parse::{Parse, Parser}, + punctuated::Punctuated, + spanned::Spanned, + Error, ImplItem, ItemImpl, Meta, Result, Type, Visibility, +}; + +pub fn expand(attr: TokenStream, input: TokenStream) -> Result { + let attributes = Punctuated::::parse_terminated.parse(attr)?; + let impls: ItemImpl = ItemImpl::parse.parse(input)?; + let ident; + let mut _name = "functions".into(); + if let Type::Path(p) = impls.self_ty.as_ref() { + ident = p.path.get_ident().unwrap(); + } else { + return Err(Error::new(impls.span(), "Only applicable to impl blocks")); + } + for attr in attributes { + if attr.path().is_ident("name") { + if let syn::Meta::NameValue(val) = &attr { + if let syn::Expr::Lit(v) = &val.value { + if let syn::Lit::Str(s) = &v.lit { + _name = s.value(); + } + } + } + } else { + return Err(Error::new( + attr.span(), + format!( + "Unrecognized attribute {:?}", + attr.path() + .get_ident() + .map(|i| i.to_string()) + .unwrap_or_default() + ), + )); + } + } + + let mut functions = vec![]; + for item in impls.items { + if let ImplItem::Fn(function) = item { + if (function + .attrs + .iter() + .find(|attr| attr.path().is_ident("skip"))) + .is_none() + { + let is_async = function.sig.asyncness.is_some(); + if matches!(function.vis, Visibility::Public(_) | Visibility::Inherited) { + let id = function.sig.ident.to_string(); + functions.push(quote! { + (#id, #is_async) + }); + } + } + } + } + let func = format_ident!("{_name}"); + let expanded = quote! { + impl #ident { + pub fn #func() -> &'static[(&'static str, bool)] { + &[ #(#functions),* ] + } + } + }; + Ok(TokenStream::from(expanded)) +} From fddf5475b766b8fd63cc833852c8301f12aa85fa Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Mon, 16 Dec 2024 18:58:08 +0100 Subject: [PATCH 02/10] toml --- Cargo.toml | 1 + warp/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 7f5937428..8aff53781 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,6 +94,7 @@ tracing = { version = "0.1" } either = "1" void = "1" indexmap = { version = "2.4.0", features = ["serde"] } +macro_utils = { path = "./tools/macro-utils" } # ipfs dependency rust-ipfs = "0.14.0" diff --git a/warp/Cargo.toml b/warp/Cargo.toml index 29d2f3b1d..665855bc4 100644 --- a/warp/Cargo.toml +++ b/warp/Cargo.toml @@ -60,6 +60,7 @@ tracing = { workspace = true } mediatype.workspace = true send_wrapper.workspace = true indexmap.workspace = true +macro_utils.workspace = true [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tokio = { workspace = true } From 9db9e7e0723651bac3f88e6ab7b4bfed9d1e71ba Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Mon, 16 Dec 2024 19:41:58 +0100 Subject: [PATCH 03/10] add trait parsing --- tools/macro-utils/src/struct_utils.rs | 86 +++++++++++++++++---------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/tools/macro-utils/src/struct_utils.rs b/tools/macro-utils/src/struct_utils.rs index 8c4ac8547..c67850ddf 100644 --- a/tools/macro-utils/src/struct_utils.rs +++ b/tools/macro-utils/src/struct_utils.rs @@ -1,28 +1,19 @@ use proc_macro::TokenStream; use quote::{format_ident, quote}; use syn::{ - parse::{Parse, Parser}, - punctuated::Punctuated, - spanned::Spanned, - Error, ImplItem, ItemImpl, Meta, Result, Type, Visibility, + parse::{Parse, Parser}, parse_quote, punctuated::Punctuated, spanned::Spanned, Error, ImplItem, ItemImpl, ItemTrait, Meta, Result, TraitItem, Visibility }; pub fn expand(attr: TokenStream, input: TokenStream) -> Result { let attributes = Punctuated::::parse_terminated.parse(attr)?; - let impls: ItemImpl = ItemImpl::parse.parse(input)?; - let ident; - let mut _name = "functions".into(); - if let Type::Path(p) = impls.self_ty.as_ref() { - ident = p.path.get_ident().unwrap(); - } else { - return Err(Error::new(impls.span(), "Only applicable to impl blocks")); - } + let mut name = "functions".into(); + let expanded; for attr in attributes { if attr.path().is_ident("name") { if let syn::Meta::NameValue(val) = &attr { if let syn::Expr::Lit(v) = &val.value { if let syn::Lit::Str(s) = &v.lit { - _name = s.value(); + name = s.value(); } } } @@ -40,17 +31,49 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> Result { } } - let mut functions = vec![]; - for item in impls.items { - if let ImplItem::Fn(function) = item { - if (function - .attrs - .iter() - .find(|attr| attr.path().is_ident("skip"))) - .is_none() - { - let is_async = function.sig.asyncness.is_some(); - if matches!(function.vis, Visibility::Public(_) | Visibility::Inherited) { + if let Ok(mut impls) = ItemImpl::parse.parse(input.clone()) { + // Parse impl block + let mut functions = vec![]; + for item in impls.items.iter() { + if let ImplItem::Fn(function) = item { + if (function + .attrs + .iter() + .find(|attr| attr.path().is_ident("skip"))) + .is_none() + { + let is_async = function.sig.asyncness.is_some(); + if matches!(function.vis, Visibility::Public(_) | Visibility::Inherited) { + let id = function.sig.ident.to_string(); + functions.push(quote! { + (#id, #is_async) + }); + } + } + } + } + let func = format_ident!("{name}"); + impls.items.push(parse_quote! { + fn #func() -> &'static[(&'static str, bool)] { + &[ #(#functions),* ] + } + }); + expanded = quote! { + #impls + }; + } else { + // Parse trait block + let mut trait_impl: ItemTrait = ItemTrait::parse.parse(input)?; + let mut functions = vec![]; + for item in &trait_impl.items { + if let TraitItem::Fn(function) = item { + if (function + .attrs + .iter() + .find(|attr| attr.path().is_ident("skip"))) + .is_none() + { + let is_async = function.sig.asyncness.is_some(); let id = function.sig.ident.to_string(); functions.push(quote! { (#id, #is_async) @@ -58,14 +81,15 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> Result { } } } - } - let func = format_ident!("{_name}"); - let expanded = quote! { - impl #ident { - pub fn #func() -> &'static[(&'static str, bool)] { + let func = format_ident!("{name}"); + trait_impl.items.push(parse_quote! { + fn #func() -> &'static[(&'static str, bool)] { &[ #(#functions),* ] } - } - }; + }); + expanded = quote! { + #trait_impl + }; + } Ok(TokenStream::from(expanded)) } From 3d5cbd3687b9591a6e037d0232626013f6e81e94 Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Mon, 16 Dec 2024 19:56:07 +0100 Subject: [PATCH 04/10] update docs --- tools/macro-utils/src/lib.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tools/macro-utils/src/lib.rs b/tools/macro-utils/src/lib.rs index c412cc7b7..5afcd0e24 100644 --- a/tools/macro-utils/src/lib.rs +++ b/tools/macro-utils/src/lib.rs @@ -19,9 +19,9 @@ mod struct_utils; /// /// assert_eq!([SomeEnum::SomeValue1, SomeEnum::SomeValue2], SomeEnum::values()); /// -/// #[derive(VariantExport, PartialEq, Debug)] /// pub struct B; /// +/// #[derive(VariantExport)] /// pub struct A { /// x: i64, /// y: i128, @@ -37,7 +37,7 @@ pub fn field_values(input: TokenStream) -> TokenStream { .into() } -/// Implements a way to fetch all public implemented method for a given struct. +/// Implements a way to fetch all public implemented method for a given struct or trait. /// It returns a tuple where the first element is the functions name and the second if its async /// E.g. /// ``` @@ -45,6 +45,7 @@ pub fn field_values(input: TokenStream) -> TokenStream { /// /// pub struct A; /// +/// /// For structs /// #[impl_funcs(name="get_all_impls")] /// Optional name parameter. If not present will be called functions /// impl A { /// fn some_method_a() {} @@ -54,6 +55,28 @@ pub fn field_values(input: TokenStream) -> TokenStream { /// async fn some_async_method_c() {} /// } /// assert_eq!([("some_method_a", false), ("some_method_b", false), ("some_async_method_c", true)], A::get_all_impls()); +/// +/// +/// /// For traits +/// #[impl_funcs(name="get_all_impls")] /// Optional name parameter. If not present will be called functions +/// trait SomeTrait { +/// fn some_method_a(); +/// +/// fn some_method_b(); +/// +/// async fn some_async_method_c(); +/// } +/// +/// pub struct B; +/// impl SomeTrait for B { +/// fn some_method_a() {} +/// +/// fn some_method_b() {} +/// +/// async fn some_async_method_c() {} +/// } +/// +/// assert_eq!([("some_method_a", false), ("some_method_b", false), ("some_async_method_c", true)], B::get_all_impls()); /// ``` #[proc_macro_attribute] pub fn impl_funcs(attr: TokenStream, input: TokenStream) -> TokenStream { From c1c2d8b12d32d2218466bb655189ef0da53358b4 Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Mon, 16 Dec 2024 19:56:23 +0100 Subject: [PATCH 05/10] expose fields and funcs for community --- warp/src/raygun/community.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/warp/src/raygun/community.rs b/warp/src/raygun/community.rs index 219470a05..bdbb422d0 100644 --- a/warp/src/raygun/community.rs +++ b/warp/src/raygun/community.rs @@ -4,6 +4,7 @@ use bytes::Bytes; use chrono::{DateTime, Utc}; use futures::stream::BoxStream; use indexmap::{IndexMap, IndexSet}; +use macro_utils::{impl_funcs, VariantExport}; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -21,7 +22,7 @@ pub type CommunityRoles = IndexMap; pub type CommunityPermissions = IndexMap>; pub type CommunityChannelPermissions = IndexMap>; -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq, VariantExport)] pub struct CommunityRole { id: RoleId, name: String, @@ -50,7 +51,7 @@ impl CommunityRole { } } -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq, VariantExport)] pub struct CommunityInvite { id: Uuid, target_user: Option, @@ -86,7 +87,7 @@ impl CommunityInvite { } } -#[derive(Default, Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, Eq, PartialEq, VariantExport)] pub struct Community { id: Uuid, name: String, @@ -171,7 +172,7 @@ impl Community { } } -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq, VariantExport)] pub struct CommunityChannel { id: Uuid, name: String, @@ -229,7 +230,7 @@ impl CommunityChannel { } } -#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, VariantExport)] #[serde(rename_all = "snake_case")] pub enum CommunityChannelType { #[default] @@ -237,7 +238,7 @@ pub enum CommunityChannelType { VoiceEnabled, } -#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, VariantExport)] #[serde(rename_all = "snake_case")] pub enum CommunityPermission { EditName, @@ -269,7 +270,7 @@ pub enum CommunityPermission { PinMessages, } -#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, VariantExport)] #[serde(rename_all = "snake_case")] pub enum CommunityChannelPermission { ViewChannel, @@ -277,6 +278,7 @@ pub enum CommunityChannelPermission { SendAttachments, } +#[impl_funcs(name = "raygun_community_impls")] #[async_trait::async_trait] pub trait RayGunCommunity: Sync + Send { async fn get_community_stream( From 9f8e7e247fc467d772f05ef169ee1a20f1dddb7e Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Wed, 18 Dec 2024 16:31:55 +0100 Subject: [PATCH 06/10] remove field expose macro --- tools/macro-utils/src/field_utils.rs | 75 ---------------------------- tools/macro-utils/src/lib.rs | 33 ------------ 2 files changed, 108 deletions(-) delete mode 100644 tools/macro-utils/src/field_utils.rs diff --git a/tools/macro-utils/src/field_utils.rs b/tools/macro-utils/src/field_utils.rs deleted file mode 100644 index 1c034095a..000000000 --- a/tools/macro-utils/src/field_utils.rs +++ /dev/null @@ -1,75 +0,0 @@ -use proc_macro::TokenStream; -use quote::{quote, ToTokens}; -use syn::{parse, Data, DeriveInput, Result}; - -pub fn expand(input: TokenStream) -> Result { - let input: DeriveInput = parse(input)?; - let name = &input.ident; - - let expanded = match input.data { - Data::Struct(data_struct) => { - let fields: Vec<_> = data_struct - .fields - .iter() - .filter(|f| { - f.attrs - .iter() - .find(|attr| attr.path().is_ident("skip_field")) - .is_none() - }) - .map(|f| { - let field = f.ident.as_ref().map(|i| i.to_string()).unwrap_or_default(); - let type_str = f.ty.to_token_stream().to_string(); - quote! { - (#field, #type_str) - } - }) - .collect::>(); - quote! { - impl #name { - pub fn fields() -> &'static[(&'static str, &'static str)] { - &[ #(#fields),* ] - } - } - } - } - Data::Enum(data_enum) => { - let variants: Vec<_> = data_enum.variants.into_iter().map(|v| v.ident).collect(); - quote! { - impl #name { - pub fn values() -> &'static[#name] { - &[ #(#name::#variants),* ] - } - } - } - } - Data::Union(data_union) => { - let fields: Vec<_> = data_union - .fields - .named - .iter() - .filter(|f| { - f.attrs - .iter() - .find(|attr| attr.path().is_ident("skip_field")) - .is_none() - }) - .map(|f| { - let field = f.ident.as_ref().map(|i| i.to_string()).unwrap_or_default(); - let type_str = f.ty.to_token_stream().to_string(); - quote! { - (#field, #type_str) - } - }) - .collect::>(); - quote! { - impl #name { - pub fn fields() -> &'static[(&'static str, &'static str)] { - &[ #(#fields),* ] - } - } - } - } - }; - Ok(TokenStream::from(expanded)) -} diff --git a/tools/macro-utils/src/lib.rs b/tools/macro-utils/src/lib.rs index 5afcd0e24..4f6551bf3 100644 --- a/tools/macro-utils/src/lib.rs +++ b/tools/macro-utils/src/lib.rs @@ -2,41 +2,8 @@ extern crate proc_macro2; use proc_macro::TokenStream; -mod field_utils; mod struct_utils; -/// Implements either: -/// #values() -> &'static[#Enum] for enums that returns all defined values in the enum. -/// #fields() -> &'static[(field_name, field_type_definition)] for struct and union types that returns all defined fields. -/// E.g. -/// ``` -/// use macro_utils::VariantExport; -/// #[derive(VariantExport, PartialEq, Debug)] -/// pub enum SomeEnum { -/// SomeValue1, -/// SomeValue2 -/// } -/// -/// assert_eq!([SomeEnum::SomeValue1, SomeEnum::SomeValue2], SomeEnum::values()); -/// -/// pub struct B; -/// -/// #[derive(VariantExport)] -/// pub struct A { -/// x: i64, -/// y: i128, -/// z: B -/// } -/// -/// assert_eq!([("x", "i64"), ("y", "i128"), ("z", "B")], A::fields()); -/// ``` -#[proc_macro_derive(VariantExport)] -pub fn field_values(input: TokenStream) -> TokenStream { - field_utils::expand(input) - .unwrap_or_else(|e| e.into_compile_error().into()) - .into() -} - /// Implements a way to fetch all public implemented method for a given struct or trait. /// It returns a tuple where the first element is the functions name and the second if its async /// E.g. From 58b5c3a0f3c8f93f5c3d451bf03d7a30ac10212c Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Fri, 20 Dec 2024 12:49:26 +0100 Subject: [PATCH 07/10] expose trait funcs --- warp/src/constellation/mod.rs | 1 + warp/src/multipass/mod.rs | 6 ++++++ warp/src/raygun/group.rs | 3 +++ warp/src/raygun/mod.rs | 5 +++++ 4 files changed, 15 insertions(+) diff --git a/warp/src/constellation/mod.rs b/warp/src/constellation/mod.rs index abfb7aac1..1af09f6f5 100644 --- a/warp/src/constellation/mod.rs +++ b/warp/src/constellation/mod.rs @@ -82,6 +82,7 @@ pub type ConstellationProgressStream = BoxStream<'static, Progression>; /// Interface that would provide functionality around the filesystem. #[async_trait::async_trait] +#[impl_funcs(name = "constellation_impls")] pub trait Constellation: ConstellationEvent + Extension + Sync + Send + SingleHandle { /// Provides the timestamp of when the file system was modified fn modified(&self) -> DateTime; diff --git a/warp/src/multipass/mod.rs b/warp/src/multipass/mod.rs index 36c021571..e5662c62e 100644 --- a/warp/src/multipass/mod.rs +++ b/warp/src/multipass/mod.rs @@ -69,6 +69,7 @@ pub enum IdentityImportOption<'a> { pub type MultiPassEventStream = BoxStream<'static, MultiPassEventKind>; #[async_trait::async_trait] +#[impl_funcs(name = "multipass_impls")] pub trait MultiPass: Extension + IdentityInformation @@ -92,6 +93,7 @@ pub trait MultiPass: } #[async_trait::async_trait] +#[impl_funcs(name = "multipass_local_id_impls")] pub trait LocalIdentity: Sync + Send { /// Reference to the local [`Identity`] async fn identity(&self) -> Result; @@ -109,6 +111,7 @@ pub trait LocalIdentity: Sync + Send { } #[async_trait::async_trait] +#[impl_funcs(name = "multipass_im_export_impls")] pub trait MultiPassImportExport: Sync + Send { /// Import identity from a specific location async fn import_identity<'a>( @@ -125,6 +128,7 @@ pub trait MultiPassImportExport: Sync + Send { } #[async_trait::async_trait] +#[impl_funcs(name = "multipass_friends_impls")] pub trait Friends: Sync + Send { /// Send friend request to corresponding public key async fn send_request(&mut self, _: &DID) -> Result<(), Error> { @@ -203,6 +207,7 @@ pub trait Friends: Sync + Send { } #[async_trait::async_trait] +#[impl_funcs(name = "multipass_event_impls")] pub trait MultiPassEvent: Sync + Send { /// Subscribe to an stream of events async fn multipass_subscribe(&mut self) -> Result { @@ -211,6 +216,7 @@ pub trait MultiPassEvent: Sync + Send { } #[async_trait::async_trait] +#[impl_funcs(name = "multipass_identity_impls")] pub trait IdentityInformation: Send + Sync { /// Profile picture belonging to the `Identity` async fn identity_picture(&self, _: &DID) -> Result { diff --git a/warp/src/raygun/group.rs b/warp/src/raygun/group.rs index 2e7b15cdd..67ad5f8b1 100644 --- a/warp/src/raygun/group.rs +++ b/warp/src/raygun/group.rs @@ -154,6 +154,7 @@ impl GroupInvitation { } // General/Base GroupChat Trait +#[impl_funcs(name = "raygun_group_chat_impls")] pub trait GroupChat: GroupInvite + GroupChatManagement { /// Join a existing group fn join_group(&mut self, _: Uuid) -> Result<(), Error> { @@ -172,6 +173,7 @@ pub trait GroupChat: GroupInvite + GroupChatManagement { } // Group Invite Management Trait +#[impl_funcs(name = "raygun_group_invite_impls")] pub trait GroupInvite { /// Sends a invite to join a group fn send_invite(&mut self, _: Uuid, _: DID) -> Result<(), Error> { @@ -195,6 +197,7 @@ pub trait GroupInvite { } // Group Admin Management Trait +#[impl_funcs(name = "raygun_group_management_impls")] pub trait GroupChatManagement { /// Create a group fn create_group(&mut self, _: &str) -> Result { diff --git a/warp/src/raygun/mod.rs b/warp/src/raygun/mod.rs index c0f7f0994..cd5463f79 100644 --- a/warp/src/raygun/mod.rs +++ b/warp/src/raygun/mod.rs @@ -1400,6 +1400,7 @@ impl PartialEq for Location { impl Eq for Location {} #[async_trait::async_trait] +#[impl_funcs(name = "raygun_impls")] pub trait RayGun: RayGunStream + RayGunGroupConversation @@ -1587,6 +1588,7 @@ pub trait RayGunGroupConversation: Sync + Send { } #[async_trait::async_trait] +#[impl_funcs(name = "raygun_attachment_impls")] pub trait RayGunAttachment: Sync + Send { /// Send files to a conversation. /// If no files is provided in the array, it will throw an error @@ -1625,6 +1627,7 @@ pub trait RayGunAttachment: Sync + Send { } #[async_trait::async_trait] +#[impl_funcs(name = "raygun_stream_impls")] pub trait RayGunStream: Sync + Send { /// Subscribe to an stream of events from the conversation async fn get_conversation_stream(&mut self, _: Uuid) -> Result { @@ -1638,6 +1641,7 @@ pub trait RayGunStream: Sync + Send { } #[async_trait::async_trait] +#[impl_funcs(name = "raygun_events_impls")] pub trait RayGunEvents: Sync + Send { /// Send an event to a conversation async fn send_event(&mut self, _: Uuid, _: MessageEvent) -> Result<(), Error> { @@ -1651,6 +1655,7 @@ pub trait RayGunEvents: Sync + Send { } #[async_trait::async_trait] +#[impl_funcs(name = "raygun_conversations_impls")] pub trait RayGunConversationInformation: Sync + Send { /// Set a description to a conversation async fn set_conversation_description( From 24087b50663eb977bbbaf3218ec2a0abd33c9be0 Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Fri, 20 Dec 2024 12:58:35 +0100 Subject: [PATCH 08/10] fix missing impl --- warp/src/constellation/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/warp/src/constellation/mod.rs b/warp/src/constellation/mod.rs index 1af09f6f5..dfd775e30 100644 --- a/warp/src/constellation/mod.rs +++ b/warp/src/constellation/mod.rs @@ -219,6 +219,7 @@ pub trait Constellation: ConstellationEvent + Extension + Sync + Send + SingleHa } #[async_trait::async_trait] +#[impl_funcs(name = "constellation_event_impls")] pub trait ConstellationEvent: Sync + Send { /// Subscribe to an stream of events async fn constellation_subscribe(&mut self) -> Result { From 1467e93ae5f8440482707844306de171f1ca06cc Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Fri, 20 Dec 2024 13:16:08 +0100 Subject: [PATCH 09/10] clippy and linter --- tools/macro-utils/src/lib.rs | 30 +++++++++++++-------------- tools/macro-utils/src/struct_utils.rs | 16 +++++++------- warp/src/constellation/mod.rs | 1 + warp/src/multipass/mod.rs | 1 + warp/src/raygun/community.rs | 16 +++++++------- warp/src/raygun/group.rs | 1 + warp/src/raygun/mod.rs | 1 + 7 files changed, 35 insertions(+), 31 deletions(-) diff --git a/tools/macro-utils/src/lib.rs b/tools/macro-utils/src/lib.rs index 4f6551bf3..03bb7143b 100644 --- a/tools/macro-utils/src/lib.rs +++ b/tools/macro-utils/src/lib.rs @@ -9,45 +9,43 @@ mod struct_utils; /// E.g. /// ``` /// use macro_utils::impl_funcs; -/// +/// /// pub struct A; -/// +/// /// /// For structs /// #[impl_funcs(name="get_all_impls")] /// Optional name parameter. If not present will be called functions /// impl A { /// fn some_method_a() {} -/// +/// /// fn some_method_b() {} -/// +/// /// async fn some_async_method_c() {} /// } /// assert_eq!([("some_method_a", false), ("some_method_b", false), ("some_async_method_c", true)], A::get_all_impls()); -/// -/// +/// +/// /// /// For traits /// #[impl_funcs(name="get_all_impls")] /// Optional name parameter. If not present will be called functions /// trait SomeTrait { /// fn some_method_a(); -/// +/// /// fn some_method_b(); -/// +/// /// async fn some_async_method_c(); /// } -/// +/// /// pub struct B; /// impl SomeTrait for B { /// fn some_method_a() {} -/// +/// /// fn some_method_b() {} -/// +/// /// async fn some_async_method_c() {} /// } -/// +/// /// assert_eq!([("some_method_a", false), ("some_method_b", false), ("some_async_method_c", true)], B::get_all_impls()); /// ``` #[proc_macro_attribute] pub fn impl_funcs(attr: TokenStream, input: TokenStream) -> TokenStream { - struct_utils::expand(attr, input) - .unwrap_or_else(|e| e.into_compile_error().into()) - .into() -} \ No newline at end of file + struct_utils::expand(attr, input).unwrap_or_else(|e| e.into_compile_error().into()) +} diff --git a/tools/macro-utils/src/struct_utils.rs b/tools/macro-utils/src/struct_utils.rs index c67850ddf..980c6bc6f 100644 --- a/tools/macro-utils/src/struct_utils.rs +++ b/tools/macro-utils/src/struct_utils.rs @@ -1,7 +1,11 @@ use proc_macro::TokenStream; use quote::{format_ident, quote}; use syn::{ - parse::{Parse, Parser}, parse_quote, punctuated::Punctuated, spanned::Spanned, Error, ImplItem, ItemImpl, ItemTrait, Meta, Result, TraitItem, Visibility + parse::{Parse, Parser}, + parse_quote, + punctuated::Punctuated, + spanned::Spanned, + Error, ImplItem, ItemImpl, ItemTrait, Meta, Result, TraitItem, Visibility, }; pub fn expand(attr: TokenStream, input: TokenStream) -> Result { @@ -36,11 +40,10 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> Result { let mut functions = vec![]; for item in impls.items.iter() { if let ImplItem::Fn(function) = item { - if (function + if function .attrs .iter() - .find(|attr| attr.path().is_ident("skip"))) - .is_none() + .any(|attr| attr.path().is_ident("skip")) { let is_async = function.sig.asyncness.is_some(); if matches!(function.vis, Visibility::Public(_) | Visibility::Inherited) { @@ -67,11 +70,10 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> Result { let mut functions = vec![]; for item in &trait_impl.items { if let TraitItem::Fn(function) = item { - if (function + if function .attrs .iter() - .find(|attr| attr.path().is_ident("skip"))) - .is_none() + .any(|attr| attr.path().is_ident("skip")) { let is_async = function.sig.asyncness.is_some(); let id = function.sig.ident.to_string(); diff --git a/warp/src/constellation/mod.rs b/warp/src/constellation/mod.rs index dfd775e30..1be6e68bb 100644 --- a/warp/src/constellation/mod.rs +++ b/warp/src/constellation/mod.rs @@ -14,6 +14,7 @@ use chrono::{DateTime, Utc}; use directory::Directory; use futures::stream::BoxStream; use futures::Stream; +use macro_utils::impl_funcs; #[derive(Debug, Clone)] pub enum ConstellationEventKind { diff --git a/warp/src/multipass/mod.rs b/warp/src/multipass/mod.rs index e5662c62e..6a02c962c 100644 --- a/warp/src/multipass/mod.rs +++ b/warp/src/multipass/mod.rs @@ -3,6 +3,7 @@ use chrono::{DateTime, Utc}; use futures::stream::BoxStream; use futures::{Stream, StreamExt}; +use macro_utils::impl_funcs; use serde::{Deserialize, Serialize}; use std::future::Future; use std::path::PathBuf; diff --git a/warp/src/raygun/community.rs b/warp/src/raygun/community.rs index bdbb422d0..c1bc9e92b 100644 --- a/warp/src/raygun/community.rs +++ b/warp/src/raygun/community.rs @@ -4,7 +4,7 @@ use bytes::Bytes; use chrono::{DateTime, Utc}; use futures::stream::BoxStream; use indexmap::{IndexMap, IndexSet}; -use macro_utils::{impl_funcs, VariantExport}; +use macro_utils::impl_funcs; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -22,7 +22,7 @@ pub type CommunityRoles = IndexMap; pub type CommunityPermissions = IndexMap>; pub type CommunityChannelPermissions = IndexMap>; -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq, VariantExport)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct CommunityRole { id: RoleId, name: String, @@ -51,7 +51,7 @@ impl CommunityRole { } } -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq, VariantExport)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct CommunityInvite { id: Uuid, target_user: Option, @@ -87,7 +87,7 @@ impl CommunityInvite { } } -#[derive(Default, Debug, Clone, Serialize, Deserialize, Eq, PartialEq, VariantExport)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] pub struct Community { id: Uuid, name: String, @@ -172,7 +172,7 @@ impl Community { } } -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq, VariantExport)] +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct CommunityChannel { id: Uuid, name: String, @@ -230,7 +230,7 @@ impl CommunityChannel { } } -#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, VariantExport)] +#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum CommunityChannelType { #[default] @@ -238,7 +238,7 @@ pub enum CommunityChannelType { VoiceEnabled, } -#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, VariantExport)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(rename_all = "snake_case")] pub enum CommunityPermission { EditName, @@ -270,7 +270,7 @@ pub enum CommunityPermission { PinMessages, } -#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, VariantExport)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(rename_all = "snake_case")] pub enum CommunityChannelPermission { ViewChannel, diff --git a/warp/src/raygun/group.rs b/warp/src/raygun/group.rs index 67ad5f8b1..d905af808 100644 --- a/warp/src/raygun/group.rs +++ b/warp/src/raygun/group.rs @@ -1,6 +1,7 @@ #![allow(clippy::result_large_err)] use crate::crypto::DID; use crate::error::Error; +use macro_utils::impl_funcs; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use uuid::Uuid; diff --git a/warp/src/raygun/mod.rs b/warp/src/raygun/mod.rs index cd5463f79..cad7a9bc5 100644 --- a/warp/src/raygun/mod.rs +++ b/warp/src/raygun/mod.rs @@ -19,6 +19,7 @@ use bytes::Bytes; use chrono::{DateTime, Utc}; use core::ops::Range; use indexmap::{IndexMap, IndexSet}; +use macro_utils::impl_funcs; use serde::{Deserialize, Serialize}; use std::collections::{BTreeSet, HashSet}; use std::fmt::Debug; From 9d0e07e7831063133ce51e4ca1d9d2527581810f Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Fri, 20 Dec 2024 18:06:47 +0100 Subject: [PATCH 10/10] fix inverted check --- tools/macro-utils/src/struct_utils.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/macro-utils/src/struct_utils.rs b/tools/macro-utils/src/struct_utils.rs index 980c6bc6f..23db93b12 100644 --- a/tools/macro-utils/src/struct_utils.rs +++ b/tools/macro-utils/src/struct_utils.rs @@ -40,7 +40,7 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> Result { let mut functions = vec![]; for item in impls.items.iter() { if let ImplItem::Fn(function) = item { - if function + if !function .attrs .iter() .any(|attr| attr.path().is_ident("skip")) @@ -70,7 +70,7 @@ pub fn expand(attr: TokenStream, input: TokenStream) -> Result { let mut functions = vec![]; for item in &trait_impl.items { if let TraitItem::Fn(function) = item { - if function + if !function .attrs .iter() .any(|attr| attr.path().is_ident("skip"))