diff --git a/examples/chat.rs b/examples/chat.rs index 4ff6af1a..607d2e0e 100644 --- a/examples/chat.rs +++ b/examples/chat.rs @@ -79,13 +79,30 @@ fn main() -> Result<(), Box> { // We create a custom network behaviour that combines floodsub and mDNS. // In the future, we want to improve libp2p to make this easier to do. + // Use the derive to generate delegating NetworkBehaviour impl and require the + // NetworkBehaviourEventProcess implementations below. #[derive(NetworkBehaviour)] struct MyBehaviour { floodsub: Floodsub, mdns: Mdns, + + // Struct fields which do not implement NetworkBehaviour need to be ignored + #[behaviour(ignore)] + #[allow(dead_code)] + ignored_member: bool, + } + + impl NetworkBehaviourEventProcess for MyBehaviour { + // Called when `floodsub` produces an event. + fn inject_event(&mut self, message: FloodsubEvent) { + if let FloodsubEvent::Message(message) = message { + println!("Received: '{:?}' from {:?}", String::from_utf8_lossy(&message.data), message.source); + } + } } impl NetworkBehaviourEventProcess for MyBehaviour { + // Called when `mdns` produces an event. fn inject_event(&mut self, event: MdnsEvent) { match event { MdnsEvent::Discovered(list) => @@ -102,21 +119,13 @@ fn main() -> Result<(), Box> { } } - impl NetworkBehaviourEventProcess for MyBehaviour { - // Called when `floodsub` produces an event. - fn inject_event(&mut self, message: FloodsubEvent) { - if let FloodsubEvent::Message(message) = message { - println!("Received: '{:?}' from {:?}", String::from_utf8_lossy(&message.data), message.source); - } - } - } - // Create a Swarm to manage peers and events let mut swarm = { let mdns = task::block_on(Mdns::new())?; let mut behaviour = MyBehaviour { floodsub: Floodsub::new(local_peer_id.clone()), - mdns + mdns, + ignored_member: false, }; behaviour.floodsub.subscribe(floodsub_topic.clone()); @@ -152,8 +161,8 @@ fn main() -> Result<(), Box> { Poll::Ready(None) => return Poll::Ready(Ok(())), Poll::Pending => { if !listening { - if let Some(a) = Swarm::listeners(&swarm).next() { - println!("Listening on {:?}", a); + for addr in Swarm::listeners(&swarm) { + println!("Listening on {:?}", addr); listening = true; } } diff --git a/misc/core-derive/src/lib.rs b/misc/core-derive/src/lib.rs index fbceef63..8e9fd667 100644 --- a/misc/core-derive/src/lib.rs +++ b/misc/core-derive/src/lib.rs @@ -26,7 +26,8 @@ use quote::quote; use proc_macro::TokenStream; use syn::{parse_macro_input, DeriveInput, Data, DataStruct, Ident}; -/// The interface that satisfies Rust. +/// Generates a delegating `NetworkBehaviour` implementation for the struct this is used for. See +/// the trait documentation for better description. #[proc_macro_derive(NetworkBehaviour, attributes(behaviour))] pub fn hello_macro_derive(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index aca59112..eaec5137 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -26,6 +26,23 @@ use std::{error, task::Context, task::Poll}; /// /// This trait has been designed to be composable. Multiple implementations can be combined into /// one that handles all the behaviours at once. +/// +/// # Deriving `NetworkBehaviour` +/// +/// Crate users can implement this trait by using the the `#[derive(NetworkBehaviour)]` +/// proc macro re-exported by the `libp2p` crate. The macro generates a delegating `trait` +/// implementation for the `struct`, which delegates method calls to all trait members. Any events +/// generated by struct members are delegated to [`NetworkBehaviourEventProcess`] implementations +/// which are expected to be provided by the user. +/// +/// Optionally one can implement a custom `poll` function, which needs to be tagged with the +/// `#[behaviour(poll_method = "poll")]` attribute, and would be called last with no parameters. +/// +/// By default the derive sets the `NetworkBehaviour::OutEvent` as `()` but this can be overriden +/// with `#[behaviour(out_event = "AnotherType")]`. +/// +/// `#[behaviour(ignore)]` can be added on a struct field to disable generation of delegation to +/// the fields which do not implement `NetworkBehaviour`. pub trait NetworkBehaviour { /// Handler for all the protocols the network behaviour supports. type ProtocolsHandler: IntoProtocolsHandler; @@ -163,9 +180,8 @@ pub trait PollParameters { fn local_peer_id(&self) -> &PeerId; } -/// Used when deriving `NetworkBehaviour`. When deriving `NetworkBehaviour`, must be implemented -/// for all the possible event types generated by the various fields. -// TODO: document how the custom behaviour works and link this here +/// When deriving [`NetworkBehaviour`] this trait must be implemented for all the possible event types +/// generated by the inner behaviours. pub trait NetworkBehaviourEventProcess { /// Called when one of the fields of the type you're deriving `NetworkBehaviour` on generates /// an event.