mod arg;
mod result;
#[cfg(feature = "tauri")]
mod tauri;
#[cfg(feature = "tauri")]
pub use self::tauri::*;
pub use arg::*;
pub use result::*;
use crate::*;
#[macro_export]
macro_rules! fn_datatype {
($function:path) => {{
let mut type_map = $crate::TypeDefs::default();
$crate::fn_datatype!(type_map, $function)
}};
($type_map:ident, $function:path) => {{
let type_map: &mut $crate::TypeDefs = &mut $type_map;
$crate::internal::fn_datatype!(type_map, $function)
}};
}
#[derive(Debug, Clone)]
pub struct FunctionDataType {
pub asyncness: bool,
pub name: &'static str,
pub args: Vec<(&'static str, DataType)>,
pub result: DataType,
pub docs: Vec<&'static str>,
}
pub trait SpectaFunction<TMarker> {
fn to_datatype(
asyncness: bool,
name: &'static str,
type_map: &mut TypeDefs,
fields: &[&'static str],
docs: Vec<&'static str>,
) -> Result<FunctionDataType, ExportError>;
}
impl<TResultMarker, TResult: SpectaFunctionResult<TResultMarker>> SpectaFunction<TResultMarker>
for fn() -> TResult
{
fn to_datatype(
asyncness: bool,
name: &'static str,
type_map: &mut TypeDefs,
_fields: &[&'static str],
docs: Vec<&'static str>,
) -> Result<FunctionDataType, ExportError> {
TResult::to_datatype(DefOpts {
parent_inline: false,
type_map,
})
.map(|result| FunctionDataType {
asyncness,
name,
args: vec![],
result,
docs,
})
}
}
#[doc(hidden)]
pub fn get_datatype_internal<TMarker, T: SpectaFunction<TMarker>>(
_: T,
asyncness: bool,
name: &'static str,
type_map: &mut TypeDefs,
fields: &[&'static str],
docs: Vec<&'static str>,
) -> Result<FunctionDataType, ExportError> {
T::to_datatype(asyncness, name, type_map, fields, docs)
}
macro_rules! impl_typed_command {
( impl $($i:ident),* ) => {
paste::paste! {
impl<
TResultMarker,
TResult: SpectaFunctionResult<TResultMarker>,
$([<$i Marker>]),*,
$($i: SpectaFunctionArg<[<$i Marker>]>),*
> SpectaFunction<(TResultMarker, $([<$i Marker>]),*)> for fn($($i),*) -> TResult {
fn to_datatype(
asyncness: bool,
name: &'static str,
type_map: &mut TypeDefs,
fields: &[&'static str],
docs: Vec<&'static str>,
) -> Result<FunctionDataType, ExportError> {
let mut fields = fields.into_iter();
Ok(FunctionDataType {
asyncness,
name,
docs,
args: [$(
fields
.next()
.map_or_else(
|| Ok(None),
|field| $i::to_datatype(DefOpts {
parent_inline: false,
type_map,
}).map(|v| v.map(|ty| (*field, ty)))
)?
),*,]
.into_iter()
.filter_map(|v| v)
.collect(),
result: TResult::to_datatype(DefOpts {
parent_inline: false,
type_map,
})?,
})
}
}
}
};
( $i2:ident $(, $i:ident)* ) => {
impl_typed_command!(impl $i2 $(, $i)* );
impl_typed_command!($($i),*);
};
() => {};
}
impl_typed_command!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
#[macro_export]
macro_rules! collect_types {
(type_map: $type_map:ident, $($command:path),* $(,)?) => {{
let mut type_map: $crate::TypeDefs = $type_map;
{
fn export(mut type_map: $crate::TypeDefs) -> ::std::result::Result<(Vec<$crate::functions::FunctionDataType>, $crate::TypeDefs), $crate::ExportError> {
Ok((
vec![
$($crate::fn_datatype!(type_map, $command)?),*
],
type_map,
))
}
export(type_map)
}
}};
($($command:path),* $(,)?) => {{
let mut type_map = $crate::TypeDefs::default();
$crate::functions::collect_types!(type_map: type_map, $($command),*)
}};
}
pub use collect_types;