#[doc(alias = "@interface")]
#[doc(alias = "@implementation")]
#[macro_export]
macro_rules! declare_class {
{
$(#[$m:meta])*
$v:vis struct $name:ident {
$($fields:tt)*
}
$ivar_helper_module_v:vis mod $ivar_helper_module:ident;
unsafe impl ClassType for $for:ty {
$(#[inherits($($inheritance_rest:ty),+)])?
type Super = $superclass:ty;
type Mutability = $mutability:ty;
const NAME: &'static str = $name_const:expr;
}
$($methods:tt)*
} => {
$crate::__emit_struct_and_ivars! {
($(#[$m])*)
($v)
($name)
($ivar_helper_module_v mod $ivar_helper_module)
($($fields)*)
(
__superclass: $crate::__macro_helpers::ManuallyDrop<$superclass>,
)
}
$crate::__inner_declare_class! {
($ivar_helper_module)
unsafe impl ClassType for $for {
$(#[inherits($($inheritance_rest),+)])?
type Super = $superclass;
type Mutability = $mutability;
const NAME: &'static str = $name_const;
}
$($methods)*
}
};
{
$(#[$m:meta])*
$v:vis struct $name:ident {
$($fields:tt)*
}
unsafe impl ClassType for $for:ty {
$(#[inherits($($inheritance_rest:ty),+)])?
type Super = $superclass:ty;
type Mutability = $mutability:ty;
const NAME: &'static str = $name_const:expr;
}
$($methods:tt)*
} => {
$crate::__emit_struct_and_ivars! {
($(#[$m])*)
($v)
($name)
()
($($fields)*)
(
__superclass: $crate::__macro_helpers::ManuallyDrop<$superclass>,
)
}
$crate::__inner_declare_class! {
()
unsafe impl ClassType for $for {
$(#[inherits($($inheritance_rest),+)])?
type Super = $superclass;
type Mutability = $mutability;
const NAME: &'static str = $name_const;
}
$($methods)*
}
};
{
$(#[$m:meta])*
$v:vis struct $name:ident;
unsafe impl ClassType for $for:ty {
$(#[inherits($($inheritance_rest:ty),+)])?
type Super = $superclass:ty;
type Mutability = $mutability:ty;
const NAME: &'static str = $name_const:expr;
}
$($methods:tt)*
} => {
$crate::__emit_struct_and_ivars! {
($(#[$m])*)
($v)
($name)
()
()
(
__superclass: $crate::__macro_helpers::ManuallyDrop<$superclass>,
)
}
$crate::__inner_declare_class! {
()
unsafe impl ClassType for $for {
$(#[inherits($($inheritance_rest),+)])?
type Super = $superclass;
type Mutability = $mutability;
const NAME: &'static str = $name_const;
}
$($methods)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __inner_declare_class {
{
($($ivar_helper_module:ident)?)
unsafe impl ClassType for $for:ty {
$(#[inherits($($inheritance_rest:ty),+)])?
type Super = $superclass:ty;
type Mutability = $mutability:ty;
const NAME: &'static str = $name_const:expr;
}
$($methods:tt)*
} => {
$crate::__extern_class_impl_traits! {
unsafe impl () for $for {
INHERITS = [$superclass, $($($inheritance_rest,)+)? $crate::runtime::AnyObject];
fn as_super(&self) {
&*self.__superclass
}
fn as_super_mut(&mut self) {
&mut *self.__superclass
}
}
}
unsafe impl ClassType for $for {
type Super = $superclass;
type Mutability = $mutability;
const NAME: &'static $crate::__macro_helpers::str = $name_const;
fn class() -> &'static $crate::runtime::AnyClass {
$crate::__macro_helpers::assert_mutability_matches_superclass_mutability::<Self>();
static REGISTER_CLASS: $crate::__macro_helpers::Once = $crate::__macro_helpers::Once::new();
REGISTER_CLASS.call_once(|| {
let __objc2_superclass = <$superclass as $crate::ClassType>::class();
let mut __objc2_builder = $crate::declare::ClassBuilder::new(
<Self as ClassType>::NAME,
__objc2_superclass,
).unwrap_or_else(|| {
$crate::__macro_helpers::panic!(
"could not create new class {}. Perhaps a class with that name already exists?",
<Self as ClassType>::NAME,
)
});
$($ivar_helper_module::__objc2_declare_ivars(&mut __objc2_builder);)?
unsafe extern "C" fn __objc2_dealloc(__objc2_self: *mut $for, __objc2_cmd: $crate::runtime::Sel) {
unsafe { $crate::__macro_helpers::drop_in_place(__objc2_self) };
unsafe {
$crate::MessageReceiver::__send_super_message_static(
__objc2_self,
__objc2_cmd, (), )
}
}
if $crate::__macro_helpers::needs_drop::<Self>() {
unsafe {
__objc2_builder.add_method(
$crate::sel!(dealloc),
__objc2_dealloc as unsafe extern "C" fn(_, _),
);
}
}
$crate::__declare_class_register_methods! {
(__objc2_builder)
$($methods)*
}
let _cls = __objc2_builder.register();
});
$crate::runtime::AnyClass::get(<Self as ClassType>::NAME).unwrap()
}
#[inline]
fn as_super(&self) -> &Self::Super {
&*self.__superclass
}
#[inline]
fn as_super_mut(&mut self) -> &mut Self::Super {
&mut *self.__superclass
}
}
$crate::__declare_class_methods! {
$($methods)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __select_name {
($_name:ident; $name_const:expr) => {
$name_const
};
($name:ident;) => {
$crate::__macro_helpers::stringify!($name)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_methods {
() => {};
(
$(#[$m:meta])*
unsafe impl $protocol:ident for $for:ty {
$($methods:tt)*
}
$($rest:tt)*
) => {
$(#[$m])*
unsafe impl $protocol for $for {}
$(#[$m])*
impl $for {
$crate::__declare_class_rewrite_methods! {
($crate::__declare_class_method_out)
()
$($methods)*
}
}
$crate::__declare_class_methods!{
$($rest)*
}
};
(
$(#[$m:meta])*
unsafe impl $for:ty {
$($methods:tt)*
}
$($rest:tt)*
) => {
$(#[$m])*
impl $for {
$crate::__declare_class_rewrite_methods! {
($crate::__declare_class_method_out)
()
$($methods)*
}
}
$crate::__declare_class_methods! {
$($rest)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_register_methods {
(
($builder:ident)
) => {};
(
($builder:ident)
$(#[$($m:tt)*])*
unsafe impl $protocol:ident for $for:ty {
$($methods:tt)*
}
$($rest:tt)*
) => {
$crate::__extract_and_apply_cfg_attributes! {
@($(#[$($m)*])*)
@(
#[allow(unused_mut)]
let mut __objc2_protocol_builder = $builder.__add_protocol_methods(
<dyn $protocol as $crate::ProtocolType>::protocol()
);
#[allow(deprecated)]
#[allow(unused_unsafe)]
unsafe {
$crate::__declare_class_rewrite_methods! {
($crate::__declare_class_register_out)
(__objc2_protocol_builder)
$($methods)*
}
}
__objc2_protocol_builder.__finish();
)
}
$crate::__declare_class_register_methods! {
($builder)
$($rest)*
}
};
(
($builder:ident)
$(#[$($m:tt)*])*
unsafe impl $for:ty {
$($methods:tt)*
}
$($rest:tt)*
) => {
$crate::__extract_and_apply_cfg_attributes! {
@($(#[$($m)*])*)
@(
#[allow(deprecated)]
#[allow(unused_unsafe)]
unsafe {
$crate::__declare_class_rewrite_methods! {
($crate::__declare_class_register_out)
($builder)
$($methods)*
}
}
)
}
$crate::__declare_class_register_methods! {
($builder)
$($rest)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_rewrite_methods {
{
($out_macro:path)
($($macro_arg:tt)*)
} => {};
{
($out_macro:path)
($($macro_arg:tt)*)
$(#[$($m:tt)*])*
unsafe fn $name:ident($($args:tt)*) $(-> $ret:ty)? $body:block
$($rest:tt)*
} => {
$crate::__rewrite_self_arg! {
($($args)*)
($crate::__extract_custom_attributes)
($(#[$($m)*])*)
($name)
($out_macro)
($($macro_arg)*)
(unsafe)
($name)
($($ret)?)
($body)
}
$crate::__declare_class_rewrite_methods! {
($out_macro)
($($macro_arg)*)
$($rest)*
}
};
{
($out_macro:path)
($($macro_arg:tt)*)
$(#[$($m:tt)*])*
fn $name:ident($($args:tt)*) $(-> $ret:ty)? $body:block
$($rest:tt)*
} => {
$crate::__rewrite_self_arg! {
($($args)*)
($crate::__extract_custom_attributes)
($(#[$($m)*])*)
($name)
($out_macro)
($($macro_arg)*)
()
($name)
($($ret)?)
($body)
}
$crate::__declare_class_rewrite_methods! {
($out_macro)
($($macro_arg)*)
$($rest)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_method_out {
{
()
($($qualifiers:tt)*)
($name:ident)
($($ret:ty)?)
($body:block)
($builder_method:ident)
($receiver:expr)
($receiver_ty:ty)
($($args_prefix:tt)*)
($($args_rest:tt)*)
($($m_method:tt)*)
($($m_optional:tt)*)
($($m_checked:tt)*)
} => {
$crate::__declare_class_rewrite_args! {
($($args_rest)*)
()
()
($crate::__declare_class_method_out_inner)
($($qualifiers)*)
($name)
($($ret)?)
($body)
($builder_method)
($receiver)
($receiver_ty)
($($args_prefix)*)
($($m_method)*)
($($m_optional)*)
($($m_checked)*)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_rewrite_args {
{
(_ : $param_ty:ty $(, $($rest_args:tt)*)?)
($($args_converted:tt)*)
($($body_prefix:tt)*)
($out_macro:path)
$($macro_args:tt)*
} => {
$crate::__declare_class_rewrite_args! {
($($($rest_args)*)?)
($($args_converted)* _ : <$param_ty as $crate::encode::__unstable::EncodeConvertArgument>::__Inner,)
($($body_prefix)*)
($out_macro)
$($macro_args)*
}
};
{
(mut $param:ident : $param_ty:ty $(, $($rest_args:tt)*)?)
($($args_converted:tt)*)
($($body_prefix:tt)*)
($out_macro:path)
$($macro_args:tt)*
} => {
$crate::__declare_class_rewrite_args! {
($($($rest_args)*)?)
($($args_converted)* $param : <$param_ty as $crate::encode::__unstable::EncodeConvertArgument>::__Inner,)
(
$($body_prefix)*
let mut $param = <$param_ty as $crate::encode::__unstable::EncodeConvertArgument>::__from_declared_param($param);
)
($out_macro)
$($macro_args)*
}
};
{
($param:ident : $param_ty:ty $(, $($rest_args:tt)*)?)
($($args_converted:tt)*)
($($body_prefix:tt)*)
($out_macro:path)
$($macro_args:tt)*
} => {
$crate::__declare_class_rewrite_args! {
($($($rest_args)*)?)
($($args_converted)* $param : <$param_ty as $crate::encode::__unstable::EncodeConvertArgument>::__Inner,)
(
$($body_prefix)*
let $param = <$param_ty as $crate::encode::__unstable::EncodeConvertArgument>::__from_declared_param($param);
)
($out_macro)
$($macro_args)*
}
};
{
()
($($args_converted:tt)*)
($($body_prefix:tt)*)
($out_macro:path)
$($macro_args:tt)*
} => {
$out_macro! {
$($macro_args)*
($($args_converted)*)
($($body_prefix)*)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_method_out_inner {
{
($($qualifiers:tt)*)
($name:ident)
($($ret:ty)?)
($body:block)
($__builder_method:ident)
($__receiver:expr)
($__receiver_ty:ty)
($($args_prefix:tt)*)
(#[method($($__sel:tt)*)])
($($__m_optional:tt)*)
($($m_checked:tt)*)
($($args_converted:tt)*)
($($body_prefix:tt)*)
} => {
$($m_checked)*
$($qualifiers)* extern "C" fn $name(
$($args_prefix)*
$($args_converted)*
) $(-> <$ret as $crate::encode::__unstable::EncodeConvertReturn>::__Inner)? {
$($body_prefix)*
$crate::__convert_result! {
$body $(; $ret)?
}
}
};
{
($($qualifiers:tt)*)
($name:ident)
($ret:ty)
($body:block)
($__builder_method:ident)
($__receiver:expr)
($receiver_ty:ty)
($($args_prefix:tt)*)
(#[method_id($($sel:tt)*)])
($($__m_optional:tt)*)
($($m_checked:tt)*)
($($args_converted:tt)*)
($($body_prefix:tt)*)
} => {
$($m_checked)*
$($qualifiers)* extern "C" fn $name(
$($args_prefix)*
$($args_converted)*
) -> $crate::declare::__IdReturnValue {
$($body_prefix)*
let __objc2_result = $body;
#[allow(unreachable_code)]
<$crate::__macro_helpers::RetainSemantics<{
$crate::__macro_helpers::retain_semantics(
$crate::__sel_helper! {
@()
$($sel)*
}
)
}> as $crate::__macro_helpers::MessageRecieveId<
$receiver_ty,
$ret,
>>::into_return(__objc2_result)
}
};
{
($($qualifiers:tt)*)
($name:ident)
()
($body:block)
($__builder_method:ident)
($__receiver:expr)
($__receiver_ty:ty)
($($args_prefix:tt)*)
(#[method_id($($sel:tt)*)])
($($__m_optional:tt)*)
($($m_checked:tt)*)
($($args_converted:tt)*)
($($body_prefix:tt)*)
} => {
$($m_checked)*
$($qualifiers)* extern "C" fn $name() {
compile_error!("`#[method_id(...)]` must have a return type")
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __convert_result {
($body:block) => {
$body
};
($body:block; $ret:ty) => {
let __objc2_result = $body;
#[allow(unreachable_code)]
<$ret as $crate::encode::__unstable::EncodeConvertReturn>::__into_declared_return(
__objc2_result,
)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_register_out {
{
($builder:ident)
($($qualifiers:tt)*)
($name:ident)
($($__ret:ty)?)
($__body:block)
($builder_method:ident)
($__receiver:expr)
($__receiver_ty:ty)
($($__args_prefix:tt)*)
($($args_rest:tt)*)
(#[method(dealloc)])
() ($($m_checked:tt)*)
} => {
$crate::__extract_and_apply_cfg_attributes! {
@($($m_checked)*)
@($crate::__macro_helpers::compile_error!(
"`#[method(dealloc)]` is not supported. Implement `Drop` for the type instead"
))
}
};
{
($builder:ident)
($($qualifiers:tt)*)
($name:ident)
($($__ret:ty)?)
($__body:block)
($builder_method:ident)
($__receiver:expr)
($__receiver_ty:ty)
($($__args_prefix:tt)*)
($($args_rest:tt)*)
(#[method($($sel:tt)*)])
() ($($m_checked:tt)*)
} => {
$crate::__extract_and_apply_cfg_attributes! {
@($($m_checked)*)
@(
$builder.$builder_method(
$crate::sel!($($sel)*),
Self::$name as $crate::__fn_ptr! {
($($qualifiers)*)
(_, _,)
$($args_rest)*
},
);
)
}
};
{
($builder:ident)
($($qualifiers:tt)*)
($name:ident)
($($__ret:ty)?)
($__body:block)
($builder_method:ident)
($__receiver:expr)
($__receiver_ty:ty)
($($__args_prefix:tt)*)
($($args_rest:tt)*)
(#[method_id($($sel:tt)*)])
() ($($m_checked:tt)*)
} => {
$crate::__extract_and_apply_cfg_attributes! {
@($($m_checked)*)
@(
$builder.$builder_method(
$crate::__get_method_id_sel!($($sel)*),
Self::$name as $crate::__fn_ptr! {
($($qualifiers)*)
(_, _,)
$($args_rest)*
},
);
)
}
};
{
($builder:ident)
($($qualifiers:tt)*)
($name:ident)
($($__ret:ty)?)
($__body:block)
($builder_method:ident)
($__receiver:expr)
($__receiver_ty:ty)
($($__args_prefix:tt)*)
($($args_rest:tt)*)
($($m_method:tt)*)
($($m_optional:tt)*)
($($m_checked:tt)*)
} => {
compile_error!("`#[optional]` is only supported in `extern_protocol!`")
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __get_method_id_sel {
(alloc) => {
compile_error!(concat!(
"`#[method_id(alloc)]` is not supported. ",
"Use `#[method(alloc)]` and do the memory management yourself",
))
};
(retain) => {
compile_error!(concat!(
"`#[method_id(retain)]` is not supported. ",
"Use `#[method(retain)]` and do the memory management yourself",
))
};
(release) => {
compile_error!(concat!(
"`#[method_id(release)]` is not supported. ",
"Use `#[method(release)]` and do the memory management yourself",
))
};
(autorelease) => {
compile_error!(concat!(
"`#[method_id(autorelease)]` is not supported. ",
"Use `#[method(autorelease)]` and do the memory management yourself",
))
};
(dealloc) => {
compile_error!(concat!(
"`#[method_id(dealloc)]` is not supported. ",
"Add an instance variable with a `Drop` impl to the class instead",
))
};
($($t:tt)*) => {
$crate::sel!($($t)*)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __fn_ptr {
(
($($qualifiers:tt)*)
($($output:tt)*)
$(,)?
) => {
$($qualifiers)* extern "C" fn($($output)*) -> _
};
(
($($qualifiers:tt)*)
($($output:tt)*)
_ : $param_ty:ty $(, $($rest:tt)*)?
) => {
$crate::__fn_ptr! {
($($qualifiers)*)
($($output)* _,)
$($($rest)*)?
}
};
(
($($qualifiers:tt)*)
($($output:tt)*)
mut $param:ident : $param_ty:ty $(, $($rest:tt)*)?
) => {
$crate::__fn_ptr! {
($($qualifiers)*)
($($output)* _,)
$($($rest)*)?
}
};
(
($($qualifiers:tt)*)
($($output:tt)*)
$param:ident : $param_ty:ty $(, $($rest:tt)*)?
) => {
$crate::__fn_ptr! {
($($qualifiers)*)
($($output)* _,)
$($($rest)*)?
}
};
}