pub(crate) fn generate_reactor_impl(def: &ReactorDefinition) -> TokenStream {
    let reactor_ident = def.reactor_ident();
    let event_ident = def.event_ident();
    let error_ident = def.error_ident();
    let config = def.config_type().as_given();

    let mut dispatches = Vec::new();

    // Generate dispatches for component events.
    for component in def.components() {
        let variant_ident = component.variant_ident();
        let full_component_type = component.full_component_type();
        let field_ident = component.field_ident();

        dispatches.push(quote!(
            #event_ident::#variant_ident(event) => {
                crate::reactor::wrap_effects(
                    #event_ident::#variant_ident,
                    <#full_component_type as crate::components::Component<#event_ident>>::handle_event(&mut self.#field_ident, effect_builder, rng, event)
                )
            },
        ));
    }

    // Dispatch requests as well.
    for request in def.requests() {
        let request_variant_ident = request.variant_ident();

        match request.target() {
            Target::Discard => {
                dispatches.push(quote!(
                    #event_ident::#request_variant_ident(request) => {
                        // Request is discarded.
                        // TODO: Add `trace!` call here? Consider the log spam though.
                        Default::default()
                    },
                ));
            }
            Target::Panic => {
                dispatches.push(quote!(
                    #event_ident::#request_variant_ident(request) => {
                        // Request is discarded.
                        panic!("received event that was explicitly routed to a panic: {:?}", request)
                    },
                ));
            }
            Target::Dest(ref dest) => {
                let dest_component_type = def.component(dest).full_component_type();
                let dest_variant_ident = def.component(dest).variant_ident();
                let dest_field_ident = dest;

                dispatches.push(quote!(
                            #event_ident::#request_variant_ident(request) => {
                                // Turn request into event for target component.
                                let dest_event = <#dest_component_type as crate::components::Component<Self::Event>>::Event::from(request);

                                // Route the newly created event to the component.
                                crate::reactor::wrap_effects(
                                    #event_ident::#dest_variant_ident,
                                    <#dest_component_type as crate::components::Component<Self::Event>>::handle_event(&mut self.#dest_field_ident, effect_builder, rng, dest_event)
                                )
                            },
                        ));
            }
            Target::Dispatch(ref fname) => {
                dispatches.push(quote!(
                    #event_ident::#request_variant_ident(request) => {
                        self.#fname(effect_builder, rng, request)
                    },
                ));
            }
        }
    }

    // Announcements dispatched also.
    for announcement in def.announcements() {
        let announcement_variant_ident = announcement.variant_ident();

        let mut announcement_dispatches = Vec::new();
        for target in announcement.targets() {
            match target {
                Target::Discard => {
                    // Don't do anything.
                    // TODO: Add `trace!` call here? Consider the log spam though.
                }
                Target::Panic => {
                    announcement_dispatches.push(quote!(
                        panic!("announcement received that was expressively declared as panic: {:?}",
                               announcement);
                    ));
                }
                Target::Dest(ref dest) => {
                    let dest_component_type = def.component(dest).full_component_type();
                    let dest_variant_ident = def.component(dest).variant_ident();
                    let dest_field_ident = dest;

                    announcement_dispatches.push(quote!(
                        // Dispatch announcement to target:
                        let dest_event = <#dest_component_type as crate::components::Component<Self::Event>>::Event::from(announcement);

                        let effects = crate::reactor::wrap_effects(
                            #event_ident::#dest_variant_ident,
                            <#dest_component_type as crate::components::Component<Self::Event>>::handle_event(&mut self.#dest_field_ident, effect_builder, rng, dest_event)
                        );

                        announcement_effects.extend(effects.into_iter());
                    ));
                }
                Target::Dispatch(ref fname) => {
                    announcement_dispatches.push(quote!(
                        let effects = self.#fname(effect_builder, rng, announcement);

                        announcement_effects.extend(effects.into_iter());
                    ));
                }
            }
        }

        dispatches.push(quote!(
            #event_ident::#announcement_variant_ident(announcement) => {
                let mut announcement_effects = crate::effect::Multiple::new();

                #(#announcement_dispatches)*

                announcement_effects
            }
        ))
    }

    let mut component_instantiations = Vec::new();
    let mut component_fields = Vec::new();

    for cdef in def.components() {
        let field_ident = cdef.field_ident();
        let component_type = cdef.full_component_type();
        let variant_ident = cdef.variant_ident();

        let constructor_args = cdef.component_arguments();

        let suffix = if cdef.is_infallible() {
            quote!()
        } else {
            quote!(.map_err(#error_ident::#variant_ident)?)
        };

        if cdef.has_effects() {
            component_instantiations.push(quote!(
                let (#field_ident, effects) = #component_type::new(#(#constructor_args),*)
                    #suffix;
                let wrapped_effects: crate::effect::Effects<#event_ident> = crate::reactor::wrap_effects(#event_ident::#variant_ident, effects);

                all_effects.extend(wrapped_effects.into_iter());
            ));
        } else {
            component_instantiations.push(quote!(
                let #field_ident = #component_type::new(#(#constructor_args),*)
                    #suffix;
            ));
        }

        component_fields.push(quote!(#field_ident));
    }

    quote!(
        impl crate::reactor::Reactor for #reactor_ident {
            type Event = #event_ident;
            type Error = #error_ident;
            type Config = #config;

            fn dispatch_event(
                &mut self,
                effect_builder: crate::effect::EffectBuilder<Self::Event>,
                rng: &mut crate::NodeRng,
                event: Self::Event,
            ) -> crate::effect::Effects<Self::Event> {
                match event {
                    #(#dispatches)*
                }
            }

            fn new(
                cfg: Self::Config,
                registry: &prometheus::Registry,
                event_queue: crate::reactor::EventQueueHandle<Self::Event>,
                rng: &mut crate::NodeRng,
            ) -> Result<(Self, crate::effect::Effects<Self::Event>), Self::Error> {
                let mut all_effects = crate::effect::Effects::new();

                let effect_builder = crate::effect::EffectBuilder::new(event_queue);

                // Instantiate each component.
                #(#component_instantiations)*

                // Assign component fields during reactor construction.
                let reactor = #reactor_ident {
                    #(#component_fields,)*
                };

                // To avoid unused warnings.
                let _ = effect_builder;

                Ok((reactor, all_effects))
            }

            fn maybe_exit(&self) -> Option<crate::reactor::ReactorExit> { None }
        }
    )
}
/// Generates the reactor implementation itself.
Generates the reactor implementation itself.
Generates the reactor implementation itself .
pub(crate) fn generate_reactor_impl(def: &ReactorDefinition) -> TokenStream {
    let reactor_ident = def.reactor_ident();
    let event_ident = def.event_ident();
    let error_ident = def.error_ident();
    let config = def.config_type().as_given();
    let mut dispatches = Vec::new();
    // Generate dispatches for component events.
    for component in def.components() {
        let variant_ident = component.variant_ident();
        let full_component_type = component.full_component_type();
        let field_ident = component.field_ident();
        dispatches.push(quote!(
            #event_ident::#variant_ident(event) => {
                crate::reactor::wrap_effects(
                    #event_ident::#variant_ident,
                    <#full_component_type as crate::components::Component<#event_ident>>::handle_event(&mut self.#field_ident, effect_builder, rng, event)
                )
            },
        ));
    }
    // Dispatch requests as well.
    for request in def.requests() {
        let request_variant_ident = request.variant_ident();
        match request.target() {
            Target::Discard => {
                dispatches.push(quote!(
                    #event_ident::#request_variant_ident(request) => {
                        // Request is discarded.
                        // TODO: Add `trace!` call here? Consider the log spam though.
                        Default::default()
                    },
                ));
            }
            Target::Panic => {
                dispatches.push(quote!(
                    #event_ident::#request_variant_ident(request) => {
                        // Request is discarded.
                        panic!("received event that was explicitly routed to a panic: {:?}", request)
                    },
                ));
            }
            Target::Dest(ref dest) => {
                let dest_component_type = def.component(dest).full_component_type();
                let dest_variant_ident = def.component(dest).variant_ident();
                let dest_field_ident = dest;
                dispatches.push(quote!(
                            #event_ident::#request_variant_ident(request) => {
                                // Turn request into event for target component.
                                let dest_event = <#dest_component_type as crate::components::Component<Self::Event>>::Event::from(request);
                                // Route the newly created event to the component.
                                crate::reactor::wrap_effects(
                                    #event_ident::#dest_variant_ident,
                                    <#dest_component_type as crate::components::Component<Self::Event>>::handle_event(&mut self.#dest_field_ident, effect_builder, rng, dest_event)
                                )
                            },
                        ));
            }
            Target::Dispatch(ref fname) => {
                dispatches.push(quote!(
                    #event_ident::#request_variant_ident(request) => {
                        self.#fname(effect_builder, rng, request)
                    },
                ));
            }
        }
    }
    // Announcements dispatched also.
    for announcement in def.announcements() {
        let announcement_variant_ident = announcement.variant_ident();
        let mut announcement_dispatches = Vec::new();
        for target in announcement.targets() {
            match target {
                Target::Discard => {
                    // Don't do anything.
                    // TODO: Add `trace!` call here? Consider the log spam though.
                }
                Target::Panic => {
                    announcement_dispatches.push(quote!(
                        panic!("announcement received that was expressively declared as panic: {:?}",
                               announcement);
                    ));
                }
                Target::Dest(ref dest) => {
                    let dest_component_type = def.component(dest).full_component_type();
                    let dest_variant_ident = def.component(dest).variant_ident();
                    let dest_field_ident = dest;
                    announcement_dispatches.push(quote!(
                        // Dispatch announcement to target:
                        let dest_event = <#dest_component_type as crate::components::Component<Self::Event>>::Event::from(announcement);
                        let effects = crate::reactor::wrap_effects(
                            #event_ident::#dest_variant_ident,
                            <#dest_component_type as crate::components::Component<Self::Event>>::handle_event(&mut self.#dest_field_ident, effect_builder, rng, dest_event)
                        );
                        announcement_effects.extend(effects.into_iter());
                    ));
                }
                Target::Dispatch(ref fname) => {
                    announcement_dispatches.push(quote!(
                        let effects = self.#fname(effect_builder, rng, announcement);
                        announcement_effects.extend(effects.into_iter());
                    ));
                }
            }
        }
        dispatches.push(quote!(
            #event_ident::#announcement_variant_ident(announcement) => {
                let mut announcement_effects = crate::effect::Multiple::new();
                #(#announcement_dispatches)*
                announcement_effects
            }
        ))
    }
    let mut component_instantiations = Vec::new();
    let mut component_fields = Vec::new();
    for cdef in def.components() {
        let field_ident = cdef.field_ident();
        let component_type = cdef.full_component_type();
        let variant_ident = cdef.variant_ident();
        let constructor_args = cdef.component_arguments();
        let suffix = if cdef.is_infallible() {
            quote!()
        } else {
            quote!(.map_err(#error_ident::#variant_ident)?)
        };
        if cdef.has_effects() {
            component_instantiations.push(quote!(
                let (#field_ident, effects) = #component_type::new(#(#constructor_args),*)
                    #suffix;
                let wrapped_effects: crate::effect::Effects<#event_ident> = crate::reactor::wrap_effects(#event_ident::#variant_ident, effects);
                all_effects.extend(wrapped_effects.into_iter());
            ));
        } else {
            component_instantiations.push(quote!(
                let #field_ident = #component_type::new(#(#constructor_args),*)
                    #suffix;
            ));
        }
        component_fields.push(quote!(#field_ident));
    }
    quote!(
        impl crate::reactor::Reactor for #reactor_ident {
            type Event = #event_ident;
            type Error = #error_ident;
            type Config = #config;
            fn dispatch_event(
                &mut self,
                effect_builder: crate::effect::EffectBuilder<Self::Event>,
                rng: &mut crate::NodeRng,
                event: Self::Event,
            ) -> crate::effect::Effects<Self::Event> {
                match event {
                    #(#dispatches)*
                }
            }
            fn new(
                cfg: Self::Config,
                registry: &prometheus::Registry,
                event_queue: crate::reactor::EventQueueHandle<Self::Event>,
                rng: &mut crate::NodeRng,
            ) -> Result<(Self, crate::effect::Effects<Self::Event>), Self::Error> {
                let mut all_effects = crate::effect::Effects::new();
                let effect_builder = crate::effect::EffectBuilder::new(event_queue);
                // Instantiate each component.
                #(#component_instantiations)*
                // Assign component fields during reactor construction.
                let reactor = #reactor_ident {
                    #(#component_fields,)*
                };
                // To avoid unused warnings.
                let _ = effect_builder;
                Ok((reactor, all_effects))
            }
            fn maybe_exit(&self) -> Option<crate::reactor::ReactorExit> { None }
        }
    )
}
pub ( crate ) fn generate_reactor_impl ( def : & ReactorDefinition ) -> TokenStream { let reactor_ident = def . reactor_ident ( ) ; let event_ident = def . event_ident ( ) ; let error_ident = def . error_ident ( ) ; let config = def . config_type ( ) . as_given ( ) ; let mut dispatches = Vec :: new ( ) ; // Generate dispatches for component events. for component in def . components ( ) { let variant_ident = component . variant_ident ( ) ; let full_component_type = component . full_component_type ( ) ; let field_ident = component . field_ident ( ) ; dispatches . push ( quote ! ( event_ident variant_ident ( event ) { crate reactor wrap_effects ( event_ident variant_ident full_component_type as crate components Component event_ident handle_event ( mut self field_ident effect_builder rng event ) ) } ) ) ; } // Dispatch requests as well. for request in def . requests ( ) { let request_variant_ident = request . variant_ident ( ) ; match request . target ( ) { Target :: Discard => { dispatches . push ( quote ! ( event_ident request_variant_ident ( request ) { // Request is discarded. // TODO: Add `trace!` call here? Consider the log spam though. Default default ( ) } ) ) ; } Target :: Panic => { dispatches . push ( quote ! ( event_ident request_variant_ident ( request ) { // Request is discarded. panic ( " " request ) } ) ) ; } Target :: Dest ( ref dest ) => { let dest_component_type = def . component ( dest ) . full_component_type ( ) ; let dest_variant_ident = def . component ( dest ) . variant_ident ( ) ; let dest_field_ident = dest ; dispatches . push ( quote ! ( event_ident request_variant_ident ( request ) { // Turn request into event for target component. let dest_event dest_component_type as crate components Component Self Event Event from ( request ) // Route the newly created event to the component. crate reactor wrap_effects ( event_ident dest_variant_ident dest_component_type as crate components Component Self Event handle_event ( mut self dest_field_ident effect_builder rng dest_event ) ) } ) ) ; } Target :: Dispatch ( ref fname ) => { dispatches . push ( quote ! ( event_ident request_variant_ident ( request ) { self fname ( effect_builder rng request ) } ) ) ; } } } // Announcements dispatched also. for announcement in def . announcements ( ) { let announcement_variant_ident = announcement . variant_ident ( ) ; let mut announcement_dispatches = Vec :: new ( ) ; for target in announcement . targets ( ) { match target { Target :: Discard => { // Don't do anything. // TODO: Add `trace!` call here? Consider the log spam though. } Target :: Panic => { announcement_dispatches . push ( quote ! ( panic ( " " announcement ) ) ) ; } Target :: Dest ( ref dest ) => { let dest_component_type = def . component ( dest ) . full_component_type ( ) ; let dest_variant_ident = def . component ( dest ) . variant_ident ( ) ; let dest_field_ident = dest ; announcement_dispatches . push ( quote ! ( // Dispatch announcement to target: let dest_event dest_component_type as crate components Component Self Event Event from ( announcement ) let effects crate reactor wrap_effects ( event_ident dest_variant_ident dest_component_type as crate components Component Self Event handle_event ( mut self dest_field_ident effect_builder rng dest_event ) ) announcement_effects extend ( effects into_iter ( ) ) ) ) ; } Target :: Dispatch ( ref fname ) => { announcement_dispatches . push ( quote ! ( let effects self fname ( effect_builder rng announcement ) announcement_effects extend ( effects into_iter ( ) ) ) ) ; } } } dispatches . push ( quote ! ( event_ident announcement_variant_ident ( announcement ) { let mut announcement_effects crate effect Multiple new ( ) ( announcement_dispatches ) announcement_effects } ) ) } let mut component_instantiations = Vec :: new ( ) ; let mut component_fields = Vec :: new ( ) ; for cdef in def . components ( ) { let field_ident = cdef . field_ident ( ) ; let component_type = cdef . full_component_type ( ) ; let variant_ident = cdef . variant_ident ( ) ; let constructor_args = cdef . component_arguments ( ) ; let suffix = if cdef . is_infallible ( ) { quote ! ( ) } else { quote ! ( map_err ( error_ident variant_ident ) ) } ; if cdef . has_effects ( ) { component_instantiations . push ( quote ! ( let ( field_ident effects ) component_type new ( ( constructor_args ) ) suffix let wrapped_effects crate effect Effects event_ident crate reactor wrap_effects ( event_ident variant_ident effects ) all_effects extend ( wrapped_effects into_iter ( ) ) ) ) ; } else { component_instantiations . push ( quote ! ( let field_ident component_type new ( ( constructor_args ) ) suffix ) ) ; } component_fields . push ( quote ! ( field_ident ) ) ; } quote ! ( impl crate reactor Reactor for reactor_ident { type Event event_ident type Error error_ident type Config config fn dispatch_event ( mut self effect_builder crate effect EffectBuilder Self Event rng mut crate NodeRng event Self Event ) crate effect Effects Self Event { match event { ( dispatches ) } } fn new ( cfg Self Config registry prometheus Registry event_queue crate reactor EventQueueHandle Self Event rng mut crate NodeRng ) Result ( Self crate effect Effects Self Event ) Self Error { let mut all_effects crate effect Effects new ( ) let effect_builder crate effect EffectBuilder new ( event_queue ) // Instantiate each component. ( component_instantiations ) // Assign component fields during reactor construction. let reactor reactor_ident { ( component_fields ) } // To avoid unused warnings. let effect_builder Ok ( ( reactor all_effects ) ) } fn maybe_exit ( self ) Option crate reactor ReactorExit { None } } ) }
Generates the reactor implementation itself.
Generates the reactor implementation itself .
def
&ReactorDefinition
def
&ReactorDefinition