manifold3d_macros/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use proc_macro::TokenStream;
use quote::quote;
use std::sync::atomic::AtomicU64;
use std::sync::Mutex;
use syn::ItemStruct;

static UNIQUE_COUNTER: Mutex<AtomicU64> = Mutex::new(AtomicU64::new(0));

#[proc_macro_attribute]
pub fn manifold_warp(_attr: TokenStream, input: TokenStream) -> TokenStream {
    let structt = syn::parse_macro_input!(input as ItemStruct);
    let struct_ident = structt.ident.clone();
    let struct_name = struct_ident.to_string();

    let unique_id = match UNIQUE_COUNTER.lock() {
        Ok(guard) => guard.fetch_add(1, std::sync::atomic::Ordering::SeqCst),
        Err(e) => panic!("Could not lock unique counter: {}", e),
    };

    let extern_c_fn_ident = proc_macro2::Ident::new(
        format!(
            "manifold3d_manifold_extern_c_warp_fn_{}_{}",
            struct_name.to_ascii_lowercase(),
            unique_id
        )
        .as_str(),
        proc_macro2::Span::call_site(),
    );

    let output = quote!(
        #structt

        const _: () = {
            use manifold3d::types::manifold::vertex::WarpVertex;

            #[no_mangle]
            #[doc(hidden)]
            pub unsafe extern "C" fn #extern_c_fn_ident(
                x: f64,
                y: f64,
                z: f64,
                ctx: *mut ::std::os::raw::c_void
            ) -> manifold3d::sys::ManifoldVec3 {
                let warp = &*(ctx as *mut #struct_ident);
                let result = warp.warp_vertex(manifold3d::types::math::Point3::new(x, y, z));
                result.into()
            }

            #[automatically_derived]
            impl manifold3d::types::manifold::vertex::ExternCWarpFn for #struct_ident {
                fn extern_c_warp_fn(&self) -> unsafe extern "C" fn(
                    f64,
                    f64,
                    f64,
                    *mut std::os::raw::c_void
                ) -> manifold3d::sys::ManifoldVec3 {
                    #extern_c_fn_ident
                }
            }
        };

        #[automatically_derived]
        impl manifold3d::types::manifold::vertex::Warp for #struct_ident {}
    );
    output.into()
}