fn to_tokens()

in quic/s2n-quic-events/src/parser.rs [99:411]


    fn to_tokens(&self, output: &mut Output) {
        let Self {
            attrs,
            ident,
            generics,
            fields,
        } = self;
        let ident_str = ident.to_string();

        let derive_attrs = &attrs.derive_attrs;
        let builder_derive_attrs = &attrs.builder_derive_attrs;
        let extra_attrs = &attrs.extra;
        let deprecated = &attrs.deprecated;
        let allow_deprecated = &attrs.allow_deprecated;

        let destructure_fields: Vec<_> = fields.iter().map(Field::destructure).collect();
        let builder_fields = fields.iter().map(Field::builder);
        let builder_field_impls = fields.iter().map(Field::builder_impl);
        let api_fields = fields.iter().map(Field::api);
        let snapshot_fields = fields.iter().map(Field::snapshot);

        if attrs.builder_derive {
            output.builders.extend(quote!(
                #[#builder_derive_attrs]
            ));
        }

        output.builders.extend(quote!(
            #[derive(Clone, Debug)]
            #extra_attrs
            pub struct #ident #generics {
                #(#builder_fields)*
            }

            #allow_deprecated
            impl #generics IntoEvent<api::#ident #generics> for #ident #generics {
                #[inline]
                fn into_event(self) -> api::#ident #generics {
                    let #ident {
                        #(#destructure_fields),*
                    } = self;

                    api::#ident {
                        #(#builder_field_impls)*
                    }
                }
            }
        ));

        if attrs.derive {
            output.api.extend(quote!(#[derive(Clone, Debug)]));
        }

        if !attrs.exhaustive {
            output.api.extend(quote!(#[non_exhaustive]));
        }

        output.api.extend(quote!(
            #derive_attrs
            #extra_attrs
            #deprecated
            #allow_deprecated
            pub struct #ident #generics {
                #(#api_fields)*
            }

            #[cfg(any(test, feature = "testing"))]
            #allow_deprecated
            impl #generics crate::event::snapshot::Fmt for #ident #generics {
                fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
                    let mut fmt = fmt.debug_struct(#ident_str);
                    #(#snapshot_fields)*
                    fmt.finish()
                }
            }
        ));

        if let Some(event_name) = attrs.event_name.as_ref() {
            output.api.extend(quote!(
                #allow_deprecated
                impl #generics Event for #ident #generics {
                    const NAME: &'static str = #event_name;
                }
            ));

            let ident_str = self.ident_str();
            let snake = self.ident_snake();
            let counter = self.counter();
            let function = self.function();

            let subscriber_doc = format!("Called when the `{ident_str}` event is triggered");
            let publisher_doc =
                format!("Publishes a `{ident_str}` event to the publisher's subscriber");

            let counter_type = output.mode.counter_type();
            let counter_init = output.mode.counter_init();

            // add a counter for testing structs
            output.testing_fields.extend(quote!(
                pub #counter: #counter_type,
            ));
            output.testing_fields_init.extend(quote!(
                #counter: #counter_init,
            ));

            let receiver = output.mode.receiver();
            let counter_increment = output.mode.counter_increment();
            let lock = output.mode.lock();

            match attrs.subject {
                Subject::Endpoint => {
                    output.subscriber.extend(quote!(
                        #[doc = #subscriber_doc]
                        #[inline]
                        #deprecated
                        #allow_deprecated
                        fn #function(&#receiver self, meta: &api::EndpointMeta, event: &api::#ident) {
                            let _ = meta;
                            let _ = event;
                        }
                    ));

                    output.tuple_subscriber.extend(quote!(
                        #[inline]
                        #allow_deprecated
                        fn #function(&#receiver self, meta: &api::EndpointMeta, event: &api::#ident) {
                            (self.0).#function(meta, event);
                            (self.1).#function(meta, event);
                        }
                    ));

                    if output.mode.is_ref() {
                        output.ref_subscriber.extend(quote!(
                            #[inline]
                            #allow_deprecated
                            fn #function(&#receiver self, meta: &api::EndpointMeta, event: &api::#ident) {
                                self.as_ref().#function(meta, event);
                            }
                        ));
                    }

                    output.tracing_subscriber.extend(quote!(
                        #[inline]
                        #allow_deprecated
                        fn #function(&#receiver self, meta: &api::EndpointMeta, event: &api::#ident) {
                            let parent = self.parent(meta);
                            let api::#ident { #(#destructure_fields),* } = event;
                            tracing::event!(target: #snake, parent: parent, tracing::Level::DEBUG, { #(#destructure_fields = tracing::field::debug(#destructure_fields)),* });
                        }
                    ));

                    output.endpoint_publisher.extend(quote!(
                        #[doc = #publisher_doc]
                        fn #function(&#receiver self, event: builder::#ident);
                    ));

                    output.endpoint_publisher_subscriber.extend(quote!(
                        #[inline]
                        #allow_deprecated
                        fn #function(&#receiver self, event: builder::#ident) {
                            let event = event.into_event();
                            self.subscriber.#function(&self.meta, &event);
                            self.subscriber.on_event(&self.meta, &event);
                        }
                    ));

                    for subscriber in [
                        &mut output.endpoint_subscriber_testing,
                        &mut output.subscriber_testing,
                    ] {
                        subscriber.extend(quote!(
                            #allow_deprecated
                            fn #function(&#receiver self, meta: &api::EndpointMeta, event: &api::#ident) {
                                self.#counter #counter_increment;
                                let meta = crate::event::snapshot::Fmt::to_snapshot(meta);
                                let event = crate::event::snapshot::Fmt::to_snapshot(event);
                                let out = format!("{meta:?} {event:?}");
                                self.output #lock.push(out);
                            }
                        ));
                    }

                    // add a counter for testing structs
                    output.endpoint_testing_fields.extend(quote!(
                        pub #counter: #counter_type,
                    ));
                    output.endpoint_testing_fields_init.extend(quote!(
                        #counter: #counter_init,
                    ));

                    output.endpoint_publisher_testing.extend(quote!(
                        #allow_deprecated
                        fn #function(&#receiver self, event: builder::#ident) {
                            self.#counter #counter_increment;
                            let event = event.into_event();
                            let event = crate::event::snapshot::Fmt::to_snapshot(&event);
                            let out = format!("{event:?}");
                            self.output #lock.push(out);
                        }
                    ));
                }
                Subject::Connection => {
                    output.subscriber.extend(quote!(
                        #[doc = #subscriber_doc]
                        #[inline]
                        #deprecated
                        #allow_deprecated
                        fn #function(
                            &#receiver self,
                            context: &#receiver Self::ConnectionContext,
                            meta: &api::ConnectionMeta,
                            event: &api::#ident
                        ) {
                            let _ = context;
                            let _ = meta;
                            let _ = event;
                        }
                    ));

                    output.tuple_subscriber.extend(quote!(
                        #[inline]
                        #allow_deprecated
                        fn #function(
                            &#receiver self,
                            context: &#receiver Self::ConnectionContext,
                            meta: &api::ConnectionMeta,
                            event: &api::#ident
                        ) {
                            (self.0).#function(&#receiver context.0, meta, event);
                            (self.1).#function(&#receiver context.1, meta, event);
                        }
                    ));

                    if output.mode.is_ref() {
                        output.ref_subscriber.extend(quote!(
                            #[inline]
                            #allow_deprecated
                            fn #function(
                                &#receiver self,
                                context: &#receiver Self::ConnectionContext,
                                meta: &api::ConnectionMeta,
                                event: &api::#ident
                            ) {
                                self.as_ref().#function(context, meta, event);
                            }
                        ));
                    }

                    output.tracing_subscriber.extend(quote!(
                        #[inline]
                        #allow_deprecated
                        fn #function(
                            &#receiver self,
                            context: &#receiver Self::ConnectionContext,
                            _meta: &api::ConnectionMeta,
                            event: &api::#ident
                        ) {
                            let id = context.id();
                            let api::#ident { #(#destructure_fields),* } = event;
                            tracing::event!(target: #snake, parent: id, tracing::Level::DEBUG, { #(#destructure_fields = tracing::field::debug(#destructure_fields)),* });
                        }
                    ));

                    output.connection_publisher.extend(quote!(
                        #[doc = #publisher_doc]
                        fn #function(&#receiver self, event: builder::#ident);
                    ));

                    output.connection_publisher_subscriber.extend(quote!(
                        #[inline]
                        #allow_deprecated
                        fn #function(&#receiver self, event: builder::#ident) {
                            let event = event.into_event();
                            self.subscriber.#function(self.context, &self.meta, &event);
                            self.subscriber.on_connection_event(self.context, &self.meta, &event);
                            self.subscriber.on_event(&self.meta, &event);
                        }
                    ));

                    output.subscriber_testing.extend(quote!(
                        #allow_deprecated
                        fn #function(
                            &#receiver self,
                            _context: &#receiver Self::ConnectionContext,
                            meta: &api::ConnectionMeta,
                            event: &api::#ident
                        ) {
                            self.#counter #counter_increment;
                            if self.location.is_some() {
                                let meta = crate::event::snapshot::Fmt::to_snapshot(meta);
                                let event = crate::event::snapshot::Fmt::to_snapshot(event);
                                let out = format!("{meta:?} {event:?}");
                                self.output #lock.push(out);
                            }
                        }
                    ));

                    output.connection_publisher_testing.extend(quote!(
                        #allow_deprecated
                        fn #function(&#receiver self, event: builder::#ident) {
                            self.#counter #counter_increment;
                            let event = event.into_event();
                            if self.location.is_some() {
                                let event = crate::event::snapshot::Fmt::to_snapshot(&event);
                                let out = format!("{event:?}");
                                self.output #lock.push(out);
                            }
                        }
                    ));
                }
            }
        }
    }