vin-macros 4.0.1

Procedural macros that power vin
Documentation
use proc_macro2::TokenStream as TokenStream2;
use syn::{Ident, ImplGenerics, TypeGenerics, WhereClause};
use quote::quote;

use crate::actor::handles_attr::*;

pub fn form_forwarder_impls(
    name: &Ident,
    handles_attrs: &Vec<HandlesAttribute>,
    impl_generics: &ImplGenerics,
    ty_generics: &TypeGenerics,
    where_clause: Option<&WhereClause>,
) -> TokenStream2 {
    let streams = handles_attrs.iter()
        .map(|attr| {
            let type_path = &attr.message_type.path;
            let short_name = attr.message_type.path.segments.last().unwrap().ident.to_string().to_lowercase();
            let short_name = quote::format_ident!("{}", short_name);
            let quoted = if let Some(Bounded { size: _, mode }) = &attr.bounded {
                match mode {
                    BoundedMode::Wait => {
                        quote! {
                            self.vin_hidden.mailbox.#short_name.0
                                .send(msg)
                                .await
                                .expect("vin | mailbox channel should never be closed during the actor's lifetime");
                        }
                    },
                    BoundedMode::Report => {
                        quote! { 
                            if let Err(err) = self.vin_hidden.mailbox.#short_name.0.try_send(msg) {
                                match err {
                                    ::vin::async_channel::TrySendError::Full(_) => {
                                        ::vin::log::error!("vin | mailbox for {:?} is full", stringify!(#type_path));
                                    },
                                    ::vin::async_channel::TrySendError::Closed(_) => {
                                        unreachable!("vin | mailbox channel should never be closed during the actor's lifetime");
                                    },
                                }
                            }
                        }
                    },
                    BoundedMode::Silent => {
                        quote! {
                            let _ = self.vin_hidden.mailbox.#short_name.0.try_send(msg);
                        }
                    },
                }
            } else {
                quote! {
                    let _ = self.vin_hidden.mailbox.#short_name.0.try_send(msg);
                }
            };

            (attr.message_type.clone(), quoted)
        })
        .map(|(msg_name, body)| {
            quote! {
                #[::vin::async_trait::async_trait]
                impl #impl_generics ::vin::vin_core::detail::Forwarder<#msg_name> for #name #ty_generics #where_clause {
                    async fn forward(&self, msg: ::vin::vin_core::detail::WrappedMessage<#msg_name>) {
                        #body
                    }
                }
            }
        })
        .collect::<Vec<_>>();

    let mut stream = TokenStream2::new();
    streams.into_iter().for_each(|x| stream.extend(x) );

    stream
}