1#[allow(unused_imports)]
2use super::*;
3
4
5#[macro_export]
80macro_rules! extension {
81 {extern $symbol_initializer:ident $(, $symbol_finalizer:ident;
83 move $initializer:path, final $($finalizer:path)?)?;
84 gen $context_initializer:path, final $($context_finalizer:path)?;
85 } => {
86 const _: () = {
87 mod _flash_runtime_extension {
88 use super::*;
89 $crate::extension! {@Extern [$symbol_initializer $(, $symbol_finalizer, $initializer $(, $finalizer)?)?]}
90 #[allow(unsafe_op_in_unsafe_fn)]
91 unsafe extern "C" fn ctx_initializer (
92 ext_data: $crate::c::markers::FREData,
93 ctx_type: $crate::c::markers::FREStr,
94 ctx: $crate::c::markers::FREContext,
95 num_funcs_to_set: *mut u32,
96 funcs_to_set: *mut *const $crate::c::ffi::FRENamedFunction,
97 ) {
98 let context_initializer: $crate::function::ContextInitializer = $context_initializer;
99 $crate::context::CurrentContext::with_context_initializer(ext_data, ctx_type, &ctx, num_funcs_to_set, funcs_to_set, $context_initializer);
100 }
101 #[allow(unsafe_op_in_unsafe_fn)]
102 unsafe extern "C" fn ctx_finalizer (ctx: $crate::c::markers::FREContext) {
103 $crate::context::CurrentContext::with(&ctx, |ctx| {
104 $(
105 let context_finalizer: $crate::function::ContextFinalizer = $context_finalizer;
106 context_finalizer(ctx);
107 )?
108 let ctx = *(ctx as *const $crate::context::CurrentContext as *const $crate::context::ForeignContext);
109 let raw = ctx
110 .get_native_data()
111 .expect("Failed to retrieve native data from FFI.")
112 .expect("`ContextRegistry` is expected in native data but is missing.");
113 assert!(<::std::cell::RefCell<$crate::context::ContextRegistry> as $crate::data::Data>::ref_from(raw).is_ok());
114 $crate::data::drop_from(raw);
115 });
116
117 }
118 }
119 };
120 };
121 {@Extern [$symbol_initializer:ident, $symbol_finalizer:ident, $initializer:path $(, $finalizer:path)?]
123 } => {
124 #[allow(unsafe_op_in_unsafe_fn, non_snake_case)]
125 #[unsafe(no_mangle)]
126 pub unsafe extern "C" fn $symbol_initializer (
127 ext_data_to_set: *mut $crate::c::markers::FREData,
128 ctx_initializer_to_set: *mut $crate::c::ffi::FREContextInitializer,
129 ctx_finalizer_to_set: *mut $crate::c::ffi::FREContextFinalizer,
130 ) {
131 assert!(!ext_data_to_set.is_null());
132 assert!(!ctx_initializer_to_set.is_null());
133 assert!(!ctx_finalizer_to_set.is_null());
134 let initializer: $crate::function::Initializer = $initializer;
135 if let Some(ext_data) = initializer() {
136 let ext_data = ::std::sync::Arc::new(::std::sync::Mutex::new(ext_data));
137 *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();
138 }
139 *ctx_initializer_to_set = ctx_initializer;
140 *ctx_finalizer_to_set = Some(ctx_finalizer);
141 }
142 #[allow(unsafe_op_in_unsafe_fn, non_snake_case)]
143 #[unsafe(no_mangle)]
144 pub unsafe extern "C" fn $symbol_finalizer (ext_data: $crate::c::markers::FREData) {
145 let ext_data = $crate::validated::NonNullFREData::new(ext_data)
146 .map(|raw| {
147 let arc_mutex_boxed = <::std::sync::Arc<::std::sync::Mutex<Box<dyn ::std::any::Any>>> as $crate::data::Data>::from_raw(raw);
148 let mutex = ::std::sync::Arc::try_unwrap(arc_mutex_boxed).expect("INVARIANT: No context exists.");
149 let boxed = mutex.into_inner().expect("The mutex is poisoned.");
150 boxed
151 });
152 $(
153 let finalizer: $crate::function::Finalizer = $finalizer;
154 finalizer(ext_data);
155 )?
156 }
157 };
158 {@Extern [$symbol_initializer:ident]
160 } => {
161 #[allow(unsafe_op_in_unsafe_fn, non_snake_case)]
162 #[unsafe(no_mangle)]
163 pub unsafe extern "C" fn $symbol_initializer (
164 ext_data_to_set: *mut $crate::c::markers::FREData,
165 ctx_initializer_to_set: *mut $crate::c::ffi::FREContextInitializer,
166 ctx_finalizer_to_set: *mut $crate::c::ffi::FREContextFinalizer,
167 ) {
168 assert!(!ext_data_to_set.is_null());
169 assert!(!ctx_initializer_to_set.is_null());
170 assert!(!ctx_finalizer_to_set.is_null());
171 *ctx_initializer_to_set = ctx_initializer;
172 *ctx_finalizer_to_set = Some(ctx_finalizer);
173 }
174 };
175}
176
177
178#[macro_export]
227macro_rules! function {
228 {$name:ident ($($arguments:tt)+) $(-> $return_type:ty)? $body:block
230 } => {
231 #[allow(non_upper_case_globals)]
232 pub const $name: &'static $crate::function::FunctionImplementation = & $crate::function::FunctionImplementation::new(
233 $crate::function!(@Name $name), {
234 #[allow(unsafe_op_in_unsafe_fn)]
235 unsafe extern "C" fn abi(
236 ctx: $crate::c::markers::FREContext,
237 func_data: $crate::c::markers::FREData,
238 argc: u32,
239 argv: *const $crate::c::markers::FREObject,
240 ) -> $crate::c::markers::FREObject {
241 fn func <'a> (
242 ctx: &$crate::context::CurrentContext<'a>,
243 func_data: Option<&mut dyn ::std::any::Any>,
244 args: &[$crate::as3::Object<'a>],
245 ) -> $crate::as3::Object<'a> {
246 $crate::function! {@Parameters [ctx, func_data, args] $($arguments)+}
247 (|| -> $crate::function!(@Return $($return_type)?) {
248 $body
249 })().into()
250 }
251 $crate::context::CurrentContext::with_method(&ctx, func_data, argc, argv, func)
252 }
253 abi},
254 );
255 };
256 ($name:ident use $func:path
258 ) => {
259 #[allow(non_upper_case_globals)]
260 pub const $name: &'static $crate::function::FunctionImplementation = & $crate::function::FunctionImplementation::new(
261 $crate::function!(@Name $name), {
262 #[allow(unsafe_op_in_unsafe_fn)]
263 unsafe extern "C" fn abi(
264 ctx: $crate::c::markers::FREContext,
265 func_data: $crate::c::markers::FREData,
266 argc: u32,
267 argv: *const $crate::c::markers::FREObject,
268 ) -> $crate::c::markers::FREObject {
269 $crate::context::CurrentContext::with_method(&ctx, func_data, argc, argv, $func)
270 }
271 abi},
272 );
273 };
274 (@Name $name:ident
276 ) => {
277 unsafe {
278 let s: &'static str = concat!(stringify!($name), "\0");
279 let s: &'static ::std::ffi::CStr = ::std::ffi::CStr::from_bytes_with_nul_unchecked(s.as_bytes());
280 let s = $crate::validated::UCStr::from_literal_unchecked(s);
281 s
282 }
283 };
284 (@Return $return_type:ty
286 ) => ($return_type);
287 (@Return
289 ) => (());
290 {@Parameters [$c:ident, $d:ident, $a:ident $(,)?]
292 $ctx:ident, $data:ident, $args:ident $(,)?
293 } => {
294 let $ctx: &$crate::context::CurrentContext<'a> = $c;
295 let $data: Option<&mut dyn ::std::any::Any> = $d;
296 let $args: &[$crate::as3::Object<'a>] = $a;
297 };
298 {@Parameters [$c:ident, $d:ident, $a:ident $(,)?]
300 $ctx:ident, $data:ident, _ $(,)?
301 } => {
302 $crate::function! {@Parameters [$c, $d, $a]
303 $ctx, $data, _args
304 }
305 };
306 {@Parameters [$c:ident, $d:ident, $a:ident $(,)?]
308 $ctx:ident, _, $args:ident $(,)?
309 } => {
310 $crate::function! {@Parameters [$c, $d, $a]
311 $ctx, _data, $args
312 }
313 };
314 {@Parameters [$c:ident, $d:ident, $a:ident $(,)?]
316 _, $data:ident, $args:ident $(,)?
317 } => {
318 $crate::function! {@Parameters [$c, $d, $a]
319 _ctx, $data, $args
320 }
321 };
322 {@Parameters [$c:ident, $d:ident, $a:ident $(,)?]
324 _, _, $args:ident $(,)?
325 } => {
326 $crate::function! {@Parameters [$c, $d, $a]
327 _ctx, _data, $args
328 }
329 };
330 {@Parameters [$c:ident, $d:ident, $a:ident $(,)?]
332 _, $data:ident, _ $(,)?
333 } => {
334 $crate::function! {@Parameters [$c, $d, $a]
335 _ctx, $data, _args
336 }
337 };
338 {@Parameters [$c:ident, $d:ident, $a:ident $(,)?]
340 $ctx:ident, _, _ $(,)?
341 } => {
342 $crate::function! {@Parameters [$c, $d, $a]
343 $ctx, _data, _args
344 }
345 };
346 {@Parameters [$c:ident, $d:ident, $a:ident $(,)?]
348 _, _, _ $(,)?
349 } => {
350 $crate::function! {@Parameters [$c, $d, $a]
351 _ctx, _data, _args
352 }
353 };
354}
355