mirror of
https://gitee.com/openharmony/third_party_rust_cxx
synced 2024-11-24 07:40:19 +00:00
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.
This commit is contained in:
parent
24d22b471a
commit
905eb2e1f5
@ -5,7 +5,7 @@ use crate::syntax::namespace::Namespace;
|
||||
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 @@ pub(super) fn gen(
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ pub(super) fn gen(
|
||||
.push(efn);
|
||||
}
|
||||
}
|
||||
if let Api::CxxType(enm) = api {
|
||||
cxx_types.insert(&enm.ident);
|
||||
}
|
||||
}
|
||||
|
||||
for api in apis {
|
||||
@ -66,7 +70,11 @@ pub(super) fn gen(
|
||||
}
|
||||
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 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
|
||||
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 {
|
||||
|
@ -7,6 +7,7 @@ use crate::syntax::{
|
||||
};
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::{format_ident, quote, quote_spanned, ToTokens};
|
||||
use std::collections::HashSet;
|
||||
use syn::{parse_quote, Error, ItemMod, Result, Token};
|
||||
|
||||
pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
|
||||
@ -39,12 +40,22 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
|
||||
}
|
||||
}
|
||||
|
||||
let mut enums = HashSet::new();
|
||||
for api in apis {
|
||||
if let Api::Enum(enm) = api {
|
||||
enums.insert(&enm.ident);
|
||||
}
|
||||
}
|
||||
for api in apis {
|
||||
match api {
|
||||
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 !enums.contains(&ety.ident) {
|
||||
expanded.extend(expand_cxx_type(ety));
|
||||
}
|
||||
}
|
||||
Api::CxxFunction(efn) => {
|
||||
expanded.extend(expand_cxx_function_shim(namespace, efn, types));
|
||||
}
|
||||
|
@ -69,7 +69,9 @@ impl<'a> Types<'a> {
|
||||
}
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user