1use proc_macro::TokenStream;
2use quote::quote;
3use std::sync::atomic::AtomicU64;
4use std::sync::Mutex;
5use syn::ItemStruct;
6
7static UNIQUE_COUNTER: Mutex<AtomicU64> = Mutex::new(AtomicU64::new(0));
8
9#[proc_macro_attribute]
10pub fn manifold_warp(_attr: TokenStream, input: TokenStream) -> TokenStream {
11 let structt = syn::parse_macro_input!(input as ItemStruct);
12 let struct_ident = structt.ident.clone();
13 let struct_name = struct_ident.to_string();
14
15 let unique_id = match UNIQUE_COUNTER.lock() {
16 Ok(guard) => guard.fetch_add(1, std::sync::atomic::Ordering::SeqCst),
17 Err(e) => panic!("Could not lock unique counter: {}", e),
18 };
19
20 let extern_c_fn_ident = proc_macro2::Ident::new(
21 format!(
22 "manifold3d_manifold_warp_fn_{}_{}",
23 struct_name.to_ascii_lowercase(),
24 unique_id
25 )
26 .as_str(),
27 proc_macro2::Span::call_site(),
28 );
29
30 let output = quote!(
31 #structt
32
33 const _: () = {
34 use manifold3d::manifold::WarpVertex;
35
36 #[no_mangle]
37 #[doc(hidden)]
38 pub unsafe extern "C" fn #extern_c_fn_ident(
39 x: f64,
40 y: f64,
41 z: f64,
42 ctx: *mut ::std::os::raw::c_void
43 ) -> manifold3d::sys::ManifoldVec3 {
44 let warp = &*(ctx as *mut #struct_ident);
45 let result = warp.warp_vertex(manifold3d::types::Point3::new(x, y, z));
46 result.into()
47 }
48
49 #[automatically_derived]
50 impl manifold3d::manifold::ExternCWarpFn for #struct_ident {
51 fn extern_c_warp_fn(&self) -> unsafe extern "C" fn(
52 f64,
53 f64,
54 f64,
55 *mut std::os::raw::c_void
56 ) -> manifold3d::sys::ManifoldVec3 {
57 #extern_c_fn_ident
58 }
59 }
60 };
61
62 #[automatically_derived]
63 impl manifold3d::manifold::Warp for #struct_ident {}
64 );
65 output.into()
66}
67
68#[proc_macro_attribute]
69pub fn manifold_manage_vertex_properties(_attr: TokenStream, input: TokenStream) -> TokenStream {
70 let structt = syn::parse_macro_input!(input as ItemStruct);
71 let struct_ident = structt.ident.clone();
72 let struct_name = struct_ident.to_string();
73
74 let unique_id = match UNIQUE_COUNTER.lock() {
75 Ok(guard) => guard.fetch_add(1, std::sync::atomic::Ordering::SeqCst),
76 Err(e) => panic!("Could not lock unique counter: {}", e),
77 };
78
79 let extern_c_fn_ident = proc_macro2::Ident::new(
80 format!(
81 "manifold3d_manifold_replace_vertex_properties_fn_{}_{}",
82 struct_name.to_ascii_lowercase(),
83 unique_id
84 )
85 .as_str(),
86 proc_macro2::Span::call_site(),
87 );
88
89 let output = quote!(
90 #structt
91
92 const _: () = {
93 use manifold3d::manifold::ReplaceVertexProperties;
94 #[no_mangle]
95 #[doc(hidden)]
96 pub unsafe extern "C" fn #extern_c_fn_ident(
97 new_prop: *mut f64,
98 position: manifold3d_sys::ManifoldVec3,
99 old_prop: *const f64,
100 ctx: *mut ::std::os::raw::c_void,
101 ) {
102 let c_ctx = &*(ctx as *const manifold3d::manifold::ReplaceVertexPropertiesCCtx);
103 let manage_vertex_properties =
104 &*(c_ctx.manage_vertex_properties_ptr as *const #struct_ident);
105
106 unsafe fn convert_ctx<'a, T>(ctx: *mut ::std::os::raw::c_void) -> &'a mut T {
108 &mut *(ctx as *mut T)
109 }
110 let manage_vertex_properties_ctx = convert_ctx(c_ctx.ctx_ptr);
111
112 let old_properties = if old_prop.is_null() {
113 &[0.0; 0]
114 } else {
115 std::slice::from_raw_parts(old_prop, c_ctx.old_properties_per_vertex_count)
116 };
117
118 let mut new_properties = Vec::from_raw_parts(
119 new_prop,
120 c_ctx.new_properties_per_vertex_count,
121 c_ctx.new_properties_per_vertex_count,
122 );
123
124 manage_vertex_properties.replace_vertex_properties(
125 manage_vertex_properties_ctx,
126 position.into(),
127 old_properties,
128 new_properties.as_mut_slice(),
129 );
130
131 ::std::mem::forget(new_properties);
133 }
134
135 #[automatically_derived]
136 impl manifold3d::manifold::ExternCReplaceVertexPropertiesFn for MyPropertyReplacer {
137 fn extern_c_replace_vertex_properties_fn(
138 &self,
139 ) -> unsafe extern "C" fn(
140 *mut f64,
141 manifold3d_sys::ManifoldVec3,
142 *const f64,
143 *mut ::std::os::raw::c_void,
144 ) -> () {
145 #extern_c_fn_ident
146 }
147 }
148 };
149
150 #[automatically_derived]
151 impl manifold3d::manifold::ManageVertexProperties for MyPropertyReplacer {}
152 );
153 output.into()
154}