#[allow(unused_imports)]
use super::*;
#[macro_export]
macro_rules! extension {
{ extern $symbol_initializer:ident $(, $symbol_finalizer:ident;
move $initializer:path, final $($finalizer:path)?)?;
gen $context_initializer:path, final $($context_finalizer:path)?;
} => {
const _: () = {
mod __flash_runtime_extension {
use super::*;
$crate::extension! {@Extern [$symbol_initializer $(, $symbol_finalizer, $initializer $(, $finalizer)?)?]}
#[allow(unsafe_op_in_unsafe_fn)]
unsafe extern "C" fn ctx_initializer (
ext_data: $crate::c::FREData,
ctx_type: $crate::c::FREStr,
ctx: $crate::c::FREContext,
num_funcs_to_set: *mut u32,
funcs_to_set: *mut *const $crate::c::FRENamedFunction,
) {
let context_initializer: $crate::function::ContextInitializer = $context_initializer;
$crate::__private::context::with_initializer(ext_data, ctx_type, &ctx, num_funcs_to_set, funcs_to_set, $context_initializer);
}
#[allow(unsafe_op_in_unsafe_fn)]
unsafe extern "C" fn ctx_finalizer (ctx: $crate::c::FREContext) {
$crate::__private::context::with(&ctx, |ctx| {
$(
let context_finalizer: $crate::function::ContextFinalizer = $context_finalizer;
context_finalizer(ctx);
)?
let ctx = *(ctx as *mut $crate::context::CurrentContext as *mut $crate::context::ForeignContext);
let raw = ctx
.get_native_data()
.expect("Failed to retrieve native data from FFI.")
.expect("`ContextRegistry` is expected in native data but is missing.");
assert!(<::std::cell::RefCell<$crate::context::ContextRegistry> as $crate::data::Data>::ref_from(raw).is_ok());
$crate::data::drop_from(raw);
});
}
}
};
};
{ @Extern [$symbol_initializer:ident, $symbol_finalizer:ident, $initializer:path $(, $finalizer:path)?]
} => {
#[allow(unsafe_op_in_unsafe_fn, non_snake_case)]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn $symbol_initializer (
ext_data_to_set: *mut $crate::c::FREData,
ctx_initializer_to_set: *mut $crate::c::FREContextInitializer,
ctx_finalizer_to_set: *mut $crate::c::FREContextFinalizer,
) {
assert!(!ext_data_to_set.is_null());
assert!(!ctx_initializer_to_set.is_null());
assert!(!ctx_finalizer_to_set.is_null());
let initializer: $crate::function::Initializer = $initializer;
if let Some(ext_data) = initializer() {
let ext_data = ::std::sync::Arc::new(::std::sync::Mutex::new(ext_data));
*ext_data_to_set = <::std::sync::Arc<::std::sync::Mutex<Box<dyn ::std::any::Any>>> as $crate::data::Data>::into_raw(ext_data).as_ptr();
}
*ctx_initializer_to_set = ctx_initializer;
*ctx_finalizer_to_set = ctx_finalizer;
}
#[allow(unsafe_op_in_unsafe_fn, non_snake_case)]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn $symbol_finalizer (ext_data: $crate::c::FREData) {
let ext_data = $crate::validated::NonNullFREData::new(ext_data)
.map(|raw| {
let arc_mutex_boxed = <::std::sync::Arc<::std::sync::Mutex<Box<dyn ::std::any::Any>>> as $crate::data::Data>::from_raw(raw);
let mutex = ::std::sync::Arc::try_unwrap(arc_mutex_boxed).expect("INVARIANT: No context exists.");
let boxed = mutex.into_inner().expect("The mutex is poisoned.");
boxed
});
$(
let finalizer: $crate::function::Finalizer = $finalizer;
finalizer(ext_data);
)?
}
};
{ @Extern [$symbol_initializer:ident]
} => {
#[allow(unsafe_op_in_unsafe_fn, non_snake_case)]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn $symbol_initializer (
ext_data_to_set: *mut $crate::c::FREData,
ctx_initializer_to_set: *mut $crate::c::FREContextInitializer,
ctx_finalizer_to_set: *mut $crate::c::FREContextFinalizer,
) {
assert!(!ctx_initializer_to_set.is_null());
assert!(!ctx_finalizer_to_set.is_null());
*ctx_initializer_to_set = ctx_initializer;
*ctx_finalizer_to_set = ctx_finalizer;
}
};
}
#[macro_export]
macro_rules! function {
{ $name:ident ($($arguments:tt)+) $(-> $return_type:ty)? $body:block
} => {
#[allow(non_upper_case_globals)]
pub const $name: &'static $crate::function::FunctionImplementation = & $crate::__private::function::implement(
$crate::ucstringify! ($name), {
#[allow(unsafe_op_in_unsafe_fn)]
unsafe extern "C" fn abi(
ctx: $crate::c::FREContext,
func_data: $crate::c::FREData,
argc: u32,
argv: *const $crate::c::FREObject,
) -> $crate::c::FREObject {
fn func <'a> (
ctx: &mut $crate::context::CurrentContext<'a>,
func_data: Option<&mut dyn ::std::any::Any>,
args: &[$crate::as3::Object<'a>],
) -> $crate::as3::Object<'a> {
$crate::function! {@Parameters [ctx, func_data, args] $($arguments)+}
(|| -> $crate::function!(@Return $($return_type)?) {
$body
})().into()
}
$crate::__private::context::with_method(&ctx, func_data, argc, argv, func)
}
abi},
);
};
( $name:ident use $func:path
) => {
#[allow(non_upper_case_globals)]
pub const $name: &'static $crate::function::FunctionImplementation = & $crate::__private::function::implement(
$crate::ucstringify! ($name), {
#[allow(unsafe_op_in_unsafe_fn)]
unsafe extern "C" fn abi(
ctx: $crate::c::FREContext,
func_data: $crate::c::FREData,
argc: u32,
argv: *const $crate::c::FREObject,
) -> $crate::c::FREObject {
$crate::__private::context::with_method(&ctx, func_data, argc, argv, $func)
}
abi},
);
};
( @Return $return_type:ty
) => ($return_type);
( @Return
) => (());
{ @Parameters [$c:ident, $d:ident, $a:ident $(,)?]
$ctx:ident, $data:ident, $args:ident $(,)?
} => {
let $ctx: &mut $crate::context::CurrentContext<'a> = $c;
let $data: Option<&mut dyn ::std::any::Any> = $d;
let $args: &[$crate::as3::Object<'a>] = $a;
};
{ @Parameters [$c:ident, $d:ident, $a:ident $(,)?]
$ctx:ident, $data:ident, _ $(,)?
} => {
$crate::function! {@Parameters [$c, $d, $a]
$ctx, $data, _args
}
};
{ @Parameters [$c:ident, $d:ident, $a:ident $(,)?]
$ctx:ident, _, $args:ident $(,)?
} => {
$crate::function! {@Parameters [$c, $d, $a]
$ctx, _data, $args
}
};
{ @Parameters [$c:ident, $d:ident, $a:ident $(,)?]
_, $data:ident, $args:ident $(,)?
} => {
$crate::function! {@Parameters [$c, $d, $a]
_ctx, $data, $args
}
};
{ @Parameters [$c:ident, $d:ident, $a:ident $(,)?]
_, _, $args:ident $(,)?
} => {
$crate::function! {@Parameters [$c, $d, $a]
_ctx, _data, $args
}
};
{ @Parameters [$c:ident, $d:ident, $a:ident $(,)?]
_, $data:ident, _ $(,)?
} => {
$crate::function! {@Parameters [$c, $d, $a]
_ctx, $data, _args
}
};
{ @Parameters [$c:ident, $d:ident, $a:ident $(,)?]
$ctx:ident, _, _ $(,)?
} => {
$crate::function! {@Parameters [$c, $d, $a]
$ctx, _data, _args
}
};
{ @Parameters [$c:ident, $d:ident, $a:ident $(,)?]
_, _, _ $(,)?
} => {
$crate::function! {@Parameters [$c, $d, $a]
_ctx, _data, _args
}
};
}
#[macro_export]
macro_rules! class {
{
$(#[$meta:meta])*
$name:ident $($modifier:tt)*
} => {
$crate::class! {@Define
$(#[$meta])*
$name $($modifier)*
}
unsafe impl<'a> $crate::types::object::AsObject<'a> for $name<'a> {
const TYPE: $crate::types::Type = $crate::types::Type::Named(stringify!($name));
}
};
{@Typeof
$(#[$meta:meta])*
$name:ident $($modifier:tt)*
} => { const _: () = $crate::__private::SEALED;
$crate::class! {@Define
$(#[$meta])*
$name $($modifier)*
}
unsafe impl<'a> $crate::types::object::AsObject<'a> for $name<'a> {
const TYPE: $crate::types::Type = $crate::types::Type::$name;
}
impl<'a> TryFrom<$crate::as3::Object<'a>> for $name<'a> {
type Error = $crate::types::Type;
fn try_from (object: $crate::as3::Object<'a>) -> Result<Self, Self::Error> {
let ty = <$crate::as3::Object as $crate::types::object::AsObject>::get_type(object);
if ty == <Self as $crate::types::object::AsObject>::TYPE {
Ok(unsafe {<$crate::as3::Object as $crate::types::object::AsObject>::as_unchecked(object)})
}else{Err(ty)}
}
}
impl<'a> TryFrom<$crate::types::object::NonNullObject<'a>> for $name<'a> {
type Error = $crate::types::Type;
fn try_from (object: $crate::types::object::NonNullObject<'a>) -> Result<Self, Self::Error> {
<$crate::types::object::NonNullObject as $crate::types::object::AsObject>::as_object(object).try_into()
}
}
};
{@Define
$(#[$meta:meta])*
$name:ident
} => {
$(#[$meta])*
#[derive(::std::fmt::Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct $name <'a> (::std::ptr::NonNull<::std::ffi::c_void>, ::std::marker::PhantomData<&'a ()>);
$crate::class!(@Implement $name);
};
{@Define
$(#[$meta:meta])*
$name:ident: ?PartialEq
} => {
$(#[$meta])*
#[derive(::std::fmt::Debug, Clone, Copy)]
#[repr(transparent)]
pub struct $name <'a> (::std::ptr::NonNull<::std::ffi::c_void>, ::std::marker::PhantomData<&'a ()>);
$crate::class!(@Implement $name);
};
{@Implement
$name:ident
} => {
#[cfg(debug_assertions)]
const _: () = {
#[used]
#[unsafe(export_name = concat!("__class_", stringify!($name)))]
pub static CLASS_NAME_MUST_UNIQUE: u8 = 0;
};
unsafe impl $crate::__private::Sealed for $name<'_> {}
impl<'a> $crate::types::object::AsNonNullObject<'a> for $name<'a> {}
impl<'a> From<$name<'a>> for $crate::types::object::NonNullObject<'a> {fn from(object: $name<'a>) -> Self {<$name as $crate::types::object::AsNonNullObject>::as_non_null_object(object)}}
impl From<$name<'_>> for $crate::c::FREObject {fn from(object: $name) -> Self {<$name as $crate::types::object::AsObject>::as_ptr(object)}}
impl ::std::fmt::Display for $name<'_> {fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {::std::fmt::Display::fmt(&(<Self as $crate::types::object::AsNonNullObject>::as_non_null_object(*self)), f)}}
impl $crate::validated::ToUcstrLossy for $name<'_> {fn to_ucstr_lossy(&self) -> $crate::validated::UCStr {
let object = <$name as $crate::types::object::AsObject>::as_object(*self);
<$crate::as3::Object as $crate::validated::ToUcstrLossy>::to_ucstr_lossy(&object)
}}
};
}
#[macro_export]
macro_rules! ucstringify {
{$($tokens:tt)*} => {
{
const STR: &'static str = concat!(stringify!($($tokens)*), "\0");
const CSTR: &'static ::std::ffi::CStr = unsafe {::std::ffi::CStr::from_bytes_with_nul_unchecked(STR.as_bytes())};
const UCSTR: $crate::validated::UCStr = unsafe {$crate::validated::UCStr::from_literal_unchecked(CSTR)};
UCSTR
}
};
}