Skip to content

Commit

Permalink
Cleanup functions stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont committed Apr 2, 2024
1 parent 2ae7766 commit e7fb839
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 125 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ bit-vec = { version = "0.6.3", optional = true, default-features = false, featur
bson = { version = "2.6.1", optional = true, default-features = false, features = [] }
openapiv3 = { version = "1.0.2", optional = true, default-features = false, features = [] }
uhlc = { version = "0.6.0", optional = true, default-features = false, features = [] }
tauri = { version = "1.4.1", optional = true, default-features = false, features = [] }
bytesize = { version = "1.2.0", optional = true, default-features = false, features = [] }
glam = { version = "0.25", optional = true, default-features = false, features = ["std"] }
tokio = { version = "1.30", optional = true, default-features = false, features = ["sync"] }
Expand Down
49 changes: 0 additions & 49 deletions macros/src/fn_datatype.rs

This file was deleted.

40 changes: 40 additions & 0 deletions macros/src/internal_fn_datatype.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use crate::utils::format_fn_wrapper;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{
parse::{Parse, ParseStream},
Path, PathArguments,
};

pub struct FnDatatypeInput {
function: Path,
}

impl Parse for FnDatatypeInput {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
Ok(Self {
function: input.parse()?,
})
}
}

pub fn proc_macro(FnDatatypeInput { function }: FnDatatypeInput) -> syn::Result<TokenStream> {
let mut specta_fn_macro = function.clone();

let last = specta_fn_macro
.segments
.last_mut()
.expect("Function path is empty!");

last.ident = format_fn_wrapper(&last.ident.clone());
last.arguments = PathArguments::None;

// `type_map` is defined by `specta::fn_datatype!` which invokes this.
Ok(quote! {
// This defines `export`
#specta_fn_macro!(@export_fn; #function);

// `let` is to workaround: error: macro expansion ignores token `;` and any following
let result = export(type_map);
})
}
13 changes: 8 additions & 5 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
mod utils;
mod data_type_from;
#[cfg(feature = "functions")]
mod fn_datatype;
mod internal_fn_datatype;
#[cfg(feature = "functions")]
mod specta;
mod r#type;
Expand All @@ -37,11 +37,14 @@ pub fn specta(
}

