diff --git a/.gitignore b/.gitignore
index ea8c4bf..d81f12e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/target
+/.idea
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/activitypub-federation-rust.iml b/.idea/activitypub-federation-rust.iml
deleted file mode 100644
index a7980b4..0000000
--- a/.idea/activitypub-federation-rust.iml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 525db14..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1dd..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index c35dffd..795da91 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6,7 +6,6 @@ version = 3
name = "activitypub_federation"
version = "0.2.3"
dependencies = [
- "activitypub_federation_derive",
"activitystreams-kinds",
"actix-rt",
"actix-web",
@@ -17,6 +16,7 @@ dependencies = [
"chrono",
"derive_builder",
"dyn-clone",
+ "enum_delegate",
"env_logger",
"http",
"http-signature-normalization-actix",
@@ -36,16 +36,6 @@ dependencies = [
"url",
]
-[[package]]
-name = "activitypub_federation_derive"
-version = "0.2.0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "trybuild",
-]
-
[[package]]
name = "activitystreams-kinds"
version = "0.2.1"
@@ -525,12 +515,6 @@ dependencies = [
"crypto-common",
]
-[[package]]
-name = "dissimilar"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c97b9233581d84b8e1e689cdd3a47b6f69770084fc246e86a7f78b0d9c1d4a5"
-
[[package]]
name = "dyn-clone"
version = "1.0.9"
@@ -552,6 +536,30 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "enum_delegate"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8ea75f31022cba043afe037940d73684327e915f88f62478e778c3de914cd0a"
+dependencies = [
+ "enum_delegate_lib",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "enum_delegate_lib"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e1f6c3800b304a6be0012039e2a45a322a093539c45ab818d9e6895a39c90fe"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rand",
+ "syn",
+]
+
[[package]]
name = "env_logger"
version = "0.9.1"
@@ -716,12 +724,6 @@ dependencies = [
"wasi",
]
-[[package]]
-name = "glob"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
-
[[package]]
name = "h2"
version = "0.3.14"
@@ -1572,15 +1574,6 @@ dependencies = [
"winapi",
]
-[[package]]
-name = "termcolor"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
-dependencies = [
- "winapi-util",
-]
-
[[package]]
name = "thiserror"
version = "1.0.37"
@@ -1691,15 +1684,6 @@ dependencies = [
"tracing",
]
-[[package]]
-name = "toml"
-version = "0.5.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
-dependencies = [
- "serde",
-]
-
[[package]]
name = "tower-service"
version = "0.3.2"
@@ -1776,22 +1760,6 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
-[[package]]
-name = "trybuild"
-version = "1.0.65"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e13556ba7dba80b3c76d1331989a341290c77efcf688eca6c307ee3066383dd"
-dependencies = [
- "dissimilar",
- "glob",
- "once_cell",
- "serde",
- "serde_derive",
- "serde_json",
- "termcolor",
- "toml",
-]
-
[[package]]
name = "typenum"
version = "1.15.0"
@@ -1970,15 +1938,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
diff --git a/Cargo.toml b/Cargo.toml
index ef9c771..a353355 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,11 +7,7 @@ license = "AGPL-3.0"
repository = "https://github.com/LemmyNet/activitypub-federation-rust"
documentation = "https://docs.rs/activitypub_federation/"
-[workspace]
-members = ["derive"]
-
[dependencies]
-activitypub_federation_derive = { version = "0.2.0", path = "derive" }
chrono = { version = "0.4.22", features = ["clock"], default-features = false }
serde = { version = "1.0.145", features = ["derive"] }
async-trait = "0.1.57"
@@ -34,6 +30,7 @@ thiserror = "1.0.37"
derive_builder = "0.11.2"
itertools = "0.10.5"
dyn-clone = "1.0.9"
+enum_delegate = "0.2.0"
[dev-dependencies]
activitystreams-kinds = "0.2.1"
diff --git a/derive/Cargo.toml b/derive/Cargo.toml
deleted file mode 100644
index 4d6d8e8..0000000
--- a/derive/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-name = "activitypub_federation_derive"
-version = "0.2.0"
-edition = "2021"
-description = "High-level Activitypub framework"
-license = "AGPL-3.0"
-repository = "https://github.com/LemmyNet/activitypub-federation-rust"
-
-[lib]
-proc-macro = true
-
-[dev-dependencies]
-trybuild = { version = "1.0.63", features = ["diff"] }
-
-[dependencies]
-proc-macro2 = "1.0.39"
-syn = "1.0.96"
-quote = "1.0.18"
diff --git a/derive/src/lib.rs b/derive/src/lib.rs
deleted file mode 100644
index af27264..0000000
--- a/derive/src/lib.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::quote;
-use syn::{parse_macro_input, Data, DeriveInput, Fields::Unnamed, Ident, Variant};
-
-/// Generates implementation ActivityHandler for an enum, which looks like the following (handling
-/// all enum variants).
-///
-/// Based on this code:
-/// ```ignore
-/// #[derive(serde::Deserialize, serde::Serialize)]
-/// #[serde(untagged)]
-/// #[activity_handler(LemmyContext, LemmyError)]
-/// pub enum PersonInboxActivities {
-/// CreateNote(CreateNote),
-/// UpdateNote(UpdateNote),
-/// }
-/// ```
-/// It will generate this:
-/// ```ignore
-/// impl ActivityHandler for PersonInboxActivities {
-/// type DataType = LemmyContext;
-/// type Error = LemmyError;
-///
-/// async fn verify(
-/// &self,
-/// data: &Self::DataType,
-/// request_counter: &mut i32,
-/// ) -> Result<(), Self::Error> {
-/// match self {
-/// PersonInboxActivities::CreateNote(a) => a.verify(data, request_counter).await,
-/// PersonInboxActivities::UpdateNote(a) => a.verify(context, request_counter).await,
-/// }
-/// }
-///
-/// async fn receive(
-/// &self,
-/// data: &Self::DataType,
-/// request_counter: &mut i32,
-/// ) -> Result<(), Self::Error> {
-/// match self {
-/// PersonInboxActivities::CreateNote(a) => a.receive(data, request_counter).await,
-/// PersonInboxActivities::UpdateNote(a) => a.receive(data, request_counter).await,
-/// }
-/// }
-/// ```
-#[proc_macro_attribute]
-pub fn activity_handler(
- attr: proc_macro::TokenStream,
- input: proc_macro::TokenStream,
-) -> proc_macro::TokenStream {
- let derive_input = parse_macro_input!(input as DeriveInput);
- let derive_input2 = derive_input.clone();
- let attr = proc_macro2::TokenStream::from(attr);
- let mut attr = attr.into_iter();
- let data_type = attr.next().expect("data type input");
- let _delimiter = attr.next();
- let error = attr.next().expect("error type input");
-
- let enum_name = derive_input2.ident;
-
- let (impl_generics, ty_generics, where_clause) = derive_input2.generics.split_for_impl();
-
- let enum_variants = if let Data::Enum(d) = derive_input2.data {
- d.variants
- } else {
- unimplemented!()
- };
-
- let impl_id = enum_variants
- .iter()
- .map(|v| generate_match_arm(&enum_name, v, "e! {a.id()}));
- let impl_actor = enum_variants
- .iter()
- .map(|v| generate_match_arm(&enum_name, v, "e! {a.actor()}));
- let body_verify = quote! {a.verify(context, request_counter).await};
- let impl_verify = enum_variants
- .iter()
- .map(|v| generate_match_arm(&enum_name, v, &body_verify));
- let body_receive = quote! {a.receive(context, request_counter).await};
- let impl_receive = enum_variants
- .iter()
- .map(|v| generate_match_arm(&enum_name, v, &body_receive));
-
- let expanded = quote! {
- #derive_input
- #[async_trait::async_trait(?Send)]
- impl #impl_generics activitypub_federation::traits::ActivityHandler for #enum_name #ty_generics #where_clause {
- type DataType = #data_type;
- type Error = #error;
- fn id(
- &self,
- ) -> &Url {
- match self {
- #(#impl_id)*
- }
- }
- fn actor(
- &self,
- ) -> &Url {
- match self {
- #(#impl_actor)*
- }
- }
- async fn verify(
- &self,
- context: &activitypub_federation::data::Data,
- request_counter: &mut i32,
- ) -> Result<(), Self::Error> {
- match self {
- #(#impl_verify)*
- }
- }
- async fn receive(
- self,
- context: &activitypub_federation::data::Data,
- request_counter: &mut i32,
- ) -> Result<(), Self::Error> {
- match self {
- #(#impl_receive)*
- }
- }
- }
- };
- expanded.into()
-}
-
-fn generate_match_arm(enum_name: &Ident, variant: &Variant, body: &TokenStream) -> TokenStream {
- let id = &variant.ident;
- match &variant.fields {
- Unnamed(_) => {
- quote! {
- #enum_name::#id(a) => #body,
- }
- }
- _ => unimplemented!(),
- }
-}
diff --git a/examples/federation/objects/person.rs b/examples/federation/objects/person.rs
index bca0b4b..3213d68 100644
--- a/examples/federation/objects/person.rs
+++ b/examples/federation/objects/person.rs
@@ -11,11 +11,11 @@ use activitypub_federation::{
object_id::ObjectId,
signatures::{Keypair, PublicKey},
},
+ data::Data,
deser::context::WithContext,
traits::{ActivityHandler, Actor, ApubObject},
LocalInstance,
};
-use activitypub_federation_derive::activity_handler;
use activitystreams_kinds::actor::PersonType;
use serde::{Deserialize, Serialize};
use url::Url;
@@ -33,9 +33,9 @@ pub struct MyUser {
}
/// List of all activities which this actor can receive.
-#[activity_handler(InstanceHandle, Error)]
#[derive(Deserialize, Serialize, Debug)]
#[serde(untagged)]
+#[enum_delegate::implement(ActivityHandler)]
pub enum PersonAcceptedActivities {
Follow(Follow),
Accept(Accept),
diff --git a/src/traits.rs b/src/traits.rs
index 42cc00c..dd39d04 100644
--- a/src/traits.rs
+++ b/src/traits.rs
@@ -1,10 +1,11 @@
use crate::data::Data;
-pub use activitypub_federation_derive::*;
use chrono::NaiveDateTime;
+use std::ops::Deref;
use url::Url;
/// Trait which allows verification and reception of incoming activities.
#[async_trait::async_trait(?Send)]
+#[enum_delegate::register]
pub trait ActivityHandler {
type DataType;
type Error;
@@ -32,6 +33,40 @@ pub trait ActivityHandler {
) -> Result<(), Self::Error>;
}
+/// Allow for boxing of enum variants
+#[async_trait::async_trait(?Send)]
+impl ActivityHandler for Box
+where
+ T: ActivityHandler,
+{
+ type DataType = T::DataType;
+ type Error = T::Error;
+
+ fn id(&self) -> &Url {
+ self.deref().id()
+ }
+
+ fn actor(&self) -> &Url {
+ self.deref().actor()
+ }
+
+ async fn verify(
+ &self,
+ data: &Data,
+ request_counter: &mut i32,
+ ) -> Result<(), Self::Error> {
+ self.verify(data, request_counter).await
+ }
+
+ async fn receive(
+ self,
+ data: &Data,
+ request_counter: &mut i32,
+ ) -> Result<(), Self::Error> {
+ self.receive(data, request_counter).await
+ }
+}
+
#[async_trait::async_trait(?Send)]
pub trait ApubObject {
type DataType;