qubit-function 0.14.2

Functional programming traits and Box/Rc/Arc adapters for Rust, inspired by Java functional interfaces
Documentation
/*******************************************************************************
 *
 *    Copyright (c) 2025 - 2026 Haixing Hu.
 *
 *    SPDX-License-Identifier: Apache-2.0
 *
 *    Licensed under the Apache License, Version 2.0.
 *
 ******************************************************************************/

/// Implement trait for closures with automatic type inference
///
/// This macro generates blanket implementations for closures implementing
/// various function traits (Consumer, Function, Predicate, etc.). It
/// automatically infers everything from the function signature and trait name.
///
/// # Parameters
///
/// * `$trait_name<$(generics),*>` - Full trait name with generics (e.g., `Consumer<T>`, `Function<T, R>`)
/// * `$method_name` - Core method name (e.g., `accept`, `apply`, `test`)
/// * `$once_type` - Optional once wrapper type (e.g., `BoxConsumerOnce`)
/// * `$fn_signature` - Function signature (e.g., `Fn(value: &T)`, `FnMut(input: &T) -> R`)
///
/// # Generated implementation
///
/// Generates a blanket implementation for all closures matching the signature,
/// including:
/// - Core method implementation
/// - `into_box`, `into_rc`, `into_arc`, `into_fn` methods
/// - `to_box`, `to_rc`, `to_arc`, `to_fn` methods
/// - `into_once`, `to_once` methods (if once_type is provided)
///
/// # Examples
///
/// ```text
/// // Consumer trait (with once conversion)
/// // impl_closure_trait!(
/// //     Consumer<i32>,
/// //     accept,
/// //     BoxConsumerOnce,
/// //     Fn(value: &i32)
/// // );
///
/// // Function trait
/// // impl_closure_trait!(
/// //     Function<i32, i32>,
/// //     apply,
/// //     BoxFunctionOnce,
/// //     Fn(input: i32) -> i32
/// // );
///
/// // Predicate trait (no once conversion)
/// // impl_closure_trait!(
/// //     Predicate<i32>,
/// //     test,
/// //     Fn(value: &i32) -> bool
/// // );
///
/// // StatefulConsumer trait
/// // impl_closure_trait!(
/// //     StatefulConsumer<i32>,
/// //     accept,
/// //     BoxConsumerOnce,
/// //     FnMut(value: &i32)
/// // );
/// ```
///
macro_rules! impl_closure_trait {
  // ==================== Helper macro: generate into_once methods ====================

  // Fn trait: into_once method
  (@into_once_fn_method $once_type:ident, ($($generics:ident),*)) => {
      #[inline]
      fn into_once(self) -> $once_type<$($generics),*>
      where
          Self: Sized + 'static,
      {
          $once_type::new(self)
      }
  };

  // FnMut trait: into_once method
  (@into_once_fnmut_method $once_type:ident, ($($generics:ident),*), ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?) => {
      #[inline]
      fn into_once(mut self) -> $once_type<$($generics),*>
      where
          Self: Sized + 'static,
      {
          $once_type::new(move |$($arg: $arg_ty),*| self($($arg),*))
      }
  };

  // ==================== Helper macro: generate to_once methods ====================

  // Fn trait: to_once method
  (@to_once_fn_method $once_type:ident, ($($generics:ident),*)) => {
      #[inline]
      fn to_once(&self) -> $once_type<$($generics),*>
      where
          Self: Clone + Sized + 'static,
      {
          $once_type::new(self.clone())
      }
  };

  // FnMut trait: to_once method
  (@to_once_fnmut_method $once_type:ident, ($($generics:ident),*), ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?) => {
      #[inline]
      fn to_once(&self) -> $once_type<$($generics),*>
      where
          Self: Clone + Sized + 'static,
      {
          let mut cloned = self.clone();
          $once_type::new(move |$($arg: $arg_ty),*| cloned($($arg),*))
      }
  };

  // ==================== Internal implementation: common Fn trait methods ====================

  (
      @impl_common_fn
      $trait_name:ident < $($generics:ident),* >,
      $method_name:ident,
      $closure_trait:path,
      ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
  ) => {
      // Core method: call the closure directly.
      #[inline]
      fn $method_name(&self, $($arg: $arg_ty),*) $(-> $ret)? {
          self($($arg),*)
      }

      // ===== Conversion methods: derive wrapper type names with paste. =====

      #[inline]
      fn into_box(self) -> paste::paste! { [<Box $trait_name>] < $($generics),* > }
      where
          Self: Sized + 'static,
      {
          paste::paste! { [<Box $trait_name>]::new(self) }
      }

      #[inline]
      fn into_rc(self) -> paste::paste! { [<Rc $trait_name>] < $($generics),* > }
      where
          Self: Sized + 'static,
      {
          paste::paste! { [<Rc $trait_name>]::new(self) }
      }

      #[inline]
      fn into_fn(self) -> impl $closure_trait
      where
          Self: Sized + 'static,
      {
          self
      }

      // into_arc: Fn wrappers require Send + Sync.
      #[inline]
      fn into_arc(self) -> paste::paste! { [<Arc $trait_name>] < $($generics),* > }
      where
          Self: Sized + Send + Sync + 'static,
      {
          paste::paste! { [<Arc $trait_name>]::new(self) }
      }

      // ===== to_* methods: clone-based conversions. =====

      #[inline]
      fn to_box(&self) -> paste::paste! { [<Box $trait_name>] < $($generics),* > }
      where
          Self: Clone + Sized + 'static,
      {
          paste::paste! { [<Box $trait_name>]::new(self.clone()) }
      }

      #[inline]
      fn to_rc(&self) -> paste::paste! { [<Rc $trait_name>] < $($generics),* > }
      where
          Self: Clone + Sized + 'static,
      {
          paste::paste! { [<Rc $trait_name>]::new(self.clone()) }
      }

      #[inline]
      fn to_fn(&self) -> impl $closure_trait
      where
          Self: Clone + Sized + 'static,
      {
          self.clone()
      }

      // to_arc: Fn wrappers require Send + Sync.
      #[inline]
      fn to_arc(&self) -> paste::paste! { [<Arc $trait_name>] < $($generics),* > }
      where
          Self: Clone + Sized + Send + Sync + 'static,
      {
          paste::paste! { [<Arc $trait_name>]::new(self.clone()) }
      }
  };

  // ==================== Internal implementation: common FnMut trait methods ====================

  (
      @impl_common_fnmut
      $trait_name:ident < $($generics:ident),* >,
      $method_name:ident,
      $closure_trait:path,
      ($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
  ) => {
      // Core method: call the closure directly.
      #[inline]
      fn $method_name(&mut self, $($arg: $arg_ty),*) $(-> $ret)? {
          self($($arg),*)
      }

      // ===== Conversion methods: derive wrapper type names with paste. =====

      #[inline]
      fn into_box(self) -> paste::paste! { [<Box $trait_name>] < $($generics),* > }
      where
          Self: Sized + 'static,
      {
          paste::paste! { [<Box $trait_name>]::new(self) }
      }

      #[inline]
      fn into_rc(self) -> paste::paste! { [<Rc $trait_name>] < $($generics),* > }
      where
          Self: Sized + 'static,
      {
          paste::paste! { [<Rc $trait_name>]::new(self) }
      }

      #[inline]
      fn into_fn(self) -> impl $closure_trait
      where
          Self: Sized + 'static,
      {
          self
      }

      // into_arc: FnMut wrappers only require Send.
      #[inline]
      fn into_arc(self) -> paste::paste! { [<Arc $trait_name>] < $($generics),* > }
      where
          Self: Sized + Send + 'static,
      {
          paste::paste! { [<Arc $trait_name>]::new(self) }
      }

      // ===== to_* methods: clone-based conversions. =====

      #[inline]
      fn to_box(&self) -> paste::paste! { [<Box $trait_name>] < $($generics),* > }
      where
          Self: Clone + Sized + 'static,
      {
          paste::paste! { [<Box $trait_name>]::new(self.clone()) }
      }

      #[inline]
      fn to_rc(&self) -> paste::paste! { [<Rc $trait_name>] < $($generics),* > }
      where
          Self: Clone + Sized + 'static,
      {
          paste::paste! { [<Rc $trait_name>]::new(self.clone()) }
      }

      #[inline]
      fn to_fn(&self) -> impl $closure_trait
      where
          Self: Clone + Sized + 'static,
      {
          self.clone()
      }

      // to_arc: FnMut wrappers only require Send.
      #[inline]
      fn to_arc(&self) -> paste::paste! { [<Arc $trait_name>] < $($generics),* > }
      where
          Self: Clone + Sized + Send + 'static,
      {
          let cloned = self.clone();
          paste::paste! { [<Arc $trait_name>]::new(cloned) }
      }
  };


  // ==================== Public interface: matches the impl_rc_conversions pattern ====================

  // Regular trait (Fn) - with once conversion
  (
      $trait_name:ident < $($generics:ident),* >,
      $method_name:ident,
      $once_type:ident,
      Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
  ) => {
      impl<$($generics,)* F> $trait_name<$($generics),*> for F
      where
          F: Fn($($arg_ty),*) $(-> $ret)?,
      {
          // Generate common methods.
          impl_closure_trait!(
              @impl_common_fn
              $trait_name<$($generics),*>,
              $method_name,
              Fn($($arg_ty),*) $(-> $ret)?,
              ($($arg : $arg_ty),*) $(-> $ret)?
          );

          // Generate into_once and to_once methods.
          impl_closure_trait!(@into_once_fn_method $once_type, ($($generics),*));
          impl_closure_trait!(@to_once_fn_method $once_type, ($($generics),*));
      }
  };

  // Regular trait (Fn) - without once version
  (
      $trait_name:ident < $($generics:ident),* >,
      $method_name:ident,
      Fn($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
  ) => {
      impl<$($generics,)* F> $trait_name<$($generics),*> for F
      where
          F: Fn($($arg_ty),*) $(-> $ret)?,
      {
          // Generate common methods without into_once/to_once.
          impl_closure_trait!(
              @impl_common_fn
              $trait_name<$($generics),*>,
              $method_name,
              Fn($($arg_ty),*) $(-> $ret)?,
              ($($arg : $arg_ty),*) $(-> $ret)?
          );
      }
  };

  // Stateful trait (FnMut) - with once conversion
  (
      $trait_name:ident < $($generics:ident),* >,
      $method_name:ident,
      $once_type:ident,
      FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
  ) => {
      impl<$($generics,)* F> $trait_name<$($generics),*> for F
      where
          F: FnMut($($arg_ty),*) $(-> $ret)?,
      {
          // Generate common methods.
          impl_closure_trait!(
              @impl_common_fnmut
              $trait_name<$($generics),*>,
              $method_name,
              FnMut($($arg_ty),*) $(-> $ret)?,
              ($($arg : $arg_ty),*) $(-> $ret)?
          );

          // Generate into_once and to_once methods.
          impl_closure_trait!(@into_once_fnmut_method $once_type, ($($generics),*), ($($arg : $arg_ty),*) $(-> $ret)?);
          impl_closure_trait!(@to_once_fnmut_method $once_type, ($($generics),*), ($($arg : $arg_ty),*) $(-> $ret)?);
      }
  };

  // Stateful trait (FnMut) - without once version
  (
      $trait_name:ident < $($generics:ident),* >,
      $method_name:ident,
      FnMut($($arg:ident : $arg_ty:ty),*) $(-> $ret:ty)?
  ) => {
      impl<$($generics,)* F> $trait_name<$($generics),*> for F
      where
          F: FnMut($($arg_ty),*) $(-> $ret)?,
      {
          // Generate common methods without into_once/to_once.
          impl_closure_trait!(
              @impl_common_fnmut
              $trait_name<$($generics),*>,
              $method_name,
              FnMut($($arg_ty),*) $(-> $ret)?,
              ($($arg : $arg_ty),*) $(-> $ret)?
          );
      }
  };
}

pub(crate) use impl_closure_trait;