#[proc_macro]
#[doc(hidden)]
#[cfg(feature = "functions")]
pub fn fn_datatype(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
pub fn internal_fn_datatype(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
use syn::parse_macro_input;

fn_datatype::proc_macro(parse_macro_input!(input as fn_datatype::FnDatatypeInput))
.unwrap_or_else(|err| err.into_compile_error())
.into()
internal_fn_datatype::proc_macro(parse_macro_input!(
input as internal_fn_datatype::FnDatatypeInput
))
.unwrap_or_else(|err| err.into_compile_error())
.into()
}
23 changes: 15 additions & 8 deletions macros/src/specta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,22 @@ pub fn attribute(item: proc_macro::TokenStream) -> syn::Result<proc_macro::Token
#function

#maybe_macro_export
#[doc(hidden)]
#[doc(hidden)] // We take in `$function` from the invocation so we have `name::<concrete_generics_types>`
macro_rules! #wrapper {
(@asyncness) => { #function_asyncness };
(@name) => { #function_name_str.into() };
(@arg_names) => { &[#(stringify!(#arg_names).into()),* ] };
(@signature) => { fn(#(#arg_signatures),*) -> _ };
(@docs) => { std::borrow::Cow::Borrowed(#docs) };
(@deprecated) => { #deprecated };
(@no_return_type) => { #no_return_type };
(@export_fn; $function:path) => {
fn export(type_map: &mut #crate_ref::TypeMap) -> #crate_ref::functions::FunctionDataType {
specta::internal::get_fn_datatype(
$function as fn(#(#arg_signatures),*) -> _,
#function_asyncness,
#function_name_str.into(),
type_map,
&[#(stringify!(#arg_names).into()),* ],
std::borrow::Cow::Borrowed(#docs),
#deprecated,
#no_return_type,
)
}
}
}

#pub_the_trait
Expand Down
8 changes: 3 additions & 5 deletions src/functions/arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ use crate::{DataType, Type, TypeMap};

/// Implemented by types that can be used as an argument in a function annotated with
/// [`specta`](crate::specta).
pub trait FunctionArg<TMarker> {
pub trait FunctionArg {
/// Gets the type of an argument as a [`DataType`].
///
/// Some argument types should be ignored (eg Tauri command State),
/// Some argument types should be ignored (eg. when doing dependency injection),
/// so the value is optional.
fn to_datatype(type_map: &mut TypeMap) -> Option<DataType>;
}

pub enum FunctionArgMarker {}

impl<T: Type> FunctionArg<FunctionArgMarker> for T {
impl<T: Type> FunctionArg for T {
fn to_datatype(type_map: &mut TypeMap) -> Option<DataType> {
Some(T::reference(type_map, &[]).inner)
}
Expand Down
109 changes: 53 additions & 56 deletions src/functions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
mod arg;
mod result;
pub(crate) mod result;

use std::borrow::Cow;

pub use arg::FunctionArg;

pub(crate) use result::*;

use crate::*;

/// Returns a [`FunctionDataType`] for a given function that has been annotated with
/// [`specta`](macro@crate::specta).
///
Expand All @@ -34,16 +31,64 @@ use crate::*;
macro_rules! fn_datatype {
($function:path) => {{
let mut type_map = $crate::TypeMap::default();

$crate::fn_datatype!(type_map; $function)
}};
($type_map:ident; $function:path) => {{
let type_map: &mut $crate::TypeMap = &mut $type_map;
$crate::internal::internal_fn_datatype!($function);
result
}};
}

$crate::internal::fn_datatype!(type_map, $function)
/// Collects function types into a [`Vec`],
/// and all downstream types into a [`TypeMap`] instance.
///
/// Specifying a `type_map` argument allows a custom [`TypeMap`] to be used.
///
/// # Examples
///
/// ```rust
/// use specta::*;
///
/// #[specta]
/// fn some_function(name: String, age: i32) -> bool {
/// true
/// }
///
/// fn main() {
/// // `type_defs` is created internally
/// let (functions, type_defs) = functions::collect_functions![some_function];
///
/// let custom_type_defs = TypeMap::default();
///
/// // `type_defs` is provided.
/// // This can be used when integrating multiple specta-enabled libraries.
/// let (functions, custom_type_defs) = functions::collect_functions![
/// custom_type_defs; // You can provide a custom map to collect the types into
/// some_function
/// ];
/// }
/// ````
#[macro_export]
macro_rules! collect_functions {
($type_map:ident; $($command:path),* $(,)?) => {{
let mut type_map: $crate::TypeMap = $type_map;
([$($crate::fn_datatype!(type_map; $command)),*]
.into_iter()
.collect::<Vec<_>>(), type_map)
}};
($($command:path),* $(,)?) => {{
let mut type_map = $crate::TypeMap::default();
$crate::functions::collect_functions!(type_map; $($command),*)
}};
}

pub type CollectFunctionsResult = (Vec<FunctionDataType>, TypeMap);

pub use crate::collect_functions;
use crate::{DataType, DeprecatedType, TypeMap};

// TODO: Probs move this into the `DataType` module???
/// Contains type information about a function annotated with [`specta`](macro@crate::specta).
/// Returned by [`fn_datatype`].
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -105,9 +150,8 @@ macro_rules! impl_typed_command {
impl<
TResultMarker,
TResult: FunctionResult<TResultMarker>,
$([<$i Marker>]),*,
$($i: FunctionArg<[<$i Marker>]>),*
> Function<(TResultMarker, $([<$i Marker>]),*)> for fn($($i),*) -> TResult {
$($i: FunctionArg),*
> Function<TResultMarker> for fn($($i),*) -> TResult {
fn to_datatype(
asyncness: bool,
name: Cow<'static, str>,
Expand Down Expand Up @@ -149,50 +193,3 @@ macro_rules! impl_typed_command {
}

impl_typed_command!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);

/// Collects function types into a [`Vec`],
/// and all downstream types into a [`TypeMap`] instance.
///
/// Specifying a `type_map` argument allows a custom [`TypeMap`] to be used.
///
/// # Examples
///
/// ```rust
/// use specta::*;
///
/// #[specta]
/// fn some_function(name: String, age: i32) -> bool {
/// true
/// }
///
/// fn main() {
/// // `type_defs` is created internally
/// let (functions, type_defs) = functions::collect_functions![some_function];
///
/// let custom_type_defs = TypeMap::default();
///
/// // `type_defs` is provided.
/// // This can be used when integrating multiple specta-enabled libraries.
/// let (functions, custom_type_defs) = functions::collect_functions![
/// custom_type_defs; // You can provide a custom map to collect the types into
/// some_function
/// ];
/// }
/// ````
#[macro_export]
macro_rules! collect_functions {
($type_map:ident; $($command:path),* $(,)?) => {{
let mut type_map: $crate::TypeMap = $type_map;
([$($crate::fn_datatype!(type_map; $command)),*]
.into_iter()
.collect::<Vec<_>>(), type_map)
}};
($($command:path),* $(,)?) => {{
let mut type_map = $crate::TypeMap::default();
$crate::functions::collect_functions!(type_map; $($command),*)
}};
}

pub type CollectFunctionsResult = (Vec<FunctionDataType>, TypeMap);

pub use crate::collect_functions;
2 changes: 1 addition & 1 deletion src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::borrow::Cow;
pub use ctor;

#[cfg(feature = "functions")]
pub use specta_macros::fn_datatype;
pub use specta_macros::internal_fn_datatype;

use crate::{DataType, DeprecatedType, Field, Generics, SpectaID, Type, TypeMap};

Expand Down

0 comments on commit e7fb839

Please sign in to comment.