mod arg;
pub(crate) mod result;
use std::borrow::Cow;
pub use arg::FunctionArg;
pub(crate) use result::*;
#[macro_export]
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
}};
}
#[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::function::collect_functions!(type_map; $($command),*)
}};
}
pub type CollectFunctionsResult = (Vec<FunctionDataType>, TypeMap);
pub use crate::collect_functions;
use crate::{DataType, DeprecatedType, TypeMap};
#[derive(Debug, Clone)]
pub struct FunctionDataType {
pub asyncness: bool,
pub name: Cow<'static, str>,
pub args: Vec<(Cow<'static, str>, DataType)>,
pub result: Option<DataType>,
pub docs: Cow<'static, str>,
pub deprecated: Option<DeprecatedType>,
}
pub trait Function<TMarker> {
fn to_datatype(
asyncness: bool,
name: Cow<'static, str>,
type_map: &mut TypeMap,
fields: &[Cow<'static, str>],
docs: Cow<'static, str>,
deprecated: Option<DeprecatedType>,
no_return_type: bool,
) -> FunctionDataType;
}
impl<TResultMarker, TResult: FunctionResult<TResultMarker>> Function<TResultMarker>
for fn() -> TResult
{
fn to_datatype(
asyncness: bool,
name: Cow<'static, str>,
type_map: &mut TypeMap,
_fields: &[Cow<'static, str>],
docs: Cow<'static, str>,
deprecated: Option<DeprecatedType>,
no_return_type: bool,
) -> FunctionDataType {
FunctionDataType {
asyncness,
name,
args: vec![],
result: (!no_return_type).then(|| TResult::to_datatype(type_map)),
docs,
deprecated,
}
}
}
macro_rules! impl_typed_command {
( impl $($i:ident),* ) => {
paste::paste! {
impl<
TResultMarker,
TResult: FunctionResult<TResultMarker>,
$($i: FunctionArg),*
> Function<TResultMarker> for fn($($i),*) -> TResult {
fn to_datatype(
asyncness: bool,
name: Cow<'static, str>,
type_map: &mut TypeMap,
fields: &[Cow<'static, str>],
docs: Cow<'static, str>,
deprecated: Option<DeprecatedType>,
no_return_type: bool,
) -> FunctionDataType {
let mut fields = fields.into_iter();
FunctionDataType {
asyncness,
name,
docs,
deprecated,
args: [$(
fields
.next()
.map_or_else(
|| None,
|field| $i::to_datatype(type_map).map(|ty| (field.clone(), ty))
)
),*,]
.into_iter()
.filter_map(|v| v)
.collect::<Vec<_>>(),
result: (!no_return_type).then(|| TResult::to_datatype(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);