1#![recursion_limit = "256"]
22#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
23
24mod syn_ext;
25
26use crate::syn_ext::RequireStrLit;
27use heck::ToUpperCamelCase;
28use proc_macro::TokenStream;
29use quote::quote;
30use syn::punctuated::Punctuated;
31use syn::spanned::Spanned;
32use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Meta, Token};
33
34#[proc_macro_derive(NetworkBehaviour, attributes(behaviour))]
37pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
38 let ast = parse_macro_input!(input as DeriveInput);
39 build(&ast).unwrap_or_else(|e| e.to_compile_error().into())
40}
41
42fn build(ast: &DeriveInput) -> syn::Result<TokenStream> {
44 match ast.data {
45 Data::Struct(ref s) => build_struct(ast, s),
46 Data::Enum(_) => Err(syn::Error::new_spanned(
47 ast,
48 "Cannot derive `NetworkBehaviour` on enums",
49 )),
50 Data::Union(_) => Err(syn::Error::new_spanned(
51 ast,
52 "Cannot derive `NetworkBehaviour` on union",
53 )),
54 }
55}
56
57fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> syn::Result<TokenStream> {
59 let name = &ast.ident;
60 let (_, ty_generics, where_clause) = ast.generics.split_for_impl();
61 let BehaviourAttributes {
62 prelude_path,
63 user_specified_out_event,
64 deprecation_tokenstream,
65 } = parse_attributes(ast)?;
66
67 let multiaddr = quote! { #prelude_path::Multiaddr };
68 let trait_to_impl = quote! { #prelude_path::NetworkBehaviour };
69 let either_ident = quote! { #prelude_path::Either };
70 let network_behaviour_action = quote! { #prelude_path::ToSwarm };
71 let connection_handler = quote! { #prelude_path::ConnectionHandler };
72 let proto_select_ident = quote! { #prelude_path::ConnectionHandlerSelect };
73 let peer_id = quote! { #prelude_path::PeerId };
74 let connection_id = quote! { #prelude_path::ConnectionId };
75 let poll_parameters = quote! { #prelude_path::PollParameters };
76 let from_swarm = quote! { #prelude_path::FromSwarm };
77 let connection_established = quote! { #prelude_path::ConnectionEstablished };
78 let address_change = quote! { #prelude_path::AddressChange };
79 let connection_closed = quote! { #prelude_path::ConnectionClosed };
80 let dial_failure = quote! { #prelude_path::DialFailure };
81 let listen_failure = quote! { #prelude_path::ListenFailure };
82 let new_listener = quote! { #prelude_path::NewListener };
83 let new_listen_addr = quote! { #prelude_path::NewListenAddr };
84 let expired_listen_addr = quote! { #prelude_path::ExpiredListenAddr };
85 let new_external_addr_candidate = quote! { #prelude_path::NewExternalAddrCandidate };
86 let external_addr_expired = quote! { #prelude_path::ExternalAddrExpired };
87 let external_addr_confirmed = quote! { #prelude_path::ExternalAddrConfirmed };
88 let listener_error = quote! { #prelude_path::ListenerError };
89 let listener_closed = quote! { #prelude_path::ListenerClosed };
90 let t_handler = quote! { #prelude_path::THandler };
91 let t_handler_in_event = quote! { #prelude_path::THandlerInEvent };
92 let t_handler_out_event = quote! { #prelude_path::THandlerOutEvent };
93 let endpoint = quote! { #prelude_path::Endpoint };
94 let connection_denied = quote! { #prelude_path::ConnectionDenied };
95
96 let impl_generics = {
98 let tp = ast.generics.type_params();
99 let lf = ast.generics.lifetimes();
100 let cst = ast.generics.const_params();
101 quote! {<#(#lf,)* #(#tp,)* #(#cst,)*>}
102 };
103
104 let (out_event_name, out_event_definition, out_event_from_clauses) = {
105 match user_specified_out_event {
109 Some(name) => {
111 let definition = None;
112 let from_clauses = data_struct
113 .fields
114 .iter()
115 .map(|field| {
116 let ty = &field.ty;
117 quote! {#name: From< <#ty as #trait_to_impl>::ToSwarm >}
118 })
119 .collect::<Vec<_>>();
120 (name, definition, from_clauses)
121 }
122 None => {
124 let enum_name_str = ast.ident.to_string() + "Event";
125 let enum_name: syn::Type =
126 syn::parse_str(&enum_name_str).expect("ident + `Event` is a valid type");
127 let definition = {
128 let fields = data_struct.fields.iter().map(|field| {
129 let variant: syn::Variant = syn::parse_str(
130 &field
131 .ident
132 .clone()
133 .expect("Fields of NetworkBehaviour implementation to be named.")
134 .to_string()
135 .to_upper_camel_case(),
136 )
137 .expect("uppercased field name to be a valid enum variant");
138 let ty = &field.ty;
139 (variant, ty)
140 });
141
142 let enum_variants = fields
143 .clone()
144 .map(|(variant, ty)| quote! {#variant(<#ty as #trait_to_impl>::ToSwarm)});
145
146 let visibility = &ast.vis;
147
148 let additional = fields
149 .clone()
150 .map(|(_variant, tp)| quote! { #tp : #trait_to_impl })
151 .collect::<Vec<_>>();
152
153 let additional_debug = fields
154 .clone()
155 .map(|(_variant, ty)| quote! { <#ty as #trait_to_impl>::ToSwarm : ::core::fmt::Debug })
156 .collect::<Vec<_>>();
157
158 let where_clause = {
159 if let Some(where_clause) = where_clause {
160 if where_clause.predicates.trailing_punct() {
161 Some(quote! {#where_clause #(#additional),* })
162 } else {
163 Some(quote! {#where_clause, #(#additional),*})
164 }
165 } else if additional.is_empty() {
166 None
167 } else {
168 Some(quote! {where #(#additional),*})
169 }
170 };
171
172 let where_clause_debug = where_clause
173 .as_ref()
174 .map(|where_clause| quote! {#where_clause, #(#additional_debug),*});
175
176 let match_variants = fields.map(|(variant, _ty)| variant);
177 let msg = format!("`NetworkBehaviour::ToSwarm` produced by {name}.");
178
179 Some(quote! {
180 #[doc = #msg]
181 #visibility enum #enum_name #ty_generics
182 #where_clause
183 {
184 #(#enum_variants),*
185 }
186
187 impl #impl_generics ::core::fmt::Debug for #enum_name #ty_generics #where_clause_debug {
188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
189 match &self {
190 #(#enum_name::#match_variants(event) => {
191 write!(f, "{}: {:?}", #enum_name_str, event)
192 }),*
193 }
194 }
195 }
196 })
197 };
198 let from_clauses = vec![];
199 (enum_name, definition, from_clauses)
200 }
201 }
202 };
203
204 let where_clause = {
206 let additional = data_struct
207 .fields
208 .iter()
209 .map(|field| {
210 let ty = &field.ty;
211 quote! {#ty: #trait_to_impl}
212 })
213 .chain(out_event_from_clauses)
214 .collect::<Vec<_>>();
215
216 if let Some(where_clause) = where_clause {
217 if where_clause.predicates.trailing_punct() {
218 Some(quote! {#where_clause #(#additional),* })
219 } else {
220 Some(quote! {#where_clause, #(#additional),*})
221 }
222 } else {
223 Some(quote! {where #(#additional),*})
224 }
225 };
226
227 let on_connection_established_stmts = {
230 data_struct
231 .fields
232 .iter()
233 .enumerate()
234 .map(|(field_n, field)| match field.ident {
235 Some(ref i) => quote! {
236 self.#i.on_swarm_event(#from_swarm::ConnectionEstablished(#connection_established {
237 peer_id,
238 connection_id,
239 endpoint,
240 failed_addresses,
241 other_established,
242 }));
243 },
244 None => quote! {
245 self.#field_n.on_swarm_event(#from_swarm::ConnectionEstablished(#connection_established {
246 peer_id,
247 connection_id,
248 endpoint,
249 failed_addresses,
250 other_established,
251 }));
252 },
253 })
254 };
255
256 let on_address_change_stmts = {
259 data_struct
260 .fields
261 .iter()
262 .enumerate()
263 .map(|(field_n, field)| match field.ident {
264 Some(ref i) => quote! {
265 self.#i.on_swarm_event(#from_swarm::AddressChange(#address_change {
266 peer_id,
267 connection_id,
268 old,
269 new,
270 }));
271 },
272 None => quote! {
273 self.#field_n.on_swarm_event(#from_swarm::AddressChange(#address_change {
274 peer_id,
275 connection_id,
276 old,
277 new,
278 }));
279 },
280 })
281 };
282
283 let on_connection_closed_stmts = {
286 data_struct
287 .fields
288 .iter()
289 .enumerate()
290 .rev()
292 .enumerate()
293 .map(|(enum_n, (field_n, field))| {
294 let handler = if field_n == 0 {
295 quote! { let handler = handlers }
297 } else {
298 quote! {
299 let (handlers, handler) = handlers.into_inner()
300 }
301 };
302 let inject = match field.ident {
303 Some(ref i) => quote! {
304 self.#i.on_swarm_event(#from_swarm::ConnectionClosed(#connection_closed {
305 peer_id,
306 connection_id,
307 endpoint,
308 handler,
309 remaining_established,
310 }));
311 },
312 None => quote! {
313 self.#enum_n.on_swarm_event(#from_swarm::ConnectionClosed(#connection_closed {
314 peer_id,
315 connection_id,
316 endpoint,
317 handler,
318 remaining_established,
319 }));
320 },
321 };
322
323 quote! {
324 #handler;
325 #inject;
326 }
327 })
328 };
329
330 let on_dial_failure_stmts = data_struct
333 .fields
334 .iter()
335 .enumerate()
336 .map(|(enum_n, field)| match field.ident {
337 Some(ref i) => quote! {
338 self.#i.on_swarm_event(#from_swarm::DialFailure(#dial_failure {
339 peer_id,
340 connection_id,
341 error,
342 }));
343 },
344 None => quote! {
345 self.#enum_n.on_swarm_event(#from_swarm::DialFailure(#dial_failure {
346 peer_id,
347 connection_id,
348 error,
349 }));
350 },
351 });
352
353 let on_listen_failure_stmts = data_struct
356 .fields
357 .iter()
358 .enumerate()
359 .map(|(enum_n, field)| match field.ident {
360 Some(ref i) => quote! {
361 self.#i.on_swarm_event(#from_swarm::ListenFailure(#listen_failure {
362 local_addr,
363 send_back_addr,
364 connection_id,
365 error
366 }));
367 },
368 None => quote! {
369 self.#enum_n.on_swarm_event(#from_swarm::ListenFailure(#listen_failure {
370 local_addr,
371 send_back_addr,
372 connection_id,
373 error
374 }));
375 },
376 });
377
378 let on_new_listener_stmts = {
381 data_struct
382 .fields
383 .iter()
384 .enumerate()
385 .map(|(field_n, field)| match field.ident {
386 Some(ref i) => quote! {
387 self.#i.on_swarm_event(#from_swarm::NewListener(#new_listener {
388 listener_id,
389 }));
390 },
391 None => quote! {
392 self.#field_n.on_swarm_event(#from_swarm::NewListener(#new_listener {
393 listener_id,
394 }));
395 },
396 })
397 };
398
399 let on_new_listen_addr_stmts = {
402 data_struct
403 .fields
404 .iter()
405 .enumerate()
406 .map(|(field_n, field)| match field.ident {
407 Some(ref i) => quote! {
408 self.#i.on_swarm_event(#from_swarm::NewListenAddr(#new_listen_addr {
409 listener_id,
410 addr,
411 }));
412 },
413 None => quote! {
414 self.#field_n.on_swarm_event(#from_swarm::NewListenAddr(#new_listen_addr {
415 listener_id,
416 addr,
417 }));
418 },
419 })
420 };
421
422 let on_expired_listen_addr_stmts = {
425 data_struct
426 .fields
427 .iter()
428 .enumerate()
429 .map(|(field_n, field)| match field.ident {
430 Some(ref i) => quote! {
431 self.#i.on_swarm_event(#from_swarm::ExpiredListenAddr(#expired_listen_addr {
432 listener_id,
433 addr,
434 }));
435 },
436 None => quote! {
437 self.#field_n.on_swarm_event(#from_swarm::ExpiredListenAddr(#expired_listen_addr {
438 listener_id,
439 addr,
440 }));
441 },
442 })
443 };
444
445 let on_new_external_addr_candidate_stmts = {
448 data_struct
449 .fields
450 .iter()
451 .enumerate()
452 .map(|(field_n, field)| match field.ident {
453 Some(ref i) => quote! {
454 self.#i.on_swarm_event(#from_swarm::NewExternalAddrCandidate(#new_external_addr_candidate {
455 addr,
456 }));
457 },
458 None => quote! {
459 self.#field_n.on_swarm_event(#from_swarm::NewExternalAddrCandidate(#new_external_addr_candidate {
460 addr,
461 }));
462 },
463 })
464 };
465
466 let on_external_addr_expired_stmts = {
469 data_struct
470 .fields
471 .iter()
472 .enumerate()
473 .map(|(field_n, field)| match field.ident {
474 Some(ref i) => quote! {
475 self.#i.on_swarm_event(#from_swarm::ExternalAddrExpired(#external_addr_expired {
476 addr,
477 }));
478 },
479 None => quote! {
480 self.#field_n.on_swarm_event(#from_swarm::ExternalAddrExpired(#external_addr_expired {
481 addr,
482 }));
483 },
484 })
485 };
486
487 let on_external_addr_confirmed_stmts = {
490 data_struct
491 .fields
492 .iter()
493 .enumerate()
494 .map(|(field_n, field)| match field.ident {
495 Some(ref i) => quote! {
496 self.#i.on_swarm_event(#from_swarm::ExternalAddrConfirmed(#external_addr_confirmed {
497 addr,
498 }));
499 },
500 None => quote! {
501 self.#field_n.on_swarm_event(#from_swarm::ExternalAddrConfirmed(#external_addr_confirmed {
502 addr,
503 }));
504 },
505 })
506 };
507
508 let on_listener_error_stmts = {
511 data_struct
512 .fields
513 .iter()
514 .enumerate()
515 .map(|(field_n, field)| match field.ident {
516 Some(ref i) => quote! {
517 self.#i.on_swarm_event(#from_swarm::ListenerError(#listener_error {
518 listener_id,
519 err,
520 }));
521 },
522 None => quote! {
523 self.#field_n.on_swarm_event(#from_swarm::ListenerError(#listener_error {
524 listener_id,
525 err,
526 }));
527 },
528 })
529 };
530
531 let on_listener_closed_stmts = {
534 data_struct
535 .fields
536 .iter()
537 .enumerate()
538 .map(|(field_n, field)| match field.ident {
539 Some(ref i) => quote! {
540 self.#i.on_swarm_event(#from_swarm::ListenerClosed(#listener_closed {
541 listener_id,
542 reason,
543 }));
544 },
545 None => quote! {
546 self.#field_n.on_swarm_event(#from_swarm::ListenerClosed(#listener_closed {
547 listener_id,
548 reason,
549 }));
550 },
551 })
552 };
553
554 let on_node_event_stmts =
559 data_struct
560 .fields
561 .iter()
562 .enumerate()
563 .enumerate()
564 .map(|(enum_n, (field_n, field))| {
565 let mut elem = if enum_n != 0 {
566 quote! { #either_ident::Right(ev) }
567 } else {
568 quote! { ev }
569 };
570
571 for _ in 0..data_struct.fields.len() - 1 - enum_n {
572 elem = quote! { #either_ident::Left(#elem) };
573 }
574
575 Some(match field.ident {
576 Some(ref i) => quote! { #elem => {
577 #trait_to_impl::on_connection_handler_event(&mut self.#i, peer_id, connection_id, ev) }},
578 None => quote! { #elem => {
579 #trait_to_impl::on_connection_handler_event(&mut self.#field_n, peer_id, connection_id, ev) }},
580 })
581 });
582
583 let connection_handler_ty = {
585 let mut ph_ty = None;
586 for field in data_struct.fields.iter() {
587 let ty = &field.ty;
588 let field_info = quote! { #t_handler<#ty> };
589 match ph_ty {
590 Some(ev) => ph_ty = Some(quote! { #proto_select_ident<#ev, #field_info> }),
591 ref mut ev @ None => *ev = Some(field_info),
592 }
593 }
594 ph_ty.unwrap_or(quote! {()}) };
597
598 let handle_pending_inbound_connection_stmts =
600 data_struct
601 .fields
602 .iter()
603 .enumerate()
604 .map(|(field_n, field)| {
605 match field.ident {
606 Some(ref i) => quote! {
607 #trait_to_impl::handle_pending_inbound_connection(&mut self.#i, connection_id, local_addr, remote_addr)?;
608 },
609 None => quote! {
610 #trait_to_impl::handle_pending_inbound_connection(&mut self.#field_n, connection_id, local_addr, remote_addr)?;
611 }
612 }
613 });
614
615 let handle_established_inbound_connection = {
617 let mut out_handler = None;
618
619 for (field_n, field) in data_struct.fields.iter().enumerate() {
620 let field_name = match field.ident {
621 Some(ref i) => quote! { self.#i },
622 None => quote! { self.#field_n },
623 };
624
625 let builder = quote! {
626 #field_name.handle_established_inbound_connection(connection_id, peer, local_addr, remote_addr)?
627 };
628
629 match out_handler {
630 Some(h) => out_handler = Some(quote! { #connection_handler::select(#h, #builder) }),
631 ref mut h @ None => *h = Some(builder),
632 }
633 }
634
635 out_handler.unwrap_or(quote! {()}) };
637
638 let handle_pending_outbound_connection = {
640 let extend_stmts =
641 data_struct
642 .fields
643 .iter()
644 .enumerate()
645 .map(|(field_n, field)| {
646 match field.ident {
647 Some(ref i) => quote! {
648 combined_addresses.extend(#trait_to_impl::handle_pending_outbound_connection(&mut self.#i, connection_id, maybe_peer, addresses, effective_role)?);
649 },
650 None => quote! {
651 combined_addresses.extend(#trait_to_impl::handle_pending_outbound_connection(&mut self.#field_n, connection_id, maybe_peer, addresses, effective_role)?);
652 }
653 }
654 });
655
656 quote! {
657 let mut combined_addresses = vec![];
658
659 #(#extend_stmts)*
660
661 Ok(combined_addresses)
662 }
663 };
664
665 let handle_established_outbound_connection = {
667 let mut out_handler = None;
668
669 for (field_n, field) in data_struct.fields.iter().enumerate() {
670 let field_name = match field.ident {
671 Some(ref i) => quote! { self.#i },
672 None => quote! { self.#field_n },
673 };
674
675 let builder = quote! {
676 #field_name.handle_established_outbound_connection(connection_id, peer, addr, role_override)?
677 };
678
679 match out_handler {
680 Some(h) => out_handler = Some(quote! { #connection_handler::select(#h, #builder) }),
681 ref mut h @ None => *h = Some(builder),
682 }
683 }
684
685 out_handler.unwrap_or(quote! {()}) };
687
688 let poll_stmts = data_struct.fields.iter().enumerate().map(|(field_n, field)| {
692 let field = field
693 .ident
694 .clone()
695 .expect("Fields of NetworkBehaviour implementation to be named.");
696
697 let mut wrapped_event = if field_n != 0 {
698 quote!{ #either_ident::Right(event) }
699 } else {
700 quote!{ event }
701 };
702 for _ in 0 .. data_struct.fields.len() - 1 - field_n {
703 wrapped_event = quote!{ #either_ident::Left(#wrapped_event) };
704 }
705
706 let generate_event_match_arm = {
707 let into_out_event = if out_event_definition.is_some() {
712 let event_variant: syn::Variant = syn::parse_str(
713 &field
714 .to_string()
715 .to_upper_camel_case()
716 ).expect("uppercased field name to be a valid enum variant name");
717 quote! { #out_event_name::#event_variant(event) }
718 } else {
719 quote! { event.into() }
720 };
721
722 quote! {
723 std::task::Poll::Ready(#network_behaviour_action::GenerateEvent(event)) => {
724 return std::task::Poll::Ready(#network_behaviour_action::GenerateEvent(#into_out_event))
725 }
726 }
727 };
728
729 quote!{
730 match #trait_to_impl::poll(&mut self.#field, cx, poll_params) {
731 #generate_event_match_arm
732 std::task::Poll::Ready(#network_behaviour_action::Dial { opts }) => {
733 return std::task::Poll::Ready(#network_behaviour_action::Dial { opts });
734 }
735 std::task::Poll::Ready(#network_behaviour_action::ListenOn { opts }) => {
736 return std::task::Poll::Ready(#network_behaviour_action::ListenOn { opts });
737 }
738 std::task::Poll::Ready(#network_behaviour_action::RemoveListener { id }) => {
739 return std::task::Poll::Ready(#network_behaviour_action::RemoveListener { id });
740 }
741 std::task::Poll::Ready(#network_behaviour_action::NotifyHandler { peer_id, handler, event }) => {
742 return std::task::Poll::Ready(#network_behaviour_action::NotifyHandler {
743 peer_id,
744 handler,
745 event: #wrapped_event,
746 });
747 }
748 std::task::Poll::Ready(#network_behaviour_action::NewExternalAddrCandidate(addr)) => {
749 return std::task::Poll::Ready(#network_behaviour_action::NewExternalAddrCandidate(addr));
750 }
751 std::task::Poll::Ready(#network_behaviour_action::ExternalAddrConfirmed(addr)) => {
752 return std::task::Poll::Ready(#network_behaviour_action::ExternalAddrConfirmed(addr));
753 }
754 std::task::Poll::Ready(#network_behaviour_action::ExternalAddrExpired(addr)) => {
755 return std::task::Poll::Ready(#network_behaviour_action::ExternalAddrExpired(addr));
756 }
757 std::task::Poll::Ready(#network_behaviour_action::CloseConnection { peer_id, connection }) => {
758 return std::task::Poll::Ready(#network_behaviour_action::CloseConnection { peer_id, connection });
759 }
760 std::task::Poll::Pending => {},
761 }
762 }
763 });
764
765 let out_event_reference = if out_event_definition.is_some() {
766 quote! { #out_event_name #ty_generics }
767 } else {
768 quote! { #out_event_name }
769 };
770
771 let final_quote = quote! {
773 #deprecation_tokenstream
774
775 #out_event_definition
776
777 impl #impl_generics #trait_to_impl for #name #ty_generics
778 #where_clause
779 {
780 type ConnectionHandler = #connection_handler_ty;
781 type ToSwarm = #out_event_reference;
782
783 #[allow(clippy::needless_question_mark)]
784 fn handle_pending_inbound_connection(
785 &mut self,
786 connection_id: #connection_id,
787 local_addr: &#multiaddr,
788 remote_addr: &#multiaddr,
789 ) -> Result<(), #connection_denied> {
790 #(#handle_pending_inbound_connection_stmts)*
791
792 Ok(())
793 }
794
795 #[allow(clippy::needless_question_mark)]
796 fn handle_established_inbound_connection(
797 &mut self,
798 connection_id: #connection_id,
799 peer: #peer_id,
800 local_addr: &#multiaddr,
801 remote_addr: &#multiaddr,
802 ) -> Result<#t_handler<Self>, #connection_denied> {
803 Ok(#handle_established_inbound_connection)
804 }
805
806 #[allow(clippy::needless_question_mark)]
807 fn handle_pending_outbound_connection(
808 &mut self,
809 connection_id: #connection_id,
810 maybe_peer: Option<#peer_id>,
811 addresses: &[#multiaddr],
812 effective_role: #endpoint,
813 ) -> Result<::std::vec::Vec<#multiaddr>, #connection_denied> {
814 #handle_pending_outbound_connection
815 }
816
817 #[allow(clippy::needless_question_mark)]
818 fn handle_established_outbound_connection(
819 &mut self,
820 connection_id: #connection_id,
821 peer: #peer_id,
822 addr: &#multiaddr,
823 role_override: #endpoint,
824 ) -> Result<#t_handler<Self>, #connection_denied> {
825 Ok(#handle_established_outbound_connection)
826 }
827
828 fn on_connection_handler_event(
829 &mut self,
830 peer_id: #peer_id,
831 connection_id: #connection_id,
832 event: #t_handler_out_event<Self>
833 ) {
834 match event {
835 #(#on_node_event_stmts),*
836 }
837 }
838
839 fn poll(&mut self, cx: &mut std::task::Context, poll_params: &mut impl #poll_parameters) -> std::task::Poll<#network_behaviour_action<Self::ToSwarm, #t_handler_in_event<Self>>> {
840 use #prelude_path::futures::*;
841 #(#poll_stmts)*
842 std::task::Poll::Pending
843 }
844
845 fn on_swarm_event(&mut self, event: #from_swarm<Self::ConnectionHandler>) {
846 match event {
847 #from_swarm::ConnectionEstablished(
848 #connection_established { peer_id, connection_id, endpoint, failed_addresses, other_established })
849 => { #(#on_connection_established_stmts)* }
850 #from_swarm::AddressChange(
851 #address_change { peer_id, connection_id, old, new })
852 => { #(#on_address_change_stmts)* }
853 #from_swarm::ConnectionClosed(
854 #connection_closed { peer_id, connection_id, endpoint, handler: handlers, remaining_established })
855 => { #(#on_connection_closed_stmts)* }
856 #from_swarm::DialFailure(
857 #dial_failure { peer_id, connection_id, error })
858 => { #(#on_dial_failure_stmts)* }
859 #from_swarm::ListenFailure(
860 #listen_failure { local_addr, send_back_addr, connection_id, error })
861 => { #(#on_listen_failure_stmts)* }
862 #from_swarm::NewListener(
863 #new_listener { listener_id })
864 => { #(#on_new_listener_stmts)* }
865 #from_swarm::NewListenAddr(
866 #new_listen_addr { listener_id, addr })
867 => { #(#on_new_listen_addr_stmts)* }
868 #from_swarm::ExpiredListenAddr(
869 #expired_listen_addr { listener_id, addr })
870 => { #(#on_expired_listen_addr_stmts)* }
871 #from_swarm::NewExternalAddrCandidate(
872 #new_external_addr_candidate { addr })
873 => { #(#on_new_external_addr_candidate_stmts)* }
874 #from_swarm::ExternalAddrExpired(
875 #external_addr_expired { addr })
876 => { #(#on_external_addr_expired_stmts)* }
877 #from_swarm::ExternalAddrConfirmed(
878 #external_addr_confirmed { addr })
879 => { #(#on_external_addr_confirmed_stmts)* }
880 #from_swarm::ListenerError(
881 #listener_error { listener_id, err })
882 => { #(#on_listener_error_stmts)* }
883 #from_swarm::ListenerClosed(
884 #listener_closed { listener_id, reason })
885 => { #(#on_listener_closed_stmts)* }
886 _ => {}
887 }
888 }
889 }
890 };
891
892 Ok(final_quote.into())
893}
894
895struct BehaviourAttributes {
896 prelude_path: syn::Path,
897 user_specified_out_event: Option<syn::Type>,
898 deprecation_tokenstream: proc_macro2::TokenStream,
899}
900
901fn parse_attributes(ast: &DeriveInput) -> syn::Result<BehaviourAttributes> {
903 let mut attributes = BehaviourAttributes {
904 prelude_path: syn::parse_quote! { ::libp2p::swarm::derive_prelude },
905 user_specified_out_event: None,
906 deprecation_tokenstream: proc_macro2::TokenStream::new(),
907 };
908
909 for attr in ast
910 .attrs
911 .iter()
912 .filter(|attr| attr.path().is_ident("behaviour"))
913 {
914 let nested = attr.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
915
916 for meta in nested {
917 if meta.path().is_ident("prelude") {
918 let value = meta.require_name_value()?.value.require_str_lit()?;
919
920 attributes.prelude_path = syn::parse_str(&value)?;
921
922 continue;
923 }
924
925 if meta.path().is_ident("to_swarm") || meta.path().is_ident("out_event") {
926 if meta.path().is_ident("out_event") {
927 let warning = proc_macro_warning::FormattedWarning::new_deprecated(
928 "out_event_renamed_to_to_swarm",
929 "The `out_event` attribute has been renamed to `to_swarm`.",
930 meta.span(),
931 );
932
933 attributes.deprecation_tokenstream = quote::quote! { #warning };
934 }
935
936 let value = meta.require_name_value()?.value.require_str_lit()?;
937
938 attributes.user_specified_out_event = Some(syn::parse_str(&value)?);
939
940 continue;
941 }
942 }
943 }
944
945 Ok(attributes)
946}