mod __rewrite_self_arg;
mod declare_class;
mod extern_class;
mod extern_methods;
#[macro_export]
macro_rules! class {
($name:ident) => {{
$crate::__class_inner!($name, $crate::__hash_idents!($name))
}};
}
#[doc(hidden)]
#[macro_export]
#[cfg(not(feature = "unstable-static-class"))]
macro_rules! __class_inner {
($name:ident, $_hash:expr) => {{
use $crate::__macro_helpers::{concat, panic, stringify, CachedClass, None, Some};
static CACHED_CLASS: CachedClass = CachedClass::new();
let name = concat!(stringify!($name), '\0');
#[allow(unused_unsafe)]
let cls = unsafe { CACHED_CLASS.get(name) };
match cls {
Some(cls) => cls,
None => panic!("Class with name {} could not be found", stringify!($name)),
}
}};
}
#[cfg_attr(not(feature = "unstable-static-sel"), doc = "```no_run")]
#[cfg_attr(feature = "unstable-static-sel", doc = "```compile_fail")]
#[macro_export]
macro_rules! sel {
(alloc) => ({
$crate::__macro_helpers::alloc()
});
(init) => ({
$crate::__macro_helpers::init()
});
(new) => ({
$crate::__macro_helpers::new()
});
($first:ident $(: $($rest:ident :)*)?) => ({
use $crate::__macro_helpers::{concat, stringify, str};
const SELECTOR_DATA: &str = concat!(stringify!($first), $(':', $(stringify!($rest), ':',)*)? '\0');
$crate::__sel_inner!(SELECTOR_DATA, $crate::__hash_idents!($first $($($rest)*)?))
});
}
#[doc(hidden)]
#[macro_export]
#[cfg(not(feature = "unstable-static-sel"))]
macro_rules! __sel_inner {
($data:expr, $_hash:expr) => {{
use $crate::__macro_helpers::CachedSel;
static CACHED_SEL: CachedSel = CachedSel::new();
#[allow(unused_unsafe)]
unsafe {
CACHED_SEL.get($data)
}
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __inner_statics_apple_generic {
{
@string_to_known_length_bytes;
$x:ident;
} => {{
let mut res: [u8; $x.len()] = [0; $x.len()];
let mut i = 0;
while i < $x.len() {
res[i] = $x[i];
i += 1;
}
res
}};
{
@image_info;
$image_info_section:literal;
$hash:expr;
} => {
#[link_section = $image_info_section]
#[export_name = $crate::__macro_helpers::concat!(
"\x01L_OBJC_IMAGE_INFO_",
$hash,
)]
#[used] static _IMAGE_INFO: $crate::ffi::__ImageInfo = $crate::ffi::__ImageInfo::system();
};
{
@module_info;
$hash:expr;
} => {
#[link_section = "__TEXT,__cstring,cstring_literals"]
#[export_name = $crate::__macro_helpers::concat!(
"\x01L_OBJC_CLASS_NAME_",
$hash,
"_MODULE_INFO"
)]
static MODULE_INFO_NAME: [$crate::__macro_helpers::u8; 1] = [0];
#[link_section = "__OBJC,__module_info,regular,no_dead_strip"]
#[export_name = $crate::__macro_helpers::concat!(
"\x01L_OBJC_MODULES_",
$hash,
)]
#[used] static _MODULE_INFO: $crate::__macro_helpers::ModuleInfo = $crate::__macro_helpers::ModuleInfo::new(
MODULE_INFO_NAME.as_ptr()
);
};
{
@sel;
$var_name_section:literal;
$selector_ref_section:literal;
$data:expr;
$hash:expr;
} => {
use $crate::__macro_helpers::{u8, UnsafeCell};
use $crate::runtime::Sel;
const X: &[u8] = $data.as_bytes();
#[link_section = $var_name_section]
#[export_name = $crate::__macro_helpers::concat!(
"\x01L_OBJC_METH_VAR_NAME_",
$hash,
)]
static NAME_DATA: [u8; X.len()] = $crate::__inner_statics_apple_generic! {
@string_to_known_length_bytes;
X;
};
#[link_section = $selector_ref_section]
#[export_name = $crate::__macro_helpers::concat!(
"\x01L_OBJC_SELECTOR_REFERENCES_",
$hash,
)]
static mut REF: UnsafeCell<Sel> = unsafe {
UnsafeCell::new(Sel::__internal_from_ptr(NAME_DATA.as_ptr().cast()))
};
};
{
@class;
$name:ident;
$hash:expr;
} => {
use $crate::__macro_helpers::UnsafeCell;
use $crate::runtime::Class;
extern "C" {
#[link_name = $crate::__macro_helpers::concat!(
"OBJC_CLASS_$_",
$crate::__macro_helpers::stringify!($name),
)]
static CLASS: Class;
}
#[link_section = "__DATA,__objc_classrefs,regular,no_dead_strip"]
#[export_name = $crate::__macro_helpers::concat!(
"\x01L_OBJC_CLASSLIST_REFERENCES_$_",
$crate::__hash_idents!($name),
)]
static mut REF: UnsafeCell<&Class> = unsafe {
UnsafeCell::new(&CLASS)
};
};
{
@class_old;
$name:ident;
$hash:expr;
} => {
use $crate::__macro_helpers::{u8, UnsafeCell};
use $crate::runtime::Class;
const X: &[u8] = $crate::__macro_helpers::stringify!($name).as_bytes();
#[link_section = "__TEXT,__cstring,cstring_literals"]
#[export_name = $crate::__macro_helpers::concat!(
"\x01L_OBJC_CLASS_NAME_",
$crate::__hash_idents!($name),
)]
static NAME_DATA: [u8; X.len()] = $crate::__inner_statics_apple_generic! {
@string_to_known_length_bytes;
X;
};
#[link_section = "__OBJC,__cls_refs,literal_pointers,no_dead_strip"]
#[export_name = $crate::__macro_helpers::concat!(
"\x01L_OBJC_CLASS_REFERENCES_",
$crate::__hash_idents!($name),
)]
static mut REF: UnsafeCell<&Class> = unsafe {
let ptr: *const Class = NAME_DATA.as_ptr().cast();
UnsafeCell::new(&*ptr)
};
}
}
#[doc(hidden)]
#[macro_export]
#[cfg(all(feature = "apple", not(all(target_os = "macos", target_arch = "x86"))))]
macro_rules! __inner_statics {
(@image_info $hash:expr) => {
$crate::__inner_statics_apple_generic! {
@image_info;
"__DATA,__objc_imageinfo,regular,no_dead_strip";
$hash;
}
};
(@sel $data:expr, $hash:expr) => {
$crate::__inner_statics_apple_generic! {
@sel;
"__TEXT,__objc_methname,cstring_literals";
"__DATA,__objc_selrefs,literal_pointers,no_dead_strip";
$data;
$hash;
}
};
(@class $name:ident, $hash:expr) => {
$crate::__inner_statics_apple_generic! {
@class;
$name;
$hash;
}
};
}
#[doc(hidden)]
#[macro_export]
#[cfg(all(feature = "apple", target_os = "macos", target_arch = "x86"))]
macro_rules! __inner_statics {
(@image_info $hash:expr) => {
$crate::__inner_statics_apple_generic! {
@image_info;
"__OBJC,__image_info,regular";
$hash;
}
};
(@sel $data:expr, $hash:expr) => {
$crate::__inner_statics_apple_generic! {
@sel;
"__TEXT,__cstring,cstring_literals";
"__OBJC,__message_refs,literal_pointers,no_dead_strip";
$data;
$hash;
}
};
(@class $name:ident, $hash:expr) => {
$crate::__inner_statics_apple_generic! {
@class_old;
$name;
$hash;
}
$crate::__inner_statics_apple_generic! {
@module_info;
$hash;
}
};
}
#[doc(hidden)]
#[macro_export]
#[cfg(not(feature = "apple"))]
macro_rules! __inner_statics {
(@image_info $($args:tt)*) => {
};
(@sel $($args:tt)*) => {
$crate::__macro_helpers::compile_error!(
"The `\"unstable-static-sel\"` feature is not yet supported on GNUStep!"
)
};
(@class $($args:tt)*) => {
$crate::__macro_helpers::compile_error!(
"The `\"unstable-static-class\"` feature is not yet supported on GNUStep!"
)
};
}
#[doc(hidden)]
#[macro_export]
#[cfg(all(
feature = "unstable-static-sel",
not(feature = "unstable-static-sel-inlined")
))]
macro_rules! __sel_inner {
($data:expr, $hash:expr) => {{
$crate::__inner_statics!(@image_info $hash);
$crate::__inner_statics!(@sel $data, $hash);
#[inline(never)]
fn objc_static_workaround() -> $crate::runtime::Sel {
unsafe { *REF.get() }
}
objc_static_workaround()
}};
}
#[doc(hidden)]
#[macro_export]
#[cfg(all(feature = "unstable-static-sel-inlined"))]
macro_rules! __sel_inner {
($data:expr, $hash:expr) => {{
$crate::__inner_statics!(@image_info $hash);
$crate::__inner_statics!(@sel $data, $hash);
#[allow(unused_unsafe)]
unsafe { *REF.get() }
}};
}
#[doc(hidden)]
#[macro_export]
#[cfg(all(
feature = "unstable-static-class",
not(feature = "unstable-static-class-inlined")
))]
macro_rules! __class_inner {
($name:ident, $hash:expr) => {{
$crate::__inner_statics!(@image_info $hash);
$crate::__inner_statics!(@class $name, $hash);
#[inline(never)]
fn objc_static_workaround() -> &'static Class {
unsafe { *REF.get() }
}
objc_static_workaround()
}};
}
#[doc(hidden)]
#[macro_export]
#[cfg(all(feature = "unstable-static-class-inlined"))]
macro_rules! __class_inner {
($name:ident, $hash:expr) => {{
$crate::__inner_statics!(@image_info $hash);
$crate::__inner_statics!(@class $name, $hash);
#[allow(unused_unsafe)]
unsafe { *REF.get() }
}};
}
#[macro_export]
macro_rules! msg_send {
[super($obj:expr), $selector:ident $(,)?] => ({
let sel = $crate::sel!($selector);
let result;
result = $crate::MessageReceiver::__send_super_message_static($obj, sel, ());
result
});
[super($obj:expr), $($selector:ident : $argument:expr),+ $(,)?] => ({
let sel = $crate::sel!($($selector :)+);
let result;
result = $crate::MessageReceiver::__send_super_message_static($obj, sel, ($($argument,)+));
result
});
[super($obj:expr, $superclass:expr), $selector:ident $(,)?] => ({
let sel = $crate::sel!($selector);
let result;
result = $crate::MessageReceiver::send_super_message($obj, $superclass, sel, ());
result
});
[super($obj:expr, $superclass:expr), $($selector:ident : $argument:expr $(,)?)+] => ({
let sel = $crate::sel!($($selector :)+);
let result;
result = $crate::MessageReceiver::send_super_message($obj, $superclass, sel, ($($argument,)+));
result
});
[$obj:expr, $selector:ident $(,)?] => ({
let sel = $crate::sel!($selector);
let result;
result = $crate::MessageReceiver::send_message($obj, sel, ());
result
});
[$obj:expr, $($selector:ident : $argument:expr $(,)?)+] => ({
let sel = $crate::sel!($($selector :)+);
let result;
result = $crate::MessageReceiver::send_message($obj, sel, ($($argument,)+));
result
});
}
#[macro_export]
#[deprecated = "use a normal msg_send! instead, it will perform the conversion for you"]
macro_rules! msg_send_bool {
[$($msg_send_args:tt)+] => ({
// Use old impl for backwards compat
let result: $crate::runtime::Bool = $crate::msg_send![$($msg_send_args)+];
result.as_bool()
});
}
#[cfg_attr(
feature = "exception",
doc = "[`exception::catch`]: crate::exception::catch"
)]
#[cfg_attr(
not(feature = "exception"),
doc = "[`exception::catch`]: crate::exception#feature-not-enabled"
)]
#[macro_export]
macro_rules! msg_send_id {
[$obj:expr, $selector:ident $(,)?] => ({
$crate::__msg_send_id_helper!(@verify $selector);
let sel = $crate::sel!($selector);
const NAME: &[$crate::__macro_helpers::u8] = $crate::__macro_helpers::stringify!($selector).as_bytes();
$crate::__msg_send_id_helper!(@get_assert_consts NAME);
let result;
result = <RS as $crate::__macro_helpers::MsgSendId<_, _, _>>::send_message_id($obj, sel, ());
result
});
[$obj:expr, $($selector:ident : $argument:expr),+ $(,)?] => ({
let sel = $crate::sel!($($selector:)+);
const NAME: &[$crate::__macro_helpers::u8] =
$crate::__macro_helpers::concat!($($crate::__macro_helpers::stringify!($selector), ':'),+).as_bytes();
$crate::__msg_send_id_helper!(@get_assert_consts NAME);
let result;
result = <RS as $crate::__macro_helpers::MsgSendId<_, _, _>>::send_message_id($obj, sel, ($($argument,)+));
result
});
}
#[doc(hidden)]
#[macro_export]
macro_rules! __msg_send_id_helper {
(@verify retain) => {{
$crate::__macro_helpers::compile_error!(
"msg_send_id![obj, retain] is not supported. Use `Id::retain` instead"
)
}};
(@verify release) => {{
$crate::__macro_helpers::compile_error!(
"msg_send_id![obj, release] is not supported. Drop an `Id` instead"
)
}};
(@verify autorelease) => {{
$crate::__macro_helpers::compile_error!(
"msg_send_id![obj, autorelease] is not supported. Use `Id::autorelease`"
)
}};
(@verify $selector:ident) => {{}};
(@get_assert_consts $selector:ident) => {
use $crate::__macro_helpers::{bool, in_selector_family, RetainSemantics};
const NEW: bool = in_selector_family($selector, b"new");
const ALLOC: bool = in_selector_family($selector, b"alloc");
const INIT: bool = in_selector_family($selector, b"init");
const COPY_OR_MUT_COPY: bool = {
in_selector_family($selector, b"copy") || in_selector_family($selector, b"mutableCopy")
};
type RS = RetainSemantics<NEW, ALLOC, INIT, COPY_OR_MUT_COPY>;
};
}