Emit an ExternType impl for shared structs and enums

This commit is contained in:
David Tolnay 2020-10-07 17:09:48 -07:00
parent 9420532466
commit 8684cc51ad
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82

View File

@ -41,8 +41,8 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
for api in apis { for api in apis {
match api { match api {
Api::Include(_) | Api::RustType(_) | Api::Impl(_) => {} Api::Include(_) | Api::RustType(_) | Api::Impl(_) => {}
Api::Struct(strct) => expanded.extend(expand_struct(strct)), Api::Struct(strct) => expanded.extend(expand_struct(namespace, strct)),
Api::Enum(enm) => expanded.extend(expand_enum(enm)), Api::Enum(enm) => expanded.extend(expand_enum(namespace, enm)),
Api::CxxType(ety) => { Api::CxxType(ety) => {
let ident = &ety.ident; let ident = &ety.ident;
if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) { if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
@ -125,16 +125,18 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
} }
} }
fn expand_struct(strct: &Struct) -> TokenStream { fn expand_struct(namespace: &Namespace, strct: &Struct) -> TokenStream {
let ident = &strct.ident; let ident = &strct.ident;
let doc = &strct.doc; let doc = &strct.doc;
let derives = &strct.derives; let derives = &strct.derives;
let type_id = type_id(namespace, ident);
let fields = strct.fields.iter().map(|field| { let fields = strct.fields.iter().map(|field| {
// This span on the pub makes "private type in public interface" errors // This span on the pub makes "private type in public interface" errors
// appear in the right place. // appear in the right place.
let vis = Token![pub](field.ident.span()); let vis = Token![pub](field.ident.span());
quote!(#vis #field) quote!(#vis #field)
}); });
quote! { quote! {
#doc #doc
#[derive(#(#derives),*)] #[derive(#(#derives),*)]
@ -142,13 +144,19 @@ fn expand_struct(strct: &Struct) -> TokenStream {
pub struct #ident { pub struct #ident {
#(#fields,)* #(#fields,)*
} }
unsafe impl ::cxx::ExternType for #ident {
type Id = #type_id;
type Kind = ::cxx::kind::Trivial;
}
} }
} }
fn expand_enum(enm: &Enum) -> TokenStream { fn expand_enum(namespace: &Namespace, enm: &Enum) -> TokenStream {
let ident = &enm.ident; let ident = &enm.ident;
let doc = &enm.doc; let doc = &enm.doc;
let repr = enm.repr; let repr = enm.repr;
let type_id = type_id(namespace, ident);
let variants = enm.variants.iter().map(|variant| { let variants = enm.variants.iter().map(|variant| {
let variant_ident = &variant.ident; let variant_ident = &variant.ident;
let discriminant = &variant.discriminant; let discriminant = &variant.discriminant;
@ -156,6 +164,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
pub const #variant_ident: Self = #ident { repr: #discriminant }; pub const #variant_ident: Self = #ident { repr: #discriminant };
}) })
}); });
quote! { quote! {
#doc #doc
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
@ -168,6 +177,11 @@ fn expand_enum(enm: &Enum) -> TokenStream {
impl #ident { impl #ident {
#(#variants)* #(#variants)*
} }
unsafe impl ::cxx::ExternType for #ident {
type Id = #type_id;
type Kind = ::cxx::kind::Trivial;
}
} }
} }