mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-18 23:41:24 +00:00
Generate accessors for public struct fields
Automatically infer public struct fields as "JS wants to access this" and generate appropriate getters/setters for the field. At this time the field is required to implement `Copy`, but we will probably want to relax that in the future to at least encompass `JsValue` and maybe other `Clone` values as well. Closes #121
This commit is contained in:
@ -68,6 +68,15 @@ pub struct Function {
|
||||
|
||||
pub struct Struct {
|
||||
pub name: syn::Ident,
|
||||
pub fields: Vec<StructField>,
|
||||
}
|
||||
|
||||
pub struct StructField {
|
||||
pub name: syn::Ident,
|
||||
pub struct_name: syn::Ident,
|
||||
pub ty: syn::Type,
|
||||
pub getter: syn::Ident,
|
||||
pub setter: syn::Ident,
|
||||
}
|
||||
|
||||
pub struct Enum {
|
||||
@ -415,7 +424,7 @@ impl Program {
|
||||
pub fn shared(&self) -> shared::Program {
|
||||
shared::Program {
|
||||
exports: self.exports.iter().map(|a| a.shared()).collect(),
|
||||
structs: self.structs.iter().map(|a| a.name.as_ref().to_string()).collect(),
|
||||
structs: self.structs.iter().map(|a| a.shared()).collect(),
|
||||
enums: self.enums.iter().map(|a| a.shared()).collect(),
|
||||
imports: self.imports.iter().map(|a| a.shared()).collect(),
|
||||
version: shared::version(),
|
||||
@ -659,7 +668,47 @@ impl ImportType {
|
||||
|
||||
impl Struct {
|
||||
fn from(s: syn::ItemStruct, _opts: BindgenAttrs) -> Struct {
|
||||
Struct { name: s.ident }
|
||||
let mut fields = Vec::new();
|
||||
if let syn::Fields::Named(names) = s.fields {
|
||||
for field in names.named.iter() {
|
||||
match field.vis {
|
||||
syn::Visibility::Public(..) => {}
|
||||
_ => continue,
|
||||
}
|
||||
let name = match field.ident {
|
||||
Some(n) => n,
|
||||
None => continue,
|
||||
};
|
||||
let getter = shared::struct_field_get(s.ident.as_ref(), name.as_ref());
|
||||
let setter = shared::struct_field_set(s.ident.as_ref(), name.as_ref());
|
||||
fields.push(StructField {
|
||||
name,
|
||||
struct_name: s.ident,
|
||||
ty: field.ty.clone(),
|
||||
getter: getter.into(),
|
||||
setter: setter.into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Struct {
|
||||
name: s.ident,
|
||||
fields,
|
||||
}
|
||||
}
|
||||
|
||||
fn shared(&self) -> shared::Struct {
|
||||
shared::Struct {
|
||||
name: self.name.as_ref().to_string(),
|
||||
fields: self.fields.iter().map(|s| s.shared()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StructField {
|
||||
fn shared(&self) -> shared::StructField {
|
||||
shared::StructField {
|
||||
name: self.name.as_ref().to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,6 +212,65 @@ impl ToTokens for ast::Struct {
|
||||
}
|
||||
}
|
||||
}).to_tokens(tokens);
|
||||
|
||||
for field in self.fields.iter() {
|
||||
field.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::StructField {
|
||||
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||
let name = &self.name;
|
||||
let struct_name = &self.struct_name;
|
||||
let ty = &self.ty;
|
||||
let getter = &self.getter;
|
||||
let setter = &self.setter;
|
||||
let desc = syn::Ident::from(format!("__wbindgen_describe_{}", getter));
|
||||
(quote! {
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn #getter(js: u32)
|
||||
-> <#ty as ::wasm_bindgen::convert::IntoWasmAbi>::Abi
|
||||
{
|
||||
use wasm_bindgen::__rt::{WasmRefCell, assert_not_null};
|
||||
use wasm_bindgen::convert::{GlobalStack, IntoWasmAbi};
|
||||
|
||||
fn assert_copy<T: Copy>(){}
|
||||
assert_copy::<#ty>();
|
||||
|
||||
let js = js as *mut WasmRefCell<#struct_name>;
|
||||
assert_not_null(js);
|
||||
let val = (*js).borrow().#name;
|
||||
<#ty as IntoWasmAbi>::into_abi(
|
||||
val,
|
||||
&mut GlobalStack::new(),
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn #setter(
|
||||
js: u32,
|
||||
val: <#ty as ::wasm_bindgen::convert::FromWasmAbi>::Abi,
|
||||
) {
|
||||
use wasm_bindgen::__rt::{WasmRefCell, assert_not_null};
|
||||
use wasm_bindgen::convert::{GlobalStack, FromWasmAbi};
|
||||
|
||||
let js = js as *mut WasmRefCell<#struct_name>;
|
||||
assert_not_null(js);
|
||||
let val = <#ty as FromWasmAbi>::from_abi(
|
||||
val,
|
||||
&mut GlobalStack::new(),
|
||||
);
|
||||
(*js).borrow_mut().#name = val;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn #desc() {
|
||||
use wasm_bindgen::describe::*;
|
||||
<#ty as WasmDescribe>::describe();
|
||||
|
||||
}
|
||||
}).to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user