Support enum repr types from std::os::raw
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 9d673c6..c6d59d8 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -9,8 +9,8 @@
use crate::syntax::symbol::Symbol;
use crate::syntax::trivial::{self, TrivialReason};
use crate::syntax::{
- derive, mangle, Api, Doc, Enum, ExternFn, ExternType, Pair, Signature, Struct, Trait, Type,
- TypeAlias, Types, Var,
+ derive, mangle, Api, Doc, Enum, EnumRepr, ExternFn, ExternType, Pair, Signature, Struct, Trait,
+ Type, TypeAlias, Types, Var,
};
use proc_macro2::Ident;
@@ -317,8 +317,12 @@
}
fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
+ let repr = match &enm.repr {
+ EnumRepr::Foreign { .. } => return,
+ EnumRepr::Native { atom, .. } => *atom,
+ };
write!(out, "enum class {} : ", enm.name.cxx);
- write_atom(out, enm.repr);
+ write_atom(out, repr);
writeln!(out, ";");
}
@@ -376,6 +380,10 @@
}
fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
+ let repr = match &enm.repr {
+ EnumRepr::Foreign { .. } => return,
+ EnumRepr::Native { atom, .. } => *atom,
+ };
out.set_namespace(&enm.name.namespace);
let guard = format!("CXXBRIDGE1_ENUM_{}", enm.name.to_symbol());
writeln!(out, "#ifndef {}", guard);
@@ -384,7 +392,7 @@
writeln!(out, "//{}", line);
}
write!(out, "enum class {} : ", enm.name.cxx);
- write_atom(out, enm.repr);
+ write_atom(out, repr);
writeln!(out, " {{");
for variant in &enm.variants {
for line in variant.doc.to_string().lines() {
@@ -397,6 +405,10 @@
}
fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
+ let repr = match &enm.repr {
+ EnumRepr::Foreign { .. } => return,
+ EnumRepr::Native { atom, .. } => *atom,
+ };
out.set_namespace(&enm.name.namespace);
out.include.type_traits = true;
writeln!(
@@ -405,11 +417,11 @@
enm.name.cxx,
);
write!(out, "static_assert(sizeof({}) == sizeof(", enm.name.cxx);
- write_atom(out, enm.repr);
+ write_atom(out, repr);
writeln!(out, "), \"incorrect size\");");
for variant in &enm.variants {
write!(out, "static_assert(static_cast<");
- write_atom(out, enm.repr);
+ write_atom(out, repr);
writeln!(
out,
">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e2fa646..3a8c87e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -293,7 +293,7 @@
let ident = &enm.name.rust;
let doc = &enm.doc;
let attrs = &enm.attrs;
- let repr = enm.repr;
+ let repr = &enm.repr;
let type_id = type_id(&enm.name);
let variants = enm.variants.iter().map(|variant| {
let doc = &variant.doc;
diff --git a/syntax/mod.rs b/syntax/mod.rs
index b22587f..1d98634 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -36,7 +36,7 @@
use proc_macro2::{Ident, Span};
use syn::punctuated::Punctuated;
use syn::token::{Brace, Bracket, Paren};
-use syn::{Attribute, Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
+use syn::{Attribute, Expr, Generics, Lifetime, LitInt, Path, Token, Type as RustType};
pub use self::atom::Atom;
pub use self::derive::{Derive, Trait};
@@ -113,11 +113,15 @@
pub variants: Vec<Variant>,
pub variants_from_header: bool,
pub variants_from_header_attr: Option<Attribute>,
- pub repr: Atom,
- pub repr_type: Type,
+ pub repr: EnumRepr,
pub explicit_repr: bool,
}
+pub enum EnumRepr {
+ Native { atom: Atom, repr_type: Type },
+ Foreign { rust_type: Path },
+}
+
pub struct ExternFn {
pub lang: Lang,
pub doc: Doc,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index bcf75ef..32d36eb 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -4,9 +4,9 @@
use crate::syntax::report::Errors;
use crate::syntax::Atom::*;
use crate::syntax::{
- attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, ForeignName, Impl, Include,
- IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Ptr, Receiver, Ref, Signature,
- SliceRef, Struct, Ty1, Type, TypeAlias, Var, Variant,
+ attrs, error, Api, Array, Derive, Doc, Enum, EnumRepr, ExternFn, ExternType, ForeignName, Impl,
+ Include, IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Ptr, Receiver, Ref,
+ Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var, Variant,
};
use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
use quote::{format_ident, quote, quote_spanned};
@@ -241,6 +241,10 @@
let name = pair(namespace, &item.ident, cxx_name, rust_name);
let repr_ident = Ident::new(repr.as_ref(), Span::call_site());
let repr_type = Type::Ident(NamedType::new(repr_ident));
+ let repr = EnumRepr::Native {
+ atom: repr,
+ repr_type,
+ };
let generics = Lifetimes {
lt_token: None,
lifetimes: Punctuated::new(),
@@ -262,7 +266,6 @@
variants_from_header,
variants_from_header_attr,
repr,
- repr_type,
explicit_repr,
})
}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index b0c2f20..33f20fa 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
use crate::syntax::atom::Atom::*;
use crate::syntax::{
- Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Lifetimes, NamedType, Ptr, Receiver,
- Ref, Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
+ Array, Atom, Derive, Enum, EnumRepr, ExternFn, ExternType, Impl, Lifetimes, NamedType, Ptr,
+ Receiver, Ref, Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote_spanned, ToTokens};
@@ -280,6 +280,15 @@
}
}
+impl ToTokens for EnumRepr {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ EnumRepr::Native { atom, repr_type: _ } => atom.to_tokens(tokens),
+ EnumRepr::Foreign { rust_type } => rust_type.to_tokens(tokens),
+ }
+ }
+}
+
impl ToTokens for NamedType {
fn to_tokens(&self, tokens: &mut TokenStream) {
let NamedType { rust, generics } = self;
diff --git a/syntax/types.rs b/syntax/types.rs
index c8d3398..c54682b 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -7,7 +7,7 @@
use crate::syntax::trivial::{self, TrivialReason};
use crate::syntax::visit::{self, Visit};
use crate::syntax::{
- toposort, Api, Atom, Enum, ExternType, Impl, Lifetimes, Pair, Struct, Type, TypeAlias,
+ toposort, Api, Atom, Enum, EnumRepr, ExternType, Impl, Lifetimes, Pair, Struct, Type, TypeAlias,
};
use proc_macro2::Ident;
use quote::ToTokens;
@@ -88,7 +88,12 @@
add_resolution(&strct.name, &strct.generics);
}
Api::Enum(enm) => {
- all.insert(&enm.repr_type);
+ match &enm.repr {
+ EnumRepr::Native { atom: _, repr_type } => {
+ all.insert(repr_type);
+ }
+ EnumRepr::Foreign { rust_type: _ } => {}
+ }
let ident = &enm.name.rust;
if !type_names.insert(ident)
&& (!cxx.contains(ident)