Support enums defined in C++ code.
This allows listing an enum in an extern "C" block as well as in the
shared block. In this case, we do not emit the C++ declaration of the
enum but instead emit static assertions that it has the values that we
expect.
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8ce3813..2ea6ca8 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,7 +5,7 @@
use crate::syntax::symbol::Symbol;
use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
use proc_macro2::Ident;
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
pub(super) fn gen(
namespace: &Namespace,
@@ -46,6 +46,7 @@
}
}
+ let mut cxx_types = HashSet::new();
let mut methods_for_type = HashMap::new();
for api in apis {
if let Api::RustFunction(efn) = api {
@@ -56,6 +57,9 @@
.push(efn);
}
}
+ if let Api::CxxType(enm) = api {
+ cxx_types.insert(&enm.ident);
+ }
}
for api in apis {
@@ -66,7 +70,11 @@
}
Api::Enum(enm) => {
out.next_section();
- write_enum(out, enm);
+ if cxx_types.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 +381,34 @@
writeln!(out, "}};");
}
+fn check_enum(out: &mut OutFile, enm: &Enum) {
+ let discriminants = enm
+ .variants
+ .iter()
+ .scan(None, |prev_discriminant, variant| {
+ let discriminant = variant
+ .discriminant
+ .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+ *prev_discriminant = Some(discriminant);
+ Some(discriminant)
+ });
+ writeln!(
+ out,
+ "static_assert(sizeof({}) == sizeof(uint32_t));",
+ enm.ident
+ );
+ enm.variants
+ .iter()
+ .zip(discriminants)
+ .for_each(|(variant, discriminant)| {
+ writeln!(
+ out,
+ "static_assert({}::{} == {});",
+ enm.ident, variant.ident, discriminant
+ );
+ });
+}
+
fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
let mut has_cxx_throws = false;
for api in apis {