1use heck::ToUpperCamelCase;
2use proc_macro::TokenStream;
3use quote::quote;
4use syn::{
5 Data, DataStruct, DeriveInput, Expr, ExprLit, Lit, Meta, Token, parse_macro_input,
6 punctuated::Punctuated,
7};
8
9trait RequireStrLit {
10 fn require_str_lit(&self) -> syn::Result<String>;
11}
12
13impl RequireStrLit for Expr {
14 fn require_str_lit(&self) -> syn::Result<String> {
15 match self {
16 Expr::Lit(ExprLit {
17 lit: Lit::Str(str), ..
18 }) => Ok(str.value()),
19 _ => Err(syn::Error::new_spanned(self, "expected a string literal")),
20 }
21 }
22}
23
24#[proc_macro_derive(NetworkIncomingBehavior, attributes(behavior))]
25pub fn network_incoming_macro_derive(input: TokenStream) -> TokenStream {
26 let ast = parse_macro_input!(input as DeriveInput);
28 build_incoming(&ast).unwrap_or_else(|e| e.to_compile_error().into())
29}
30
31#[proc_macro_derive(NetworkOutgoingBehavior, attributes(behavior))]
32pub fn network_outgoing_macro_derive(input: TokenStream) -> TokenStream {
33 let ast = parse_macro_input!(input as DeriveInput);
35 build_outgoing(&ast).unwrap_or_else(|e| e.to_compile_error().into())
36}
37
38fn build_incoming(ast: &DeriveInput) -> syn::Result<TokenStream> {
39 match ast.data {
40 Data::Struct(ref s) => build_incoming_struct(ast, s),
42 Data::Enum(_) => Err(syn::Error::new_spanned(
43 ast,
44 "Cannot derive `NetworkIncomingBehavior` on enums",
45 )),
46 Data::Union(_) => Err(syn::Error::new_spanned(
47 ast,
48 "Cannot derive `NetworkIncomingBehavior` on union",
49 )),
50 }
51}
52
53fn build_outgoing(ast: &DeriveInput) -> syn::Result<TokenStream> {
54 match ast.data {
55 Data::Struct(ref s) => build_outgoing_struct(ast, s),
57 Data::Enum(_) => Err(syn::Error::new_spanned(
58 ast,
59 "Cannot derive `NetworkOutgoingBehavior` on enums",
60 )),
61 Data::Union(_) => Err(syn::Error::new_spanned(
62 ast,
63 "Cannot derive `NetworkOutgoingBehavior` on union",
64 )),
65 }
66}
67
68struct PreludeTokenStream {
69 addr: proc_macro2::TokenStream,
70 peer_id: proc_macro2::TokenStream,
71 behavior_event: proc_macro2::TokenStream,
72 listener_event: proc_macro2::TokenStream,
73 connection_id: proc_macro2::TokenStream,
74 connection_denied: proc_macro2::TokenStream,
75 network_behavior_to_impl: proc_macro2::TokenStream,
76 network_incoming_behavior_to_impl: proc_macro2::TokenStream,
77 network_outgoing_behavior_to_impl: proc_macro2::TokenStream,
78 handler_select: proc_macro2::TokenStream,
79 t_handler: proc_macro2::TokenStream,
80 t_handler_event: proc_macro2::TokenStream,
81 t_handler_action: proc_macro2::TokenStream,
82 connection_handler: proc_macro2::TokenStream,
83 either: proc_macro2::TokenStream,
86
87 dial_opts: proc_macro2::TokenStream,
88
89 connection_error: proc_macro2::TokenStream,
91 listen_error: proc_macro2::TokenStream,
92 dial_error: proc_macro2::TokenStream,
93
94 impl_generics: proc_macro2::TokenStream,
95}
96
97struct CommonParsed {
98 prelude: PreludeTokenStream,
99 attributes: BehaviorAttributes,
100}
101
102fn parse_common_token_stream(ast: &DeriveInput) -> syn::Result<CommonParsed> {
103 let attributes = parse_attributes(ast)?;
104 let BehaviorAttributes { prelude_path, .. } = &attributes;
105
106 let impl_generics = {
107 let tp = ast.generics.type_params();
108 let lf = ast.generics.lifetimes();
109 let cst = ast.generics.const_params();
110 quote! {<#(#lf,)* #(#tp,)* #(#cst,)*>}
111 };
112
113 let prelude = PreludeTokenStream {
114 addr: quote! { #prelude_path::Multiaddr },
115 peer_id: quote! { #prelude_path::PeerId },
116 behavior_event: quote! { #prelude_path::BehaviorEvent },
117 listener_event: quote! { #prelude_path::ListenerEvent },
118 connection_id: quote! { #prelude_path::ConnectionId },
119 connection_denied: quote! { #prelude_path::ConnectionDenied },
120 network_behavior_to_impl: quote! { #prelude_path::NetworkBehavior },
121 network_incoming_behavior_to_impl: quote! { #prelude_path::NetworkIncomingBehavior },
122 network_outgoing_behavior_to_impl: quote! { #prelude_path::NetworkOutgoingBehavior },
123 handler_select: quote! { #prelude_path::ConnectionHandlerSelect },
124 t_handler: quote! { #prelude_path::THandler },
125 t_handler_event: quote! { #prelude_path::THandlerEvent },
126 t_handler_action: quote! { #prelude_path::THandlerAction },
127 connection_handler: quote! { #prelude_path::ConnectionHandler },
128 either: quote! { #prelude_path::Either },
131 connection_error: quote! { #prelude_path::ConnectionError },
132 listen_error: quote! { #prelude_path::ListenError },
133 dial_error: quote! { #prelude_path::DialError },
134 dial_opts: quote! { #prelude_path::DialOpts },
135 impl_generics,
136 };
137
138 Ok(CommonParsed {
139 prelude,
140 attributes,
141 })
142}
143
144fn build_event_impl(
145 ast: &DeriveInput,
146 data_struct: &DataStruct,
147 common: &CommonParsed,
148) -> (
149 syn::Type,
150 Option<proc_macro2::TokenStream>,
151 Vec<proc_macro2::TokenStream>,
152) {
153 let CommonParsed {
154 prelude:
155 PreludeTokenStream {
156 network_behavior_to_impl,
157 impl_generics,
158 ..
159 },
160 attributes:
161 BehaviorAttributes {
162 user_specified_out_event,
163 ..
164 },
165 } = common;
166
167 let name = &ast.ident;
169 let (_, ty_generics, where_clause) = ast.generics.split_for_impl();
171
172 match user_specified_out_event {
173 Some(name) => {
174 let definition = None;
175 let from_clauses = data_struct
176 .fields
177 .iter()
178 .map(|field| {
179 let ty = &field.ty;
180 quote! {#name: From< <#ty as #network_behavior_to_impl>::Event >}
181 })
182 .collect::<Vec<_>>();
183 (name.clone(), definition, from_clauses)
184 }
185 None => {
186 let enum_name_str = ast.ident.to_string() + "Event";
187 let enum_name: syn::Type =
188 syn::parse_str(&enum_name_str).expect("ident + `Event` is a valid type");
189 let definition = {
190 let fields = data_struct.fields.iter().map(|field| {
191 let variant: syn::Variant = syn::parse_str(
192 &field
193 .ident
194 .clone()
195 .expect("Fields of NetworkBehaviour implementation to be named.")
196 .to_string()
197 .to_upper_camel_case(),
198 )
199 .expect("uppercased field name to be a valid enum variant");
200 let ty = &field.ty;
201 (variant, ty)
202 });
203
204 let enum_variants = fields.clone().map(
205 |(variant, ty)| quote! {#variant(<#ty as #network_behavior_to_impl>::Event)},
206 );
207
208 let visibility = &ast.vis;
209
210 let additional = fields
211 .clone()
212 .map(|(_variant, tp)| quote! { #tp : #network_behavior_to_impl })
213 .collect::<Vec<_>>();
214
215 let additional_debug = fields
216 .clone()
217 .map(|(_variant, ty)| quote! { <#ty as #network_behavior_to_impl>::Event : ::core::fmt::Debug })
218 .collect::<Vec<_>>();
219
220 let where_clause = {
221 if let Some(where_clause) = where_clause {
222 if where_clause.predicates.trailing_punct() {
223 Some(quote! {#where_clause #(#additional),* })
224 } else {
225 Some(quote! {#where_clause, #(#additional),*})
226 }
227 } else if additional.is_empty() {
228 None
229 } else {
230 Some(quote! {where #(#additional),*})
231 }
232 };
233
234 let where_clause_debug = where_clause
235 .as_ref()
236 .map(|where_clause| quote! {#where_clause, #(#additional_debug),*});
237
238 let match_variants = fields.map(|(variant, _ty)| variant);
239 let msg = format!("`NetworkBehavior::Event` produced by {name}.");
240
241 Some(quote! {
242 #[doc = #msg]
243 #visibility enum #enum_name #impl_generics
244 #where_clause
245 {
246 #(#enum_variants),*
247 }
248
249 impl #impl_generics ::core::fmt::Debug for #enum_name #ty_generics #where_clause_debug {
250 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
251 match &self {
252 #(#enum_name::#match_variants(event) => {
253 write!(f, "{}: {:?}", #enum_name_str, event)
254 }),*
255 }
256 }
257 }
258 })
259 };
260 let from_clauses = vec![];
261 (enum_name, definition, from_clauses)
262 }
263 }
264}
265
266fn where_clause_token(
267 ast: &DeriveInput,
268 data_struct: &DataStruct,
269 out_event_from_clauses: Vec<proc_macro2::TokenStream>,
270 trait_to_impl: &proc_macro2::TokenStream,
271) -> Option<proc_macro2::TokenStream> {
272 let (_, _, where_clause) = ast.generics.split_for_impl();
273
274 let where_clause = {
275 let additional = data_struct
276 .fields
277 .iter()
278 .map(|field| {
279 let ty = &field.ty;
280 quote! {#ty: #trait_to_impl}
281 })
282 .chain(out_event_from_clauses)
283 .collect::<Vec<_>>();
284
285 if let Some(where_clause) = where_clause {
286 if where_clause.predicates.trailing_punct() {
287 Some(quote! {#where_clause #(#additional),* })
288 } else {
289 Some(quote! {#where_clause, #(#additional),*})
290 }
291 } else {
292 Some(quote! {where #(#additional),*})
293 }
294 };
295 where_clause
296}
297
298fn build_network_behavior_impl(
299 ast: &DeriveInput,
300 data_struct: &DataStruct,
301 common_parsed: &CommonParsed,
302) -> (proc_macro2::TokenStream, Vec<proc_macro2::TokenStream>) {
303 let name = &ast.ident;
305 let (_, ty_generics, _) = ast.generics.split_for_impl();
307
308 let (out_event_name, out_event_definition, out_event_from_clauses) =
309 build_event_impl(ast, data_struct, common_parsed);
310
311 let where_clause = where_clause_token(
312 ast,
313 data_struct,
314 out_event_from_clauses.clone(),
315 &common_parsed.prelude.network_behavior_to_impl,
316 );
317
318 let out_event_reference = if out_event_definition.is_some() {
319 quote! { #out_event_name #ty_generics }
320 } else {
321 quote! { #out_event_name }
322 };
323
324 let CommonParsed {
325 prelude:
326 PreludeTokenStream {
327 peer_id,
328 behavior_event,
329 connection_id,
330 network_behavior_to_impl,
331 handler_select,
332 t_handler,
333 t_handler_event,
334 t_handler_action,
335 either,
336 impl_generics,
337 ..
338 },
339 ..
340 } = &common_parsed;
341
342 let connection_handler_ty = {
343 let mut ph_ty = None;
344 for field in data_struct.fields.iter() {
345 let ty = &field.ty;
346 let field_info = quote! { #t_handler<#ty> };
347 match ph_ty {
348 Some(ev) => ph_ty = Some(quote! { #handler_select<#ev, #field_info> }),
349 ref mut ev @ None => *ev = Some(field_info),
350 }
351 }
352 ph_ty.unwrap_or(quote! {()})
353 };
354
355 let on_connection_handler_event_stmts = data_struct.fields.iter().enumerate().enumerate().map(
356 |(enum_n, (field_n, field))| {
357 let mut elem = if enum_n != 0 {
358 quote! { #either::Right(ev) }
359 } else {
360 quote! { ev }
361 };
362
363 for _ in 0..data_struct.fields.len() - 1 - enum_n {
364 elem = quote! { #either::Left(#elem) };
365 }
366
367 Some(match field.ident {
368 Some(ref i) => quote! { #elem => {
369 #network_behavior_to_impl::on_connection_handler_event(&mut self.#i, id, peer_id, ev) }},
370 None => quote! { #elem => {
371 #network_behavior_to_impl::on_connection_handler_event(&mut self.#field_n, id, peer_id, ev) }},
372 })
373 },
374 );
375
376 let poll_stmts = data_struct
377 .fields
378 .iter()
379 .enumerate()
380 .map(|(field_n, field)| {
381 let field = field
382 .ident
383 .clone()
384 .expect("Fields of NetworkBehavior implementation to be named.");
385
386 let mut wrapped_event = if field_n != 0 {
387 quote! { #either::Right(event) }
388 } else {
389 quote! { event }
390 };
391 for _ in 0..data_struct.fields.len() - 1 - field_n {
392 wrapped_event = quote! { #either::Left(#wrapped_event) };
393 }
394
395 let map_event = if out_event_definition.is_some() {
396 let event_variant: syn::Variant =
397 syn::parse_str(&field.to_string().to_upper_camel_case())
398 .expect("field name to be a valid enum variant name");
399 quote! { #out_event_name::#event_variant }
400 } else {
401 quote! { |e| e.into() }
402 };
403
404 let map_handler_action = quote! { |event| #wrapped_event };
405
406 quote! {
407 match #network_behavior_to_impl::poll(&mut self.#field, cx) {
408 std::task::Poll::Ready(e) => return std::task::Poll::Ready(e.map_event(#map_event).map_handler_action(#map_handler_action)),
409 std::task::Poll::Pending => {},
410 }
411 }
412 });
413
414 let final_quote = quote! {
415 #out_event_definition
416 impl #impl_generics #network_behavior_to_impl for #name #ty_generics
417 #where_clause
418 {
419 type ConnectionHandler = #connection_handler_ty;
420 type Event = #out_event_reference;
421
422 fn on_connection_handler_event(
423 &mut self,
424 id: #connection_id,
425 peer_id: #peer_id,
426 event: #t_handler_event<Self>
427 ) {
428 match event {
429 #(#on_connection_handler_event_stmts),*
430 }
431 }
432
433 fn poll(
434 &mut self,
435 cx: &mut std::task::Context<'_>,
436 ) -> std::task::Poll<#behavior_event<Self::Event, #t_handler_action<Self>>> {
437 #(#poll_stmts)*
438 std::task::Poll::Pending
439 }
440
441 }
442 };
443
444 return (final_quote, out_event_from_clauses);
445}
446
447fn build_incoming_struct(ast: &DeriveInput, data_struct: &DataStruct) -> syn::Result<TokenStream> {
448 let common_parsed = parse_common_token_stream(ast)?;
449 let name = &ast.ident;
451 let (_, ty_generics, _) = ast.generics.split_for_impl();
453
454 let (network_behavior_token, out_event_from_clauses) =
455 build_network_behavior_impl(ast, data_struct, &common_parsed);
456
457 let CommonParsed {
458 prelude:
459 PreludeTokenStream {
460 addr,
461 peer_id,
462 listener_event,
463 connection_id,
464 connection_denied,
465 network_incoming_behavior_to_impl,
466 connection_handler,
467 listen_error,
468 connection_error,
469 impl_generics,
470 ..
471 },
472 ..
473 } = &common_parsed;
474
475 let where_clause = where_clause_token(
476 ast,
477 data_struct,
478 out_event_from_clauses,
479 network_incoming_behavior_to_impl,
480 );
481
482 let handle_pending_inbound_connection_stmts =
484 data_struct
485 .fields
486 .iter()
487 .enumerate()
488 .map(|(field_n, field)| {
489 match field.ident {
490 Some(ref i) => quote! {
491 #network_incoming_behavior_to_impl::handle_pending_connection(&mut self.#i, id, local_addr, remote_addr)?;
492 },
493 None => quote! {
494 #network_incoming_behavior_to_impl::handle_pending_connection(&mut self.#field_n, id, local_addr, remote_addr)?;
495 }
496 }
497 });
498
499 let handle_established_inbound_connection = {
500 let mut out_handler = None;
501
502 for (field_n, field) in data_struct.fields.iter().enumerate() {
503 let field_name = match field.ident {
504 Some(ref i) => quote! { self.#i },
505 None => quote! { self.#field_n },
506 };
507
508 let builder = quote! {
509 #field_name.handle_established_connection(id, peer_id, local_addr, remote_addr)?
510 };
511
512 match out_handler {
513 Some(h) => out_handler = Some(quote! { #connection_handler::select(#h, #builder) }),
514 ref mut h @ None => *h = Some(builder),
515 }
516 }
517
518 out_handler.unwrap_or(quote! {()})
519 };
520
521 let on_listen_failure_stmts = data_struct.fields.iter().enumerate().map(
523 |(field_n, field)| {
524 match field.ident {
525 Some(ref i) => quote! {
526 #network_incoming_behavior_to_impl::on_listen_failure(&mut self.#i, id, peer_id, local_addr, remote_addr, error);
527 },
528 None => quote! {
529 #network_incoming_behavior_to_impl::on_listen_failure(&mut self.#field_n, id, peer_id, local_addr, remote_addr, error);
530 },
531 }
532 },
533 );
534
535 let on_connection_established_stmts = data_struct.fields.iter().enumerate().map(
537 |(field_n, field)| {
538 match field.ident {
539 Some(ref i) => quote! {
540 #network_incoming_behavior_to_impl::on_connection_established(&mut self.#i, id, peer_id, local_addr, remote_addr);
541 },
542 None => quote! {
543 #network_incoming_behavior_to_impl::on_connection_established(&mut self.#field_n, id, peer_id, local_addr, remote_addr);
544 },
545 }
546 },
547 );
548
549 let on_connection_closed_stmts = data_struct.fields.iter().enumerate().map(
551 |(field_n, field)| {
552 match field.ident {
553 Some(ref i) => quote! {
554 #network_incoming_behavior_to_impl::on_connection_closed(&mut self.#i, id, peer_id, local_addr, remote_addr, reason);
555 },
556 None => quote! {
557 #network_incoming_behavior_to_impl::on_connection_closed(&mut self.#field_n, id, peer_id, local_addr, remote_addr, reason);
558 },
559 }
560 },
561 );
562
563 let on_listener_event_stmts = {
565 data_struct
566 .fields
567 .iter()
568 .enumerate()
569 .map(|(field_n, field)| match field.ident {
570 Some(ref i) => quote! {
571 self.#i.on_listener_event(event);
572 },
573 None => quote! {
574 self.#field_n.on_listener_event(event);
575 },
576 })
577 };
578
579 let final_quote = quote! {
580 #network_behavior_token
581 impl #impl_generics #network_incoming_behavior_to_impl for #name #ty_generics
582 #where_clause
583 {
584 fn handle_pending_connection(
585 &mut self,
586 id: #connection_id,
587 local_addr: &#addr,
588 remote_addr: &#addr
589 ) -> Result<(), #connection_denied> {
590 #(#handle_pending_inbound_connection_stmts)*
591 Ok(())
592 }
593
594 fn handle_established_connection(
595 &mut self,
596 id: #connection_id,
597 peer_id: #peer_id,
598 local_addr: &#addr,
599 remote_addr: &#addr
600 ) -> Result<Self::ConnectionHandler, #connection_denied> {
601 Ok(#handle_established_inbound_connection)
602 }
603
604 fn on_connection_established(
605 &mut self,
606 id: #connection_id,
607 peer_id: #peer_id,
608 local_addr: &#addr,
609 remote_addr: &#addr,
610 ) {
611 #(#on_connection_established_stmts)*
612 }
613
614 fn on_connection_closed(
615 &mut self,
616 id: #connection_id,
617 peer_id: #peer_id,
618 local_addr: &#addr,
619 remote_addr: &#addr,
620 reason: Option<&#connection_error>,
621 ) {
622 #(#on_connection_closed_stmts)*
623 }
624
625 fn on_listen_failure(
626 &mut self,
627 id: #connection_id,
628 peer_id: Option<#peer_id>,
629 local_addr: &#addr,
630 remote_addr: &#addr,
631 error: &#listen_error,
632 ) {
633 #(#on_listen_failure_stmts)*
634 }
635
636 fn on_listener_event(&mut self, event: #listener_event<'_>) {
637 #(#on_listener_event_stmts)*
638 }
639 }
640
641 };
642
643 return Ok(final_quote.into());
644}
645
646fn build_outgoing_struct(ast: &DeriveInput, data_struct: &DataStruct) -> syn::Result<TokenStream> {
647 let common_parsed = parse_common_token_stream(ast)?;
648 let name = &ast.ident;
650 let (_, ty_generics, _) = ast.generics.split_for_impl();
652
653 let (network_behavior_token, out_event_from_clauses) =
654 build_network_behavior_impl(ast, data_struct, &common_parsed);
655
656 let CommonParsed {
657 prelude:
658 PreludeTokenStream {
659 addr,
660 peer_id,
661 connection_id,
662 connection_denied,
663 network_outgoing_behavior_to_impl,
664 connection_handler,
665 dial_error,
666 connection_error,
667 dial_opts,
668 impl_generics,
669 ..
670 },
671 ..
672 } = &common_parsed;
673
674 let where_clause = where_clause_token(
675 ast,
676 data_struct,
677 out_event_from_clauses,
678 network_outgoing_behavior_to_impl,
679 );
680
681 let handle_pending_outbound_connection = {
682 let extend_stmts =
683 data_struct
684 .fields
685 .iter()
686 .enumerate()
687 .map(|(field_n, field)| {
688 match field.ident {
689 Some(ref i) => quote! {
690 if let Some(addr) = #network_outgoing_behavior_to_impl::handle_pending_connection(&mut self.#i, id, maybe_peer, &maybe_addr)? {
691 maybe_addr = Some(addr);
692 }
693 },
694 None => quote! {
695 if let Some(addr) = #network_outgoing_behavior_to_impl::handle_pending_connection(&mut self.#field_n, id, maybe_peer, &maybe_addr)? {
696 maybe_addr = Some(addr);
697 }
698 }
699 }
700 });
701
702 quote! {
703 let mut maybe_addr = maybe_addr.clone();
704 #(#extend_stmts)*
705 Ok(maybe_addr)
706 }
707 };
708
709 let handle_established_outbound_connection = {
710 let mut out_handler = None;
711
712 for (field_n, field) in data_struct.fields.iter().enumerate() {
713 let field_name = match field.ident {
714 Some(ref i) => quote! { self.#i },
715 None => quote! { self.#field_n },
716 };
717
718 let builder = quote! {
719 #field_name.handle_established_connection(id, peer_id, addr)?
720 };
721
722 match out_handler {
723 Some(h) => out_handler = Some(quote! { #connection_handler::select(#h, #builder) }),
724 ref mut h @ None => *h = Some(builder),
725 }
726 }
727 out_handler.unwrap_or(quote! {()})
728 };
729
730 let on_connection_established_stmts = data_struct.fields.iter().enumerate().map(
732 |(field_n, field)| {
733 match field.ident {
734 Some(ref i) => quote! {
735 #network_outgoing_behavior_to_impl::on_connection_established(&mut self.#i, id, peer_id, addr);
736 },
737 None => quote! {
738 #network_outgoing_behavior_to_impl::on_connection_established(&mut self.#field_n, id, peer_id, addr);
739 },
740 }
741 },
742 );
743
744 let on_connection_closed_stmts = data_struct.fields.iter().enumerate().map(
746 |(field_n, field)| {
747 match field.ident {
748 Some(ref i) => quote! {
749 #network_outgoing_behavior_to_impl::on_connection_closed(&mut self.#i, id, peer_id, addr, reason);
750 },
751 None => quote! {
752 #network_outgoing_behavior_to_impl::on_connection_closed(&mut self.#field_n, id, peer_id, addr, reason);
753 },
754 }
755 },
756 );
757
758 let on_dial_failure_stmts = data_struct.fields.iter().enumerate().map(
760 |(field_n, field)| {
761 match field.ident {
762 Some(ref i) => quote! {
763 #network_outgoing_behavior_to_impl::on_dial_failure(&mut self.#i, id, maybe_peer, maybe_addr, error);
764 },
765 None => quote! {
766 #network_outgoing_behavior_to_impl::on_dial_failure(&mut self.#field_n, id, maybe_peer, maybe_addr, error);
767 },
768 }
769 },
770 );
771
772 let poll_stmts = data_struct.fields.iter().enumerate().map(|(_, field)| {
773 let field = field
774 .ident
775 .clone()
776 .expect("Fields of NetworkBehavior implementation to be named.");
777 quote! {
778 match #network_outgoing_behavior_to_impl::poll_dial(&mut self.#field, cx) {
779 std::task::Poll::Ready(opts) => return std::task::Poll::Ready(opts),
780 std::task::Poll::Pending => {},
781 }
782 }
783 });
784
785 let final_quote = quote! {
786 #network_behavior_token
787 impl #impl_generics #network_outgoing_behavior_to_impl for #name #ty_generics
788 #where_clause
789 {
790 fn handle_pending_connection(
791 &mut self,
792 id: #connection_id,
793 maybe_peer: Option<#peer_id>,
794 maybe_addr: &Option<#addr>,
795 ) -> Result<Option<#addr>, #connection_denied> {
796 #handle_pending_outbound_connection
797 }
798
799 fn handle_established_connection(
800 &mut self,
801 id: #connection_id,
802 peer_id: #peer_id,
803 addr: &#addr,
804 ) -> Result<Self::ConnectionHandler, #connection_denied> {
805 Ok(#handle_established_outbound_connection)
806 }
807
808 fn on_connection_established(
810 &mut self,
811 id: #connection_id,
812 peer_id: #peer_id,
813 addr: &#addr
814 ) {
815 #(#on_connection_established_stmts)*
816 }
817
818 fn on_connection_closed(
819 &mut self,
820 id: #connection_id,
821 peer_id: #peer_id,
822 addr: &#addr,
823 reason: Option<&#connection_error>,
824 ) {
825 #(#on_connection_closed_stmts)*
826 }
827
828 fn on_dial_failure(
829 &mut self,
830 id: #connection_id,
831 maybe_peer: Option<#peer_id>,
832 maybe_addr: Option<&#addr>,
833 error: &#dial_error,
834 ) {
835 #(#on_dial_failure_stmts)*
836 }
837
838 fn poll_dial(&mut self, cx: &mut std::task::Context<'_>) -> std::task::Poll<#dial_opts> {
839 #(#poll_stmts)*
840 std::task::Poll::Pending
841 }
842 }
843 };
844 return Ok(final_quote.into());
845}
846
847struct BehaviorAttributes {
848 prelude_path: syn::Path,
850 user_specified_out_event: Option<syn::Type>,
852}
853
854fn parse_attributes(ast: &DeriveInput) -> syn::Result<BehaviorAttributes> {
856 let mut attributes = BehaviorAttributes {
858 prelude_path: syn::parse_quote! { ::volans::swarm::derive_prelude },
859 user_specified_out_event: None,
860 };
861
862 for attr in ast
864 .attrs
865 .iter()
866 .filter(|attr| attr.path().is_ident("behavior"))
867 {
868 let nested = attr.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?;
870 for meta in nested {
871 if meta.path().is_ident("prelude") {
872 let value = meta.require_name_value()?.value.require_str_lit()?;
873 attributes.prelude_path = syn::parse_str(&value)?;
874 } else if meta.path().is_ident("to_swarm") || meta.path().is_ident("out_event") {
875 let value = meta.require_name_value()?.value.require_str_lit()?;
876 attributes.user_specified_out_event = Some(syn::parse_str(&value)?);
877 }
878 }
879 }
880
881 Ok(attributes)
882}