1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Various macro for IC canisters to enable event-based pub/sub
//!
//! Usage:
//! ```
//! // somewhere in your canister
//! implement_event_emitter!();
//! implement_become_event_listener!();
//! implement_stop_being_event_listener!();
//!
//! ...
//!
//! #[derive(Event)]
//! struct Event {
//!     #[topic]
//!     pub a: u64,
//!     pub b: String,
//! }
//!
//! emit(Event {
//!     a: 10,
//!     b: String::from("test")
//! });
//! ```
//!
//! Check the [companion crate](https://crates.io/crates/ic-event-hub) to see how a listener could
//! start receiving events

#![warn(missing_docs)]

use proc_macro::TokenStream;

use crate::derive::event_macro_impl;
use crate::implement::{
    implement_add_event_listeners_impl, implement_become_event_listener_impl,
    implement_event_emitter_impl, implement_get_event_listeners_impl,
    implement_remove_event_listeners_impl, implement_stop_being_event_listener_impl,
};

mod derive;
mod implement;
mod parser;

/// Generates an implementation of `ic_event_hub::types::IEvent` trait for a given struct. Also generates a `*Filter`
/// struct and an implementation of `ic_event_hub::types::IEventFilter` trait for that struct which can be used to filter
/// topics while listening to the given event.
///
/// Fields of the event struct have to implement `candid::CandidType` and `candid::Deserialize`
///
/// Usage:
/// ```
/// #[derive(Event)]
/// struct MyEvent {
///     ...
/// }
/// ```
#[proc_macro_derive(Event, attributes(topic))]
pub fn event_macro_derive(input: TokenStream) -> TokenStream {
    event_macro_impl(input)
}

/// Generates main functionality for event emitting
///
/// * `get_event_hub()` - returns inner state of event-hub
///   * Returns:
///     * an object of type `ic_event_hub::event_hub::EventHub`, containing all the info about listeners and topics
///
///
/// * `emit()` - sends an event message to all subscribed listeners
///   * Params:
///     * `event`: `ic_event_hub::types::IEvent`
#[proc_macro]
pub fn implement_event_emitter(ts: TokenStream) -> TokenStream {
    implement_event_emitter_impl(ts)
}

/// Generates the canister endpoint to manually subscribe new event listeners
/// ```
/// #[ic_cdk_macros::update]
/// fn _add_event_listeners(request: ic_event_hub::types::AddEventListenersRequest) {}
/// ```
///
/// Params:
/// * `guard`: `str` - optional parameter specifying a guarding function which could perform any access-control functionality
#[proc_macro]
pub fn implement_add_event_listeners(ts: TokenStream) -> TokenStream {
    implement_add_event_listeners_impl(ts)
}

/// Generates the canister endpoint to manually unsubscribe previously subscribed listeners
/// ```
/// #[ic_cdk_macros::update]
/// fn _remove_event_listeners(request: ic_event_hub::types::RemoveEventListenersRequest) {}
/// ```
///
/// Params:
/// * `guard`: `str` - optional parameter specifying a guarding function which could perform any access-control functionality
#[proc_macro]
pub fn implement_remove_event_listeners(ts: TokenStream) -> TokenStream {
    implement_remove_event_listeners_impl(ts)
}

/// Generates the canister endpoint for another canister to subscribe to particular topics
/// ```
/// #[ic_cdk_macros::update]
/// fn _become_event_listener(request: ic_event_hub::types::BecomeEventListenerRequest) {}
/// ```
///
/// Params:
/// * `guard`: `str` - optional parameter specifying a guarding function which could perform any access-control functionality
#[proc_macro]
pub fn implement_become_event_listener(ts: TokenStream) -> TokenStream {
    implement_become_event_listener_impl(ts)
}

/// Generates the canister endpoint for another canister to unsubscribe from particular topics
/// ```
/// #[ic_cdk_macros::update]
/// fn _stop_being_event_listener(request: ic_event_hub::types::StopBeingEventListenerRequest) {}
/// ```
///
/// Params:
/// * `guard`: `str` - optional parameter specifying a guarding function which could perform any access-control functionality
#[proc_macro]
pub fn implement_stop_being_event_listener(ts: TokenStream) -> TokenStream {
    implement_stop_being_event_listener_impl(ts)
}

/// Generates the canister endpoint to list all the subscribed listeners
/// ```
/// #[ic_cdk_macros::query]
/// fn _get_event_listeners(
///     request: ic_event_hub::types::GetEventListenersRequest
/// ) -> ic_event_hub::types::GetEventListenersResponse {}
/// ```
///
/// Params:
/// * `guard`: `str` - optional parameter specifying a guarding function which could perform any access-control functionality
#[proc_macro]
pub fn implement_get_event_listeners(ts: TokenStream) -> TokenStream {
    implement_get_event_listeners_impl(ts)
}