devela/lang/js/
reexport.rs

1// devela::lang::js::reexport
2//
3//! Defines the [`js_reexport`] macro.
4//
5// IMPROVE: what happens with feature-gating unsafe?
6// TODO:
7// - public fn
8// - impl block
9
10/// Helps re-exporting javascript functions.
11///
12/// # Example
13/// ```
14/// # use devela::js_reexport;
15/// js_reexport! {
16///     [ module: "env" ]
17///     pub safe fn same_fn_name(x: f64, y: f64, w: f64, h: f64);
18///     pub(crate) safe fn "js_fn_name" rust_fn_name(x: f64, y: f64, w: f64, h: f64);
19///     unsafe fn "js_fn" rs_fn(ptr: *const u8, len: usize, x: f64, y: f64);
20/// }
21/// ```
22#[doc(hidden)]
23#[macro_export]
24macro_rules! _js_reexport {
25    (
26        // # Args
27        // [            header section
28        // $module:     optional js module name (defaults to "env")
29        // ]
30        // $fn_attrs:   optional attributes and doc comments
31        // $vis:        visibility of the extern function (defaults to private)
32        // safe|unsafe  optional safety specifier (defaults to unsafe)
33        // $js_fn:      optional link_name (different javascript function name)
34        // $fn:         imported rust function name (default same js name)
35
36        [
37        $(module: $module:literal)? $(,)?
38        ]
39        $(
40            $(#[$fn_attrs:meta])*
41            $vis:vis $(safe$($_s:block)?)? $(unsafe$($_u:block)?)?
42            fn
43            $($js_fn:literal)?
44            $fn:ident
45            ($($param:ident: $param_ty:ty),* $(,)?) $(-> $fn_return:ty)?;
46        )*
47    ) => {
48        $( #[link(wasm_import_module = $module)] )?
49        unsafe extern "C" { $(
50            $(#[$fn_attrs])*
51            $( #[link_name = $js_fn] )?
52            $vis $(safe$($_s)?)? $(unsafe$($_u)?)?
53            fn $fn($($param: $param_ty),*) $(-> $fn_return)?;
54        )* }
55
56        /* // how it's manually done:
57        #[link(wasm_import_module = "api_canvas")]
58        unsafe extern "C" {
59            #[link_name = "fill_rect"]
60            pub safe fn fill_rect(x: f64, y: f64, w: f64, h: f64);
61            pub safe fn set_color(r: u8, g: u8, b: u8);
62        }
63        */
64    };
65}
66#[doc(inline)]
67#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "unsafe_ffi")))]
68pub use _js_reexport as js_reexport;
69
70// WIPZONE
71/*
72            // FAILS
73            $( =>
74                $vis2:vis  // $(unsafe$($_u2:block)?)?
75                $fn2:ident ($($param2:ident: $param2_ty:ty),* $(,)?) // $(-> $fn2_return:ty)?
76                $body2:block
77            )?
78        // WIP FAILS
79        // $(
80        // $( #[link_name = $js_fn] )?
81        // $vis2 $fn2($($param2: $param2_ty),*) $body2
82        // )*
83*/
84
85// IMPROVE
86// - accept generics, lifetimes
87// - custom visibility (not just pub)
88// - custom safety
89// $( impl $impl_ty {
90//     $(
91//         $(#[$fn_attrs])*
92//         #[no_mangle]
93//         // $shared_vis const $(async$($_a)?)? $(safe$($_s)?)? $(unsafe$($_u)?)?
94//         pub extern "C" fn $fn($($param: $param_ty),+) $(-> $fn_return)? {
95//             unsafe { [<js_$fn>]($($param),*); }
96//         }
97//     )*
98// } )?