#[macro_export]
macro_rules! extern_methods {
(
$(
$(#[$impl_m:meta])*
unsafe impl<$($t:ident $(: $b:ident $(+ $rest:ident)*)?),* $(,)?> $type:ty {
$($methods:tt)*
}
)+
) => {
$(
$(#[$impl_m])*
impl<$($t $(: $b $(+ $rest)*)?),*> $type {
$crate::__inner_extern_methods! {
@rewrite_methods
$($methods)*
}
}
)+
};
(
$(
$(#[$impl_m:meta])*
unsafe impl $type:ty {
$($methods:tt)*
}
)+
) => {
$(
$(#[$impl_m])*
impl $type {
$crate::__inner_extern_methods! {
@rewrite_methods
$($methods)*
}
}
)+
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __inner_extern_methods {
{@rewrite_methods} => {};
{
@rewrite_methods
$(#[$($m:tt)*])*
$v:vis unsafe fn $name:ident($($args:tt)*) $(-> $ret:ty)?;
$($rest:tt)*
} => {
$crate::__rewrite_self_arg! {
($crate::__inner_extern_methods)
($($args)*)
@method_out
@($(#[$($m)*])*)
@($v unsafe fn $name($($args)*) $(-> $ret)?)
}
$crate::__inner_extern_methods! {
@rewrite_methods
$($rest)*
}
};
{
@rewrite_methods
$(#[$($m:tt)*])*
$v:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?;
$($rest:tt)*
} => {
$crate::__rewrite_self_arg! {
($crate::__inner_extern_methods)
($($args)*)
@method_out
@($(#[$($m)*])*)
@($v fn $name($($args)*) $(-> $ret)?)
}
$crate::__inner_extern_methods! {
@rewrite_methods
$($rest)*
}
};
{
@rewrite_methods
$associated_item:item
$($rest:tt)*
} => {
$associated_item
$crate::__inner_extern_methods! {
@rewrite_methods
$($rest)*
}
};
{
@method_out
@($(#[$($m:tt)*])*)
@($($function_start:tt)*)
@($($kind:tt)*)
@($($args_start:tt)*)
@($($args_rest:tt)*)
} => {
$crate::__strip_custom_attributes! {
@($(#[$($m)*])*)
@($($function_start)* {
#[allow(unused_unsafe)]
unsafe {
$crate::__extract_custom_attributes! {
@($(#[$($m)*])*)
@($crate::__inner_extern_methods)
@(
@unsafe_method_body
@($($kind)*)
@($($args_start)*)
@($($args_rest)*)
)
@()
@()
}
}
})
@()
}
};
{
@unsafe_method_body
@($kind:ident)
@($($args_start:tt)*)
@($($args_rest:tt)*)
@(#[method($($sel:tt)*)])
@() } => {
$crate::__collect_msg_send! {
$crate::msg_send;
$crate::__inner_extern_methods!(
@get_receiver
@($kind)
@($($args_start)*)
);
($($sel)*);
($($args_rest)*);
}
};
{
@unsafe_method_body
@($kind:ident)
@($($args_start:tt)*)
@($($args_rest:tt)*)
@(#[method_id($($sel:tt)*)])
@() } => {
$crate::__collect_msg_send! {
$crate::msg_send_id;
$crate::__inner_extern_methods!(
@get_receiver
@($kind)
@($($args_start)*)
);
($($sel)*);
($($args_rest)*);
}
};
{
@unsafe_method_body
@($kind:ident)
@($($args_start:tt)*)
@($($args_rest:tt)*)
@($($m_method:tt)*)
@($($m_optional:tt)*)
} => {
compile_error!("`#[optional]` is only supported in `extern_protocol!`")
};
{
@get_receiver
@(instance_method)
@(
$self_or_this:ident: $self_or_this_ty:ty,
_: $sel_ty:ty,
)
} => {
$self_or_this
};
{
@get_receiver
@(class_method)
@(
_: $cls_ty:ty,
_: $sel_ty:ty,
)
} => {
Self::class()
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __collect_msg_send {
(
$macro:path;
$obj:expr;
($(@__retain_semantics $retain_semantics:ident )? $sel:ident);
();
) => {{
$macro![$obj, $(@__retain_semantics $retain_semantics )? $sel]
}};
(
$macro:path;
$obj:expr;
();
();
$($output:tt)+
) => {{
$macro![$obj, $($output)+]
}};
(
$macro:path;
$obj:expr;
($(@__retain_semantics $retain_semantics:ident )? $sel:ident:);
($(,)?);
$($output:tt)*
) => {
$crate::__collect_msg_send! {
$macro;
$obj;
();
();
$($output)* $(@__retain_semantics $retain_semantics )? $sel: _,
}
};
(
$macro:path;
$obj:expr;
($(@__retain_semantics $retain_semantics:ident )? $sel:ident : $($sel_rest:tt)*);
($arg:ident: $arg_ty:ty $(, $($args_rest:tt)*)?);
$($output:tt)*
) => {
$crate::__collect_msg_send! {
$macro;
$obj;
($($sel_rest)*);
($($($args_rest)*)?);
$($output)* $(@__retain_semantics $retain_semantics )? $sel: $arg,
}
};
($($_any:tt)*) => {{
compile_error!("Number of arguments in function and selector did not match!")
}};
}