mry_macros 0.14.0

Macro crate for mry, a simple but powerful mocking library that supports struct, trait, and function.
Documentation
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::Ident;

use crate::MAX_ARGUMENT_COUNT;

pub fn create() -> TokenStream {
    let items = (0..=MAX_ARGUMENT_COUNT).map(|nargs| {
        let (args, types): (Vec<_>, Vec<_>) = (1..=nargs)
            .map(|i| {
                let name = format!("Arg{i}");
                (
                    Ident::new(&name.to_lowercase(), Span::call_site()),
                    Ident::new(&name, Span::call_site()),
                )
            })
            .unzip();
        let behavior_name = Ident::new(&format!("Behavior{}", args.len()), Span::call_site());
        let behavior_name_send_wrapper = Ident::new(&format!("BehaviorSendWrapper{}", args.len()), Span::call_site());
        quote! {
            #[doc(hidden)]
            pub struct #behavior_name<I, O>(Box<dyn FnMut(I) -> O + Send + 'static>);
            #[doc(hidden)]
            pub struct #behavior_name_send_wrapper<I, O>(Box<dyn FnMut(I) -> crate::send_wrapper::SendWrapper<O> + Send + 'static>);

            impl<Fn, O, #(#types),*> From<Fn> for #behavior_name<(#(#types,)*), O>
            where
                Fn: FnMut(#(#types),*) -> O + Send + 'static,
            {
                fn from(mut function: Fn) -> Self {
                    #behavior_name(Box::new(move |(#(#args,)*)| function(#(#args),*)))
                }
            }

            impl<Fn, O, #(#types),*> From<Fn> for #behavior_name_send_wrapper<(#(#types,)*), O>
            where
                Fn: FnMut(#(#types),*) -> O + Send + 'static,
            {
                fn from(mut function: Fn) -> Self {
                    #behavior_name_send_wrapper(Box::new(move |(#(#args,)*)| crate::send_wrapper::SendWrapper::new(function(#(#args),*))))
                }
            }

            impl<I: Clone, O> Into<Behavior<I, O>> for #behavior_name<I, O> {
                fn into(self) -> Behavior<I, O> {
                    Behavior::Function {
                        clone: Clone::clone,
                        call: self.0,
                    }
                }
            }

            impl<I: Clone, O> Into<Behavior<I, crate::send_wrapper::SendWrapper<O>>> for #behavior_name_send_wrapper<I, O> {
                fn into(self) -> Behavior<I, crate::send_wrapper::SendWrapper<O>> {
                    Behavior::Function {
                        clone: Clone::clone,
                        call: self.0,
                    }
                }
            }
        }
    });
    quote![#(#items)*]
}