macro_rules! empty_function_caller {
    (
        $interface_name:ident {
            $(
                $empty_function_js_name:literal:
                    $empty_function_rust_name:ident() -> $empty_function_return_type:ty;
            )*
        }
    ) => {
        impl<'env> $interface_name<'env> {
            $(
                pub fn $empty_function_rust_name(
                    &self,
                ) -> Result<$empty_function_return_type, napi::Error> {
                    let js_function: bindgen_prelude::Function<
                        (),
                        $empty_function_return_type,
                    > = self.inner.get_named_property($empty_function_js_name)?;

                    js_function.apply(self.inner, ())
                }
            )*
        }
    };
}

macro_rules! function_caller {
    (
        $interface_name:ident {
            $(
                $function_js_name:literal:
                    $function_rust_name:ident(
                        $(
                            $function_argument_name:ident: $function_argument_type:ty,
                        )+
                    ) -> $function_return_type:ty;
            )*
        }
    ) => {
        impl<'env> $interface_name<'env> {
            $(
                pub fn $function_rust_name(
                    &self,
                    $($function_argument_name: $function_argument_type),+
                ) -> Result<$function_return_type, napi::Error> {
                    let js_function: bindgen_prelude::Function<
                        bindgen_prelude::FnArgs<($($function_argument_type,)+)>,
                        $function_return_type,
                    > = self.inner.get_named_property($function_js_name)?;

                    js_function.apply(self.inner, bindgen_prelude::FnArgs::from(($($function_argument_name,)+)))
                }
            )*
        }
    };
}

pub(crate) use empty_function_caller;
pub(crate) use function_caller;