wasmedge_bindgen_macro/
lib.rs

1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::{quote, ToTokens};
5use syn;
6
7static mut FUNC_NUMBER: i32 = 0;
8
9enum RetTypes {
10	U8 = 1,
11	I8 = 2,
12	U16 = 3,
13	I16 = 4,
14	U32 = 5,
15	I32 = 6,
16	U64 = 7,
17	I64 = 8,
18	F32 = 9,
19	F64 = 10,
20	Bool = 11,
21	Char = 12,
22	U8Array = 21,
23	I8Array = 22,
24	U16Array = 23,
25	I16Array = 24,
26	U32Array = 25,
27	I32Array = 26,
28	U64Array = 27,
29	I64Array = 28,
30	String = 31,
31}
32
33#[proc_macro_attribute]
34pub fn wasmedge_bindgen(_: TokenStream, item: TokenStream) -> TokenStream {
35	let mut ast: syn::ItemFn = syn::parse(item).unwrap();
36
37	let func_ident = ast.sig.ident;
38
39	let ori_run: String;
40	unsafe {
41		ori_run = format!("run{}", FUNC_NUMBER);
42		FUNC_NUMBER += 1;
43	}
44	let ori_run_ident = proc_macro2::Ident::new(ori_run.as_str(), proc_macro2::Span::call_site());
45	ast.sig.ident = ori_run_ident.clone();
46
47	let (arg_names, arg_values) = parse_params(&ast);
48	let (ret_names, ret_pointers, ret_types, ret_sizes, is_rust_result) = parse_returns(&ast);
49	let ret_len = ret_names.len();
50	let ret_i = (0..ret_len).map(syn::Index::from);
51
52	let params_len = arg_names.len();
53	let i = (0..params_len).map(syn::Index::from);
54
55	let ret_result = match is_rust_result {
56		true => quote! {
57			match #ori_run_ident(#(#arg_names),*) {
58				Ok((#(#ret_names),*)) => {
59					let mut result_vec = vec![0; #ret_len * 3];
60					#(
61						result_vec[#ret_i * 3 + 2] = #ret_sizes;
62						result_vec[#ret_i * 3] = #ret_pointers;
63						result_vec[#ret_i * 3 + 1] = #ret_types;
64					)*
65					let result_vec = std::mem::ManuallyDrop::new(result_vec);
66					// return_result
67					let mut rvec = vec![0 as u8; 9];
68					rvec.splice(1..5, (result_vec.as_ptr() as i32).to_le_bytes());
69					rvec.splice(5..9, (#ret_len as i32).to_le_bytes());
70					let rvec = std::mem::ManuallyDrop::new(rvec);
71					return rvec.as_ptr() as i32;
72				}
73				Err(message) => {
74					let message = std::mem::ManuallyDrop::new(message);
75					// return_error
76					let mut rvec = vec![1 as u8; 9];
77					rvec.splice(1..5, (message.as_ptr() as i32).to_le_bytes());
78					rvec.splice(5..9, (message.len() as i32).to_le_bytes());
79					let rvec = std::mem::ManuallyDrop::new(rvec);
80					return rvec.as_ptr() as i32;
81				}
82			}
83		},
84		false => quote! {
85			let (#(#ret_names),*) = #ori_run_ident(#(#arg_names),*);
86			let mut result_vec = vec![0; #ret_len * 3];
87			#(
88				result_vec[#ret_i * 3 + 2] = #ret_sizes;
89				result_vec[#ret_i * 3] = #ret_pointers;
90				result_vec[#ret_i * 3 + 1] = #ret_types;
91			)*
92			let result_vec = std::mem::ManuallyDrop::new(result_vec);
93			// return_result
94			let mut rvec = vec![0 as u8; 9];
95			rvec.splice(1..5, (result_vec.as_ptr() as i32).to_le_bytes());
96			rvec.splice(5..9, (#ret_len as i32).to_le_bytes());
97			let rvec = std::mem::ManuallyDrop::new(rvec);
98			return rvec.as_ptr() as i32;
99		}
100	};
101
102	let gen = quote! {
103
104		#[no_mangle]
105		pub unsafe extern "C" fn #func_ident(params_pointer: *mut u32, params_count: i32) -> i32 {
106			if #params_len != params_count as usize {
107				let err_msg = format!("Invalid params count, expect {}, got {}", #params_len, params_count);
108				let err_msg = std::mem::ManuallyDrop::new(err_msg);
109				// return_error
110				let mut rvec = vec![1 as u8; 9];
111				rvec.splice(1..5, (err_msg.as_ptr() as i32).to_le_bytes());
112				rvec.splice(5..9, (err_msg.len() as i32).to_le_bytes());
113				let rvec = std::mem::ManuallyDrop::new(rvec);
114				return rvec.as_ptr() as i32;
115			}
116
117			#(
118			let pointer = *params_pointer.offset(#i * 2) as *mut u8;
119			let size= *params_pointer.offset(#i * 2 + 1);
120			let #arg_names = #arg_values;
121			)*
122
123			#ret_result;
124		}
125	};
126
127	let ori_run_str = ast.to_token_stream().to_string();
128	let x = gen.to_string() + &ori_run_str;
129	x.parse().unwrap()
130}
131
132
133fn parse_returns(ast: &syn::ItemFn) -> (Vec::<syn::Ident>, Vec::<proc_macro2::TokenStream>, Vec::<i32>, Vec::<proc_macro2::TokenStream>, bool) {
134	let mut ret_names = Vec::<syn::Ident>::new();
135	let mut ret_pointers = Vec::<proc_macro2::TokenStream>::new();
136	let mut ret_types = Vec::<i32>::new();
137	let mut ret_sizes = Vec::<proc_macro2::TokenStream>::new();
138	let mut is_rust_result = false;
139
140	let mut prep_types = |seg: &syn::PathSegment, pos: usize| {
141		let ret_name = quote::format_ident!("ret{}", pos.to_string());
142		match seg.ident.to_string().as_str() {
143			"u8" => {
144				ret_pointers.push(quote! {{
145					let x = #ret_name.to_le_bytes()[..].to_vec();
146					std::mem::ManuallyDrop::new(x).as_ptr() as *const u8 as i32
147				}});
148				ret_names.push(ret_name);
149				ret_types.push(RetTypes::U8 as i32);
150				ret_sizes.push(quote! {
151					1
152				});
153			}
154			"i8" => {
155				ret_pointers.push(quote! {{
156					let x = #ret_name.to_le_bytes()[..].to_vec();
157					std::mem::ManuallyDrop::new(x).as_ptr() as *const i8 as i32
158				}});
159				ret_names.push(ret_name);
160				ret_types.push(RetTypes::I8 as i32);
161				ret_sizes.push(quote! {
162					1
163				});
164			}
165			"u16" => {
166				ret_pointers.push(quote! {{
167					let x = #ret_name.to_le_bytes()[..].to_vec();
168					std::mem::ManuallyDrop::new(x).as_ptr() as *const u16 as i32
169				}});
170				ret_names.push(ret_name);
171				ret_types.push(RetTypes::U16 as i32);
172				ret_sizes.push(quote! {
173					2
174				});
175			}
176			"i16" => {
177				ret_pointers.push(quote! {{
178					let x = #ret_name.to_le_bytes()[..].to_vec();
179					std::mem::ManuallyDrop::new(x).as_ptr() as *const i16 as i32
180				}});
181				ret_names.push(ret_name);
182				ret_types.push(RetTypes::I16 as i32);
183				ret_sizes.push(quote! {
184					2
185				});
186			}
187			"u32" => {
188				ret_pointers.push(quote! {{
189					let x = #ret_name.to_le_bytes()[..].to_vec();
190					std::mem::ManuallyDrop::new(x).as_ptr() as *const u32 as i32
191				}});
192				ret_names.push(ret_name);
193				ret_types.push(RetTypes::U32 as i32);
194				ret_sizes.push(quote! {
195					4
196				});
197			}
198			"i32" => {
199				ret_pointers.push(quote! {{
200					let x = #ret_name.to_le_bytes()[..].to_vec();
201					std::mem::ManuallyDrop::new(x).as_ptr() as *const i32 as i32
202				}});
203				ret_names.push(ret_name);
204				ret_types.push(RetTypes::I32 as i32);
205				ret_sizes.push(quote! {
206					4
207				});
208			}
209			"u64" => {
210				ret_pointers.push(quote! {{
211					let x = #ret_name.to_le_bytes()[..].to_vec();
212					std::mem::ManuallyDrop::new(x).as_ptr() as *const u64 as i32
213				}});
214				ret_names.push(ret_name);
215				ret_types.push(RetTypes::U64 as i32);
216				ret_sizes.push(quote! {
217					8
218				});
219			}
220			"i64" => {
221				ret_pointers.push(quote! {{
222					let x = #ret_name.to_le_bytes()[..].to_vec();
223					std::mem::ManuallyDrop::new(x).as_ptr() as *const i64 as i32
224				}});
225				ret_names.push(ret_name);
226				ret_types.push(RetTypes::I64 as i32);
227				ret_sizes.push(quote! {
228					8
229				});
230			}
231			"f32" => {
232				ret_pointers.push(quote! {{
233					let x = #ret_name.to_le_bytes()[..].to_vec();
234					std::mem::ManuallyDrop::new(x).as_ptr() as *const f32 as i32
235				}});
236				ret_names.push(ret_name);
237				ret_types.push(RetTypes::F32 as i32);
238				ret_sizes.push(quote! {
239					4
240				});
241			}
242			"f64" => {
243				ret_pointers.push(quote! {{
244					let x = #ret_name.to_le_bytes()[..].to_vec();
245					std::mem::ManuallyDrop::new(x).as_ptr() as *const f64 as i32
246				}});
247				ret_names.push(ret_name);
248				ret_types.push(RetTypes::F64 as i32);
249				ret_sizes.push(quote! {
250					8
251				});
252			}
253			"bool" => {
254				ret_pointers.push(quote! {{
255					let x = #ret_name.to_le_bytes()[..].to_vec();
256					std::mem::ManuallyDrop::new(x).as_ptr() as *const bool as i32
257				}});
258				ret_names.push(ret_name);
259				ret_types.push(RetTypes::Bool as i32);
260				ret_sizes.push(quote! {
261					1
262				});
263			}
264			"char" => {
265				ret_pointers.push(quote! {{
266					let x = #ret_name.to_le_bytes()[..].to_vec();
267					std::mem::ManuallyDrop::new(x).as_ptr() as *const char as i32
268				}});
269				ret_names.push(ret_name);
270				ret_types.push(RetTypes::Char as i32);
271				ret_sizes.push(quote! {
272					4
273				});
274			}
275			"String" => {
276				ret_pointers.push(quote! {
277					std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
278				});
279				ret_types.push(RetTypes::String as i32);
280				ret_sizes.push(quote! {
281					#ret_name.len() as i32
282				});
283				ret_names.push(ret_name);
284			}
285			"Vec" => {
286				match &seg.arguments {
287					syn::PathArguments::AngleBracketed(args) => {
288						match args.args.first().unwrap() {
289							syn::GenericArgument::Type(arg_type) => {
290								match arg_type {
291									syn::Type::Path(arg_type_path) => {
292										let arg_seg = arg_type_path.path.segments.first().unwrap();
293										match arg_seg.ident.to_string().as_str() {
294											"u8" => {
295												ret_pointers.push(quote! {
296													std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
297												});
298												ret_sizes.push(quote! {
299													#ret_name.len() as i32
300												});
301												ret_types.push(RetTypes::U8Array as i32);
302												ret_names.push(ret_name);
303											}
304											"i8" => {
305												ret_pointers.push(quote! {
306													std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
307												});
308												ret_sizes.push(quote! {
309													#ret_name.len() as i32
310												});
311												ret_types.push(RetTypes::I8Array as i32);
312												ret_names.push(ret_name);
313											}
314											"u16" => {
315												ret_pointers.push(quote! {
316													std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
317												});
318												ret_sizes.push(quote! {
319													#ret_name.len() as i32 * 2
320												});
321												ret_types.push(RetTypes::U16Array as i32);
322												ret_names.push(ret_name);
323											}
324											"i16" => {
325												ret_pointers.push(quote! {
326													std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
327												});
328												ret_sizes.push(quote! {
329													#ret_name.len() as i32 * 2
330												});
331												ret_types.push(RetTypes::I16Array as i32);
332												ret_names.push(ret_name);
333											}
334											"u32" => {
335												ret_pointers.push(quote! {
336													std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
337												});
338												ret_sizes.push(quote! {
339													#ret_name.len() as i32 * 4
340												});
341												ret_types.push(RetTypes::U32Array as i32);
342												ret_names.push(ret_name);
343											}
344											"i32" => {
345												ret_pointers.push(quote! {
346													std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
347												});
348												ret_sizes.push(quote! {
349													#ret_name.len() as i32 * 4
350												});
351												ret_types.push(RetTypes::I32Array as i32);
352												ret_names.push(ret_name);
353											}
354											"u64" => {
355												ret_pointers.push(quote! {
356													std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
357												});
358												ret_sizes.push(quote! {
359													#ret_name.len() as i32 * 8
360												});
361												ret_types.push(RetTypes::U64Array as i32);
362												ret_names.push(ret_name);
363											}
364											"i64" => {
365												ret_pointers.push(quote! {
366													std::mem::ManuallyDrop::new(#ret_name).as_ptr() as i32
367												});
368												ret_sizes.push(quote! {
369													#ret_name.len() as i32 * 8
370												});
371												ret_types.push(RetTypes::I64Array as i32);
372												ret_names.push(ret_name);
373											}
374											_ => {}
375										}
376									}
377									_ => {}
378								}
379							}
380							_ => {}
381						}
382					}
383					_ => {}
384				}
385			}	
386			_ => {}
387		}
388	};
389
390	match ast.sig.output {
391		syn::ReturnType::Type(_, ref rt) => {
392			match &**rt {
393				syn::Type::Path(type_path) => {
394					let seg = &type_path.path.segments.first().unwrap();
395					let seg_type = seg.ident.to_string();
396					if seg_type == "Result"  {
397						is_rust_result = true;
398						match &seg.arguments {
399							syn::PathArguments::AngleBracketed(args) => {
400								match args.args.first().unwrap() {
401									syn::GenericArgument::Type(arg_type) => {
402										match arg_type {
403											syn::Type::Path(arg_type_path) => {
404												let arg_seg = arg_type_path.path.segments.first().unwrap();
405												prep_types(&arg_seg, 0)
406											}
407											syn::Type::Tuple(arg_type_tuple) => {
408												for (pos, elem) in arg_type_tuple.elems.iter().enumerate() {
409													match elem {
410														syn::Type::Path(type_path) => {
411															let seg = &type_path.path.segments.first().unwrap();
412															prep_types(&seg, pos);
413														}
414														_ => {}
415													}
416												}
417											}
418											_ => {}
419										}
420									}
421									_ => {}
422								}
423							}
424							_ => {}
425						}
426					} else {
427						prep_types(&seg, 0);
428					}
429				}
430				syn::Type::Tuple(type_tuple) => {
431					for (pos, elem) in type_tuple.elems.iter().enumerate() {
432						match elem {
433							syn::Type::Path(type_path) => {
434								let seg = &type_path.path.segments.first().unwrap();
435								prep_types(&seg, pos);
436							}
437							_ => {}
438						}
439					}
440				}
441				_ => {}
442			}
443		}
444		_ => {}
445	}
446
447	(ret_names, ret_pointers, ret_types, ret_sizes, is_rust_result)
448}
449
450fn parse_params(ast: &syn::ItemFn) -> (Vec::<syn::Ident>, Vec::<proc_macro2::TokenStream>) {
451	let mut arg_names = Vec::<syn::Ident>::new();
452	let mut arg_values = Vec::<proc_macro2::TokenStream>::new();
453
454	let params_iter = ast.sig.inputs.iter();
455	for (pos, param) in params_iter.enumerate() {
456		match param {
457			syn::FnArg::Typed(param_type) => {
458				match &*param_type.ty {
459					syn::Type::Path(type_path) => {
460						let seg = &type_path.path.segments.first().unwrap();
461						match seg.ident.to_string().as_str() {
462							"Vec" => {
463								match &seg.arguments {
464									syn::PathArguments::AngleBracketed(args) => {
465										match args.args.first().unwrap() {
466											syn::GenericArgument::Type(arg_type) => {
467												match arg_type {
468													syn::Type::Path(arg_type_path) => {
469														let arg_seg = arg_type_path.path.segments.first().unwrap();
470														match arg_seg.ident.to_string().as_str() {
471															"u8" => {
472																arg_names.push(quote::format_ident!("arg{}", pos));
473																arg_values.push(quote! {
474																	Vec::from_raw_parts(pointer, size as usize, size as usize)
475																})
476															}
477															"i8" => {
478																arg_names.push(quote::format_ident!("arg{}", pos));
479																arg_values.push(quote! {
480																	Vec::from_raw_parts(pointer as *mut i8, size as usize, size as usize)
481																})
482															}
483															"u16" => {
484																arg_names.push(quote::format_ident!("arg{}", pos));
485																arg_values.push(quote! {
486																	Vec::from_raw_parts(pointer as *mut u16, size as usize, size as usize)
487																})
488															}
489															"i16" => {
490																arg_names.push(quote::format_ident!("arg{}", pos));
491																arg_values.push(quote! {
492																	Vec::from_raw_parts(pointer as *mut i16, size as usize, size as usize)
493																})
494															}
495															"u32" => {
496																arg_names.push(quote::format_ident!("arg{}", pos));
497																arg_values.push(quote! {
498																	Vec::from_raw_parts(pointer as *mut u32, size as usize, size as usize)
499																})
500															}
501															"i32" => {
502																arg_names.push(quote::format_ident!("arg{}", pos));
503																arg_values.push(quote! {
504																	Vec::from_raw_parts(pointer as *mut i32, size as usize, size as usize)
505																})
506															}
507															"u64" => {
508																arg_names.push(quote::format_ident!("arg{}", pos));
509																arg_values.push(quote! {
510																	Vec::from_raw_parts(pointer as *mut u64, size as usize, size as usize)
511																})
512															}
513															"i64" => {
514																arg_names.push(quote::format_ident!("arg{}", pos));
515																arg_values.push(quote! {
516																	Vec::from_raw_parts(pointer as *mut i64, size as usize, size as usize)
517																})
518															}
519															_ => {}
520														}
521													}
522													_ => {}
523												}
524											}
525											_ => {}
526										}
527									}
528									_ => {}
529								}
530							}
531							"bool" => {
532								arg_names.push(quote::format_ident!("arg{}", pos));
533								arg_values.push(quote! {
534									Vec::from_raw_parts(pointer as *mut bool, size as usize, size as usize)[0]
535								})
536							}
537							"char" => {
538								arg_names.push(quote::format_ident!("arg{}", pos));
539								arg_values.push(quote! {
540									Vec::from_raw_parts(pointer as *mut char, size as usize, size as usize)[0]
541								})
542							}
543							"i8" => {
544								arg_names.push(quote::format_ident!("arg{}", pos));
545								arg_values.push(quote! {
546									Vec::from_raw_parts(pointer as *mut i8, size as usize, size as usize)[0]
547								})
548							}
549							"u8" => {
550								arg_names.push(quote::format_ident!("arg{}", pos));
551								arg_values.push(quote! {
552									Vec::from_raw_parts(pointer as *mut u8, size as usize, size as usize)[0]
553								})
554							}
555							"i16" => {
556								arg_names.push(quote::format_ident!("arg{}", pos));
557								arg_values.push(quote! {
558									Vec::from_raw_parts(pointer as *mut i16, size as usize, size as usize)[0]
559								})
560							}
561							"u16" => {
562								arg_names.push(quote::format_ident!("arg{}", pos));
563								arg_values.push(quote! {
564									Vec::from_raw_parts(pointer as *mut u16, size as usize, size as usize)[0]
565								})
566							}
567							"i32" => {
568								arg_names.push(quote::format_ident!("arg{}", pos));
569								arg_values.push(quote! {
570									Vec::from_raw_parts(pointer as *mut i32, size as usize, size as usize)[0]
571								})
572							}
573							"u32" => {
574								arg_names.push(quote::format_ident!("arg{}", pos));
575								arg_values.push(quote! {
576									Vec::from_raw_parts(pointer as *mut u32, size as usize, size as usize)[0]
577								})
578							}
579							"i64" => {
580								arg_names.push(quote::format_ident!("arg{}", pos));
581								arg_values.push(quote! {
582									Vec::from_raw_parts(pointer as *mut i64, size as usize, size as usize)[0]
583								})
584							}
585							"u64" => {
586								arg_names.push(quote::format_ident!("arg{}", pos));
587								arg_values.push(quote! {
588									Vec::from_raw_parts(pointer as *mut u64, size as usize, size as usize)[0]
589								})
590							}
591							"f32" => {
592								arg_names.push(quote::format_ident!("arg{}", pos));
593								arg_values.push(quote! {
594									Vec::from_raw_parts(pointer as *mut f32, size as usize, size as usize)[0]
595								})
596							}
597							"f64" => {
598								arg_names.push(quote::format_ident!("arg{}", pos));
599								arg_values.push(quote! {
600									Vec::from_raw_parts(pointer as *mut f64, size as usize, size as usize)[0]
601								})
602							}
603							"String" => {
604								arg_names.push(quote::format_ident!("arg{}", pos));
605								arg_values.push(quote! {
606									std::str::from_utf8(&Vec::from_raw_parts(pointer, size as usize, size as usize)).unwrap().to_string()
607								})
608							}
609							_ => {}
610						}
611					}
612					syn::Type::Reference(_) => {
613
614					}
615					syn::Type::Slice(_) => {
616
617					}
618					_ => {}
619				}
620			}
621			_ => {}
622		}
623	}
624
625	(arg_names, arg_values)
626}