Merge pull request #187 from jgalenson/enums

Support enums defined in C++ code.
This commit is contained in:
David Tolnay 2020-05-04 20:49:52 -07:00 committed by GitHub
commit de471c9a22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 6 deletions

View File

@ -66,7 +66,11 @@ pub(super) fn gen(
}
Api::Enum(enm) => {
out.next_section();
write_enum(out, enm);
if types.cxx.contains(&enm.ident) {
check_enum(out, enm);
} else {
write_enum(out, enm);
}
}
Api::RustType(ety) => {
if let Some(methods) = methods_for_type.get(&ety.ident) {
@ -373,6 +377,27 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
writeln!(out, "}};");
}
fn check_enum(out: &mut OutFile, enm: &Enum) {
writeln!(
out,
"static_assert(sizeof({}) == sizeof(uint32_t), \"incorrect size\");",
enm.ident
);
let mut prev_discriminant = None;
for variant in &enm.variants {
let discriminant = variant
.discriminant
.unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
writeln!(
out,
"static_assert(static_cast<uint32_t>({}::{}) == {},
\"disagrees with the value in #[cxx::bridge]\");",
enm.ident, variant.ident, discriminant,
);
prev_discriminant = Some(discriminant);
}
}
fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
let mut has_cxx_throws = false;
for api in apis {

View File

@ -44,7 +44,11 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
Api::Include(_) | Api::RustType(_) => {}
Api::Struct(strct) => expanded.extend(expand_struct(strct)),
Api::Enum(enm) => expanded.extend(expand_enum(enm)),
Api::CxxType(ety) => expanded.extend(expand_cxx_type(ety)),
Api::CxxType(ety) => {
if !types.enums.contains_key(&ety.ident) {
expanded.extend(expand_cxx_type(ety));
}
}
Api::CxxFunction(efn) => {
expanded.extend(expand_cxx_function_shim(namespace, efn, types));
}

View File

@ -61,15 +61,18 @@ impl<'a> Types<'a> {
}
Api::Enum(enm) => {
let ident = &enm.ident;
if type_names.insert(ident) {
enums.insert(ident.clone(), enm);
} else {
// We allow declaring the same type as a shared enum and as a Cxxtype, as this
// means not to emit the C++ enum definition.
if !type_names.insert(ident) && !cxx.contains(ident) {
duplicate_name(cx, enm, ident);
}
enums.insert(ident.clone(), enm);
}
Api::CxxType(ety) => {
let ident = &ety.ident;
if !type_names.insert(ident) {
// We allow declaring the same type as a shared enum and as a Cxxtype, as this
// means not to emit the C++ enum definition.
if !type_names.insert(ident) && !enums.contains_key(ident) {
duplicate_name(cx, ety, ident);
}
cxx.insert(ident);

View File

@ -84,6 +84,15 @@ pub mod ffi {
fn set2(&mut self, n: usize) -> usize;
}
extern "C" {
type COwnedEnum;
}
enum COwnedEnum {
CVal1,
CVal2,
}
extern "Rust" {
type R;
type R2;

View File

@ -23,6 +23,11 @@ private:
std::vector<uint8_t> v;
};
enum COwnedEnum {
CVal1,
CVal2,
};
size_t c_return_primitive();
Shared c_return_shared();
rust::Box<R> c_return_box();