From 58476bb98eee67bc2e12625b14aab3f4c93394f7 Mon Sep 17 00:00:00 2001 From: Marc-Stefan Cassola Date: Tue, 27 Aug 2024 01:47:11 +0100 Subject: [PATCH] feat: variadic From for callbacks (#2873) --- leptos/src/callback.rs | 96 +++++++++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 25 deletions(-) diff --git a/leptos/src/callback.rs b/leptos/src/callback.rs index 456358cfa..d0d94534c 100644 --- a/leptos/src/callback.rs +++ b/leptos/src/callback.rs @@ -10,13 +10,13 @@ //! //! #[component] //! fn MyComponent( -//! #[prop(into)] render_number: Callback, +//! #[prop(into)] render_number: Callback<(i32,), String>, //! ) -> impl IntoView { //! view! { //!
-//! {render_number.run(1)} +//! {render_number.run((1,))} //! // callbacks can be called multiple times -//! {render_number.run(42)} +//! {render_number.run((42,))} //!
//! } //! } @@ -85,17 +85,39 @@ impl Callable for UnsyncCallback { } } -impl From for UnsyncCallback -where - F: Fn(In) -> T + 'static, - T: Into + 'static, - In: 'static, -{ - fn from(f: F) -> Self { - Self::new(move |x| f(x).into()) - } +macro_rules! impl_unsync_callable_from_fn { + ($($arg:ident),*) => { + impl From for UnsyncCallback<($($arg,)*), Out> + where + F: Fn($($arg),*) -> T + 'static, + T: Into + 'static, + $($arg: 'static,)* + { + fn from(f: F) -> Self { + paste::paste!( + Self::new(move |($([<$arg:lower>],)*)| f($([<$arg:lower>]),*).into()) + ) + } + } + }; } +impl_unsync_callable_from_fn!(); +impl_unsync_callable_from_fn!(P1); +impl_unsync_callable_from_fn!(P1, P2); +impl_unsync_callable_from_fn!(P1, P2, P3); +impl_unsync_callable_from_fn!(P1, P2, P3, P4); +impl_unsync_callable_from_fn!(P1, P2, P3, P4, P5); +impl_unsync_callable_from_fn!(P1, P2, P3, P4, P5, P6); +impl_unsync_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7); +impl_unsync_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7, P8); +impl_unsync_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7, P8, P9); +impl_unsync_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10); +impl_unsync_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11); +impl_unsync_callable_from_fn!( + P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12 +); + /// Callbacks define a standard way to store functions and closures. /// /// # Example @@ -104,11 +126,11 @@ where /// # use leptos::callback::{Callable, Callback}; /// #[component] /// fn MyComponent( -/// #[prop(into)] render_number: Callback, +/// #[prop(into)] render_number: Callback<(i32,), String>, /// ) -> impl IntoView { /// view! { ///
-/// {render_number.run(42)} +/// {render_number.run((42,))} ///
/// } /// } @@ -148,17 +170,37 @@ impl Clone for Callback { impl Copy for Callback {} -impl From for Callback -where - F: Fn(In) -> T + Send + Sync + 'static, - T: Into + 'static, - In: Send + Sync + 'static, -{ - fn from(f: F) -> Self { - Self::new(move |x| f(x).into()) - } +macro_rules! impl_callable_from_fn { + ($($arg:ident),*) => { + impl From for Callback<($($arg,)*), Out> + where + F: Fn($($arg),*) -> T + Send + Sync + 'static, + T: Into + 'static, + $($arg: Send + Sync + 'static,)* + { + fn from(f: F) -> Self { + paste::paste!( + Self::new(move |($([<$arg:lower>],)*)| f($([<$arg:lower>]),*).into()) + ) + } + } + }; } +impl_callable_from_fn!(); +impl_callable_from_fn!(P1); +impl_callable_from_fn!(P1, P2); +impl_callable_from_fn!(P1, P2, P3); +impl_callable_from_fn!(P1, P2, P3, P4); +impl_callable_from_fn!(P1, P2, P3, P4, P5); +impl_callable_from_fn!(P1, P2, P3, P4, P5, P6); +impl_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7); +impl_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7, P8); +impl_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7, P8, P9); +impl_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10); +impl_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11); +impl_callable_from_fn!(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12); + impl Callback { /// Creates a new callback from the given function. pub fn new(fun: F) -> Self @@ -190,11 +232,15 @@ mod tests { #[test] fn runback_from() { - let _callback: Callback<(), String> = (|()| "test").into(); + let _callback: Callback<(), String> = (|| "test").into(); + let _callback: Callback<(i32, String), String> = + (|num, s| format!("{num} {s}")).into(); } #[test] fn sync_callback_from() { - let _callback: UnsyncCallback<(), String> = (|()| "test").into(); + let _callback: UnsyncCallback<(), String> = (|| "test").into(); + let _callback: UnsyncCallback<(i32, String), String> = + (|num, s| format!("{num} {s}")).into(); } }