#[doc(alias = "@interface")]
#[doc(alias = "@implementation")]
#[macro_export]
macro_rules! declare_class {
{
$(#[$m:meta])*
$v:vis struct $name:ident;
unsafe impl ClassType for $for_class:ty {
$(#[inherits($($inheritance_rest:ty),+)])?
type Super = $superclass:ty;
type Mutability = $mutability:ty;
const NAME: &'static str = $name_const:expr;
}
impl DeclaredClass for $for_declared:ty {
$(type Ivars = $ivars:ty;)?
}
$($impls:tt)*
} => {
$(#[$m])*
#[repr(C)]
$v struct $name {
// Superclasses are deallocated by calling `[super dealloc]`.
__superclass: $crate::__macro_helpers::ManuallyDrop<$superclass>,
__ivars: $crate::__macro_helpers::PhantomData<<Self as $crate::DeclaredClass>::Ivars>,
}
$crate::__extern_class_impl_traits! {
unsafe impl () for $for_class {
INHERITS = [$superclass, $($($inheritance_rest,)+)? $crate::runtime::AnyObject];
fn as_super(&self) {
&*self.__superclass
}
fn as_super_mut(&mut self) {
&mut *self.__superclass
}
}
}
const _: () = {
static mut __OBJC2_CLASS: $crate::__macro_helpers::MaybeUninit<&'static $crate::runtime::AnyClass> = $crate::__macro_helpers::MaybeUninit::uninit();
static mut __OBJC2_IVAR_OFFSET: $crate::__macro_helpers::MaybeUninit<$crate::__macro_helpers::isize> = $crate::__macro_helpers::MaybeUninit::uninit();
static mut __OBJC2_DROP_FLAG_OFFSET: $crate::__macro_helpers::MaybeUninit<$crate::__macro_helpers::isize> = $crate::__macro_helpers::MaybeUninit::uninit();
unsafe impl ClassType for $for_class {
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 mut __objc2_builder = $crate::__macro_helpers::ClassBuilderHelper::<Self>::new();
$crate::__declare_class_register_impls! {
(__objc2_builder)
$($impls)*
}
let (__objc2_cls, __objc2_ivar_offset, __objc2_drop_flag_offset) = __objc2_builder.register();
unsafe {
__OBJC2_CLASS.write(__objc2_cls);
if <Self as $crate::__macro_helpers::DeclaredIvarsHelper>::HAS_IVARS {
__OBJC2_IVAR_OFFSET.write(__objc2_ivar_offset);
}
if <Self as $crate::__macro_helpers::DeclaredIvarsHelper>::HAS_DROP_FLAG {
__OBJC2_DROP_FLAG_OFFSET.write(__objc2_drop_flag_offset);
}
}
});
unsafe { __OBJC2_CLASS.assume_init() }
}
#[inline]
fn as_super(&self) -> &Self::Super {
&*self.__superclass
}
#[inline]
fn as_super_mut(&mut self) -> &mut Self::Super {
&mut *self.__superclass
}
}
impl DeclaredClass for $for_declared {
type Ivars = $crate::__select_ivars!($($ivars)?);
#[inline]
fn __ivars_offset() -> $crate::__macro_helpers::isize {
if <Self as $crate::__macro_helpers::DeclaredIvarsHelper>::HAS_IVARS {
unsafe { __OBJC2_IVAR_OFFSET.assume_init() }
} else {
0
}
}
#[inline]
fn __drop_flag_offset() -> $crate::__macro_helpers::isize {
if <Self as $crate::__macro_helpers::DeclaredIvarsHelper>::HAS_DROP_FLAG {
unsafe { __OBJC2_DROP_FLAG_OFFSET.assume_init() }
} else {
0
}
}
const __UNSAFE_OFFSETS_CORRECT: () = ();
}
};
$crate::__declare_class_output_impls! {
$($impls)*
}
};
}
#[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! __select_ivars {
($ivars:ty) => {
$ivars
};
() => {
()
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_output_impls {
() => {};
(
$(#[$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_output_methods! {
$($methods)*
}
}
$crate::__declare_class_output_impls!{
$($rest)*
}
};
(
$(#[$m:meta])*
unsafe impl $for:ty {
$($methods:tt)*
}
$($rest:tt)*
) => {
$(#[$m])*
impl $for {
$crate::__declare_class_output_methods! {
$($methods)*
}
}
$crate::__declare_class_output_impls! {
$($rest)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_output_methods {
{} => {};
{
$(#[$($m:tt)*])*
unsafe fn $name:ident($($params:tt)*) $(-> $ret:ty)? $body:block
$($rest:tt)*
} => {
$crate::__rewrite_self_param! {
($($params)*)
($crate::__extract_custom_attributes)
($(#[$($m)*])*)
($crate::__declare_class_method_out)
(unsafe)
($name)
($($ret)?)
($body)
}
$crate::__declare_class_output_methods! {
$($rest)*
}
};
{
$(#[$($m:tt)*])*
fn $name:ident($($params:tt)*) $(-> $ret:ty)? $body:block
$($rest:tt)*
} => {
$crate::__rewrite_self_param! {
($($params)*)
($crate::__extract_custom_attributes)
($(#[$($m)*])*)
($crate::__declare_class_method_out)
()
($name)
($($ret)?)
($body)
}
$crate::__declare_class_output_methods! {
$($rest)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_register_impls {
(
($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>();
#[allow(deprecated)]
#[allow(unused_unsafe)]
unsafe {
$crate::__declare_class_register_methods! {
(__objc2_protocol_builder)
$($methods)*
}
}
__objc2_protocol_builder.finish();
}
$crate::__declare_class_register_impls! {
($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_register_methods! {
($builder)
$($methods)*
}
}
}
$crate::__declare_class_register_impls! {
($builder)
$($rest)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_register_methods {
{
($builder:ident)
} => {};
{
($builder:ident)
$(#[$($m:tt)*])*
unsafe fn $name:ident($($params:tt)*) $(-> $ret:ty)? $body:block
$($rest:tt)*
} => {
$crate::__rewrite_self_param! {
($($params)*)
($crate::__extract_custom_attributes)
($(#[$($m)*])*)
($crate::__declare_class_register_out)
($builder)
(unsafe)
($name)
($($ret)?)
($body)
}
$crate::__declare_class_register_methods! {
($builder)
$($rest)*
}
};
{
($builder:ident)
$(#[$($m:tt)*])*
fn $name:ident($($params:tt)*) $(-> $ret:ty)? $body:block
$($rest:tt)*
} => {
$crate::__rewrite_self_param! {
($($params)*)
($crate::__extract_custom_attributes)
($(#[$($m)*])*)
($crate::__declare_class_register_out)
($builder)
()
($name)
($($ret)?)
($body)
}
$crate::__declare_class_register_methods! {
($builder)
$($rest)*
}
};
{
($builder:ident)
$_associated_item:item
$($rest:tt)*
} => {
$crate::__declare_class_output_methods! {
($builder)
$($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)
($($params_prefix:tt)*)
($($params_rest:tt)*)
($($m_method:tt)*)
($($retain_semantics:tt)*)
($($m_optional:tt)*)
($($m_checked:tt)*)
} => {
$crate::__declare_class_rewrite_params! {
($($params_rest)*)
()
()
($crate::__declare_class_method_out_inner)
($($qualifiers)*)
($name)
($($ret)?)
($body)
($builder_method)
($receiver)
($receiver_ty)
($($params_prefix)*)
($($m_method)*)
($($retain_semantics)*)
($($m_optional)*)
($($m_checked)*)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_rewrite_params {
{
(_ : $param_ty:ty $(, $($params_rest:tt)*)?)
($($params_converted:tt)*)
($($body_prefix:tt)*)
($out_macro:path)
$($macro_args:tt)*
} => {
$crate::__declare_class_rewrite_params! {
($($($params_rest)*)?)
($($params_converted)* _ : <$param_ty as $crate::__macro_helpers::ConvertArgument>::__Inner,)
($($body_prefix)*)
($out_macro)
$($macro_args)*
}
};
{
(mut $param:ident : $param_ty:ty $(, $($params_rest:tt)*)?)
($($params_converted:tt)*)
($($body_prefix:tt)*)
($out_macro:path)
$($macro_args:tt)*
} => {
$crate::__declare_class_rewrite_params! {
($($($params_rest)*)?)
($($params_converted)* $param : <$param_ty as $crate::__macro_helpers::ConvertArgument>::__Inner,)
(
$($body_prefix)*
let mut $param = <$param_ty as $crate::__macro_helpers::ConvertArgument>::__from_declared_param($param);
)
($out_macro)
$($macro_args)*
}
};
{
($param:ident : $param_ty:ty $(, $($params_rest:tt)*)?)
($($params_converted:tt)*)
($($body_prefix:tt)*)
($out_macro:path)
$($macro_args:tt)*
} => {
$crate::__declare_class_rewrite_params! {
($($($params_rest)*)?)
($($params_converted)* $param : <$param_ty as $crate::__macro_helpers::ConvertArgument>::__Inner,)
(
$($body_prefix)*
let $param = <$param_ty as $crate::__macro_helpers::ConvertArgument>::__from_declared_param($param);
)
($out_macro)
$($macro_args)*
}
};
{
()
($($params_converted:tt)*)
($($body_prefix:tt)*)
($out_macro:path)
$($macro_args:tt)*
} => {
$out_macro! {
$($macro_args)*
($($params_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)
($($params_prefix:tt)*)
(#[method($($__sel:tt)*)])
()
($($__m_optional:tt)*)
($($m_checked:tt)*)
($($params_converted:tt)*)
($($body_prefix:tt)*)
} => {
$($m_checked)*
#[allow(clippy::diverging_sub_expression)]
$($qualifiers)* extern "C" fn $name(
$($params_prefix)*
$($params_converted)*
) $(-> <$ret as $crate::__macro_helpers::ConvertReturn>::__Inner)? {
$($body_prefix)*
$crate::__convert_result! {
$body $(; $ret)?
}
}
};
{
($($qualifiers:tt)*)
($name:ident)
($ret:ty)
($body:block)
($__builder_method:ident)
($__receiver:expr)
($receiver_ty:ty)
($($params_prefix:tt)*)
(#[method_id($($sel:tt)*)])
() ($($__m_optional:tt)*)
($($m_checked:tt)*)
($($params_converted:tt)*)
($($body_prefix:tt)*)
} => {
$($m_checked)*
#[allow(clippy::diverging_sub_expression)]
$($qualifiers)* extern "C" fn $name(
$($params_prefix)*
$($params_converted)*
) -> $crate::__macro_helpers::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)
($($params_prefix:tt)*)
(#[method_id($($sel:tt)*)])
($($retain_semantics:tt)*)
($($__m_optional:tt)*)
($($m_checked:tt)*)
($($params_converted:tt)*)
($($body_prefix:tt)*)
} => {
$($m_checked)*
$($qualifiers)* extern "C" fn $name() {
$crate::__macro_helpers::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::__macro_helpers::ConvertReturn>::__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)
($($__params_prefix:tt)*)
($($params_rest:tt)*)
(#[$method_or_method_id:ident($($sel:tt)*)])
($($retain_semantics:tt)*)
($($m_optional:tt)*)
($($m_checked:tt)*)
} => {
$crate::__extract_and_apply_cfg_attributes! {
($($m_checked)*)
$crate::__declare_class_invalid_selectors!(#[$method_or_method_id($($sel)*)]);
$crate::__extern_methods_no_optional!($($m_optional)*);
$builder.$builder_method(
$crate::sel!($($sel)*),
Self::$name as $crate::__fn_ptr! {
($($qualifiers)*)
(_, _,)
$($params_rest)*
},
);
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_invalid_selectors {
(#[method(dealloc)]) => {
$crate::__macro_helpers::compile_error!(
"`#[method(dealloc)]` is not supported. Implement `Drop` for the type instead"
)
};
(#[method_id(dealloc)]) => {
$crate::__macro_helpers::compile_error!(
"`#[method_id(dealloc)]` is not supported. Implement `Drop` for the type instead"
)
};
(#[method_id(alloc)]) => {
$crate::__macro_helpers::compile_error!($crate::__macro_helpers::concat!(
"`#[method_id(alloc)]` is not supported. ",
"Use `#[method(alloc)]` and do the memory management yourself",
))
};
(#[method_id(retain)]) => {
$crate::__macro_helpers::compile_error!($crate::__macro_helpers::concat!(
"`#[method_id(retain)]` is not supported. ",
"Use `#[method(retain)]` and do the memory management yourself",
))
};
(#[method_id(release)]) => {
$crate::__macro_helpers::compile_error!($crate::__macro_helpers::concat!(
"`#[method_id(release)]` is not supported. ",
"Use `#[method(release)]` and do the memory management yourself",
))
};
(#[method_id(autorelease)]) => {
$crate::__macro_helpers::compile_error!($crate::__macro_helpers::concat!(
"`#[method_id(autorelease)]` is not supported. ",
"Use `#[method(autorelease)]` and do the memory management yourself",
))
};
(#[$method_or_method_id:ident($($sel:tt)*)]) => {};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __declare_class_no_optional {
() => {};
(#[optional]) => {
$crate::__macro_helpers::compile_error!(
"`#[optional]` is only supported in `extern_protocol!`"
)
};
}
#[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)*)?
}
};
}