specta 2.0.0-rc.25

Easily export your Rust types to other languages
Documentation
//! Support for collecting Rust function signatures.
//!
//! Specta does not export callable functions by itself. Instead, it records the
//! names, arguments, return types, docs, and deprecation metadata needed by
//! framework crates to generate bindings for their own function or command
//! systems.

mod arg;
mod result;
mod specta_fn;

pub use arg::FunctionArg;
pub use result::FunctionResult;
#[doc(hidden)]
pub use result::{FunctionFutureMarker, FunctionValueMarker};
pub(crate) use specta_fn::SpectaFn;

/// Returns a [`Function`](crate::datatype::Function) for a given function that has been annotated with
/// the `#[specta]` attribute.
///
/// # Examples
///
/// ```rust
/// use specta::{*, datatype::*, function::fn_datatype};
///
/// #[specta]
/// fn some_function(name: String, age: i32) -> bool {
///     true
/// }
///
/// fn main() {
///     let typ = fn_datatype!(some_function)(&mut Types::default());
///
///     assert_eq!(typ.name(), "some_function");
///     assert_eq!(typ.args().len(), 2);
///     assert_eq!(typ.result(), Some(&DataType::Primitive(Primitive::bool)));
/// }
/// ```
///
/// # Recursion limit reached while expanding the macro `fn_datatype`
///
/// This macro requires recursion internally to correctly function so you may run into the recursion limit. From my testing you can have 31 path segments before you hit the recursion limit. The size of the segment or the amount of generics in the segment should not affect this limit.
///
/// If your having issues with this limit you can increase your [`recursion_limit`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute) by adding `#![recursion_limit = "1024"]` to your `main.rs`. If your able to hit this limit in other scenarios please [let us know](https://github.com/specta-rs/tauri-specta/issues/114) and we can apply some potential optimizations.
///
#[doc(hidden)]
#[macro_export]
macro_rules! _fn_datatype {
    // Hide distracting implementation details from the generated rustdoc.
    ($($json:tt)*) => {
        $crate::function::_fn_datatype_internal!($($json)*)
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! _fn_datatype_internal {
    ([$($path:tt)*] [$($full:tt)*] [$last:tt]) => {
        $crate::internal::paste! {
            $($path)* [<__specta__fn__ $last>]!(@export_fn; $($full)*)
        }
    };
    ([$($path:tt)*] [$($full:tt)*] [$($last:tt)?] $t:tt :: <$($g:path),*> $($rest:tt)*) => {
        $crate::function::fn_datatype!([$($path)* $($last)*] [$($full)* $t::<$($g),*>] [$t] $($rest)*)
    };
    ([$($path:tt)*] [$($full:tt)*] [$($last:tt)?] $t:tt $($rest:tt)*) => {
        $crate::function::fn_datatype!([$($path)* $($last)*] [$($full)* $t] [$t] $($rest)*)
    };
    () => {{
            compile_error!("fn_datatype must be provided a function path as an argument");
    }};
    ($($rest:tt)*) => {
        $crate::function::fn_datatype!([] [] [] $($rest)*)
    };
}

/// Collects function types into a [`Vec`],
/// and all downstream types into a [`Types`](crate::Types) instance.
///
/// Specifying a `types` argument allows a custom [`Types`](crate::Types) to be used.
///
/// # Examples
///
/// ```rust
/// use specta::*;
///
/// #[specta]
/// fn some_function(name: String, age: i32) -> bool {
///     true
/// }
///
/// fn main() {
///     let functions = function::collect_functions![some_function](&mut Types::default());
/// }
/// ````
#[doc(hidden)]
#[macro_export]
macro_rules! _collect_functions {
    ($(,)?) => {{
        fn export(_: &mut $crate::Types) -> Vec<$crate::datatype::Function> {
            vec![]
        }

        export
    }};
    ($($b:tt $(:: $($p:ident)? $(<$($g:path),*>)? )* ),* $(,)?) => {{
        fn export(types: &mut $crate::Types) -> Vec<$crate::datatype::Function> {
            vec![
                $($crate::function::fn_datatype!($b $($(::$p)? $(::<$($g),*>)? )* )(types)),*
            ]
        }

        export
    }};
}

#[doc(inline)]
pub use _collect_functions as collect_functions;
#[doc(inline)]
pub use _fn_datatype as fn_datatype;
#[doc(hidden)]
pub use _fn_datatype_internal;