mirror of
https://gitee.com/openharmony/third_party_rust_cxx
synced 2024-11-28 09:50:57 +00:00
commit
02d58bb593
@ -3,7 +3,7 @@ use crate::gen::{include, Opt};
|
||||
use crate::syntax::atom::Atom::{self, *};
|
||||
use crate::syntax::namespace::Namespace;
|
||||
use crate::syntax::symbol::Symbol;
|
||||
use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
|
||||
use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
|
||||
use proc_macro2::Ident;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@ -64,6 +64,10 @@ pub(super) fn gen(
|
||||
out.next_section();
|
||||
write_struct(out, strct);
|
||||
}
|
||||
Api::Enum(enm) => {
|
||||
out.next_section();
|
||||
write_enum(out, enm);
|
||||
}
|
||||
Api::RustType(ety) => {
|
||||
if let Some(methods) = methods_for_type.get(&ety.ident) {
|
||||
out.next_section();
|
||||
@ -353,6 +357,22 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
|
||||
writeln!(out, "}};");
|
||||
}
|
||||
|
||||
fn write_enum(out: &mut OutFile, enm: &Enum) {
|
||||
for line in enm.doc.to_string().lines() {
|
||||
writeln!(out, "//{}", line);
|
||||
}
|
||||
writeln!(out, "enum class {} : uint32_t {{", enm.ident);
|
||||
for variant in &enm.variants {
|
||||
write!(out, " ");
|
||||
write!(out, "{}", variant.ident);
|
||||
if let Some(discriminant) = &variant.discriminant {
|
||||
write!(out, " = {}", discriminant);
|
||||
}
|
||||
writeln!(out, ",");
|
||||
}
|
||||
writeln!(out, "}};");
|
||||
}
|
||||
|
||||
fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
|
||||
let mut has_cxx_throws = false;
|
||||
for api in apis {
|
||||
|
@ -2,7 +2,7 @@ use crate::syntax::atom::Atom::{self, *};
|
||||
use crate::syntax::namespace::Namespace;
|
||||
use crate::syntax::symbol::Symbol;
|
||||
use crate::syntax::{
|
||||
self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
|
||||
self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types,
|
||||
};
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::{format_ident, quote, quote_spanned, ToTokens};
|
||||
@ -36,6 +36,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
|
||||
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::CxxFunction(efn) => {
|
||||
expanded.extend(expand_cxx_function_shim(namespace, efn, types));
|
||||
@ -123,6 +124,34 @@ fn expand_struct(strct: &Struct) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_enum(enm: &Enum) -> TokenStream {
|
||||
let ident = &enm.ident;
|
||||
let doc = &enm.doc;
|
||||
let variants = enm.variants.iter().scan(0, |next_discriminant, variant| {
|
||||
// This span on the pub makes "private type in public interface" errors
|
||||
// appear in the right place.
|
||||
let vis = Token![pub](variant.ident.span());
|
||||
let variant_ident = &variant.ident;
|
||||
let discriminant = match variant.discriminant {
|
||||
None => *next_discriminant,
|
||||
Some(val) => val,
|
||||
};
|
||||
*next_discriminant = discriminant + 1;
|
||||
Some(quote!( #vis const #variant_ident: Self = #ident(#discriminant)))
|
||||
});
|
||||
quote! {
|
||||
#doc
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[repr(transparent)]
|
||||
pub struct #ident(u32);
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
impl #ident {
|
||||
#(#variants;)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_cxx_type(ety: &ExternType) -> TokenStream {
|
||||
let ident = &ety.ident;
|
||||
let doc = &ety.doc;
|
||||
|
@ -1,9 +1,11 @@
|
||||
use crate::syntax::atom::Atom::{self, *};
|
||||
use crate::syntax::{
|
||||
error, ident, Api, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type, Types,
|
||||
error, ident, Api, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type,
|
||||
Types,
|
||||
};
|
||||
use proc_macro2::{Delimiter, Group, Ident, TokenStream};
|
||||
use quote::{quote, ToTokens};
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Display;
|
||||
use syn::{Error, Result};
|
||||
|
||||
@ -41,6 +43,7 @@ fn do_typecheck(cx: &mut Check) {
|
||||
for api in cx.apis {
|
||||
match api {
|
||||
Api::Struct(strct) => check_api_struct(cx, strct),
|
||||
Api::Enum(enm) => check_api_enum(cx, enm),
|
||||
Api::CxxType(ty) | Api::RustType(ty) => check_api_type(cx, ty),
|
||||
Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
|
||||
_ => {}
|
||||
@ -68,6 +71,7 @@ impl Check<'_> {
|
||||
fn check_type_ident(cx: &mut Check, ident: &Ident) {
|
||||
if Atom::from(ident).is_none()
|
||||
&& !cx.types.structs.contains_key(ident)
|
||||
&& !cx.types.enums.contains_key(ident)
|
||||
&& !cx.types.cxx.contains(ident)
|
||||
&& !cx.types.rust.contains(ident)
|
||||
{
|
||||
@ -188,6 +192,28 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_api_enum(cx: &mut Check, enm: &Enum) {
|
||||
check_reserved_name(cx, &enm.ident);
|
||||
|
||||
if enm.variants.is_empty() {
|
||||
let span = span_for_enum_error(enm);
|
||||
cx.error(span, "enums without any variants are not supported");
|
||||
}
|
||||
|
||||
let mut discriminants = HashSet::new();
|
||||
enm.variants.iter().fold(0, |next_discriminant, variant| {
|
||||
let discriminant = match variant.discriminant {
|
||||
None => next_discriminant,
|
||||
Some(val) => val,
|
||||
};
|
||||
if !discriminants.insert(discriminant) {
|
||||
let msg = format!("discriminant value `{}` already exists", discriminant);
|
||||
cx.error(span_for_enum_error(enm), msg);
|
||||
}
|
||||
discriminant + 1
|
||||
});
|
||||
}
|
||||
|
||||
fn check_api_type(cx: &mut Check, ty: &ExternType) {
|
||||
check_reserved_name(cx, &ty.ident);
|
||||
}
|
||||
@ -320,6 +346,13 @@ fn span_for_struct_error(strct: &Struct) -> TokenStream {
|
||||
quote!(#struct_token #brace_token)
|
||||
}
|
||||
|
||||
fn span_for_enum_error(enm: &Enum) -> TokenStream {
|
||||
let enum_token = enm.enum_token;
|
||||
let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());
|
||||
brace_token.set_span(enm.brace_token.span);
|
||||
quote!(#enum_token #brace_token)
|
||||
}
|
||||
|
||||
fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
|
||||
let ampersand = receiver.ampersand;
|
||||
let lifetime = &receiver.lifetime;
|
||||
|
@ -23,6 +23,12 @@ pub(crate) fn check_all(apis: &[Api], errors: &mut Vec<Error>) {
|
||||
errors.extend(check(&field.ident).err());
|
||||
}
|
||||
}
|
||||
Api::Enum(enm) => {
|
||||
errors.extend(check(&enm.ident).err());
|
||||
for variant in &enm.variants {
|
||||
errors.extend(check(&variant.ident).err());
|
||||
}
|
||||
}
|
||||
Api::CxxType(ety) | Api::RustType(ety) => {
|
||||
errors.extend(check(&ety.ident).err());
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ pub use self::types::Types;
|
||||
pub enum Api {
|
||||
Include(LitStr),
|
||||
Struct(Struct),
|
||||
Enum(Enum),
|
||||
CxxType(ExternType),
|
||||
CxxFunction(ExternFn),
|
||||
RustType(ExternType),
|
||||
@ -50,6 +51,14 @@ pub struct Struct {
|
||||
pub fields: Vec<Var>,
|
||||
}
|
||||
|
||||
pub struct Enum {
|
||||
pub doc: Doc,
|
||||
pub enum_token: Token![enum],
|
||||
pub ident: Ident,
|
||||
pub brace_token: Brace,
|
||||
pub variants: Vec<Variant>,
|
||||
}
|
||||
|
||||
pub struct ExternFn {
|
||||
pub lang: Lang,
|
||||
pub doc: Doc,
|
||||
@ -83,6 +92,11 @@ pub struct Receiver {
|
||||
pub shorthand: bool,
|
||||
}
|
||||
|
||||
pub struct Variant {
|
||||
pub ident: Ident,
|
||||
pub discriminant: Option<u32>,
|
||||
}
|
||||
|
||||
pub enum Type {
|
||||
Ident(Ident),
|
||||
RustBox(Box<Ty1>),
|
||||
|
@ -1,14 +1,15 @@
|
||||
use crate::syntax::Atom::*;
|
||||
use crate::syntax::{
|
||||
attrs, error, Api, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice, Struct,
|
||||
Ty1, Type, Var,
|
||||
attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
|
||||
Struct, Ty1, Type, Var, Variant,
|
||||
};
|
||||
use quote::{format_ident, quote};
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::{
|
||||
Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Ident,
|
||||
Item, ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token,
|
||||
Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
|
||||
Abi, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
|
||||
GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Lit, Pat, PathArguments,
|
||||
Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
|
||||
Variant as RustVariant,
|
||||
};
|
||||
|
||||
pub mod kw {
|
||||
@ -23,6 +24,10 @@ pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
|
||||
let strct = parse_struct(item)?;
|
||||
apis.push(strct);
|
||||
}
|
||||
Item::Enum(item) => {
|
||||
let enm = parse_enum(item)?;
|
||||
apis.push(enm);
|
||||
}
|
||||
Item::ForeignMod(foreign_mod) => {
|
||||
let functions = parse_foreign_mod(foreign_mod)?;
|
||||
apis.extend(functions);
|
||||
@ -78,6 +83,75 @@ fn parse_struct(item: ItemStruct) -> Result<Api> {
|
||||
}))
|
||||
}
|
||||
|
||||
fn parse_enum(item: ItemEnum) -> Result<Api> {
|
||||
let generics = &item.generics;
|
||||
if !generics.params.is_empty() || generics.where_clause.is_some() {
|
||||
let enum_token = item.enum_token;
|
||||
let ident = &item.ident;
|
||||
let where_clause = &generics.where_clause;
|
||||
let span = quote!(#enum_token #ident #generics #where_clause);
|
||||
return Err(Error::new_spanned(
|
||||
span,
|
||||
"enums with generic parameters are not allowed",
|
||||
));
|
||||
}
|
||||
|
||||
let mut doc = Doc::new();
|
||||
attrs::parse(&item.attrs, &mut doc, None)?;
|
||||
|
||||
for variant in &item.variants {
|
||||
match &variant.fields {
|
||||
Fields::Unit => {}
|
||||
_ => {
|
||||
return Err(Error::new_spanned(
|
||||
variant,
|
||||
"enums with data are not allowed",
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Api::Enum(Enum {
|
||||
doc,
|
||||
enum_token: item.enum_token,
|
||||
ident: item.ident,
|
||||
brace_token: item.brace_token,
|
||||
variants: item
|
||||
.variants
|
||||
.into_iter()
|
||||
.map(parse_variant)
|
||||
.collect::<Result<_>>()?,
|
||||
}))
|
||||
}
|
||||
|
||||
fn parse_variant(variant: RustVariant) -> Result<Variant> {
|
||||
match &variant.discriminant {
|
||||
None => Ok(Variant {
|
||||
ident: variant.ident,
|
||||
discriminant: None,
|
||||
}),
|
||||
Some((
|
||||
_,
|
||||
Expr::Lit(ExprLit {
|
||||
lit: Lit::Int(n), ..
|
||||
}),
|
||||
)) => match n.base10_digits().parse() {
|
||||
Ok(val) => Ok(Variant {
|
||||
ident: variant.ident,
|
||||
discriminant: Some(val),
|
||||
}),
|
||||
Err(_) => Err(Error::new_spanned(
|
||||
variant,
|
||||
"cannot parse enum discriminant as an integer",
|
||||
)),
|
||||
},
|
||||
_ => Err(Error::new_spanned(
|
||||
variant,
|
||||
"enums with non-integer literal discriminants are not supported",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
|
||||
let lang = parse_lang(foreign_mod.abi)?;
|
||||
let api_type = match lang {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::syntax::atom::Atom::{self, *};
|
||||
use crate::syntax::set::OrderedSet as Set;
|
||||
use crate::syntax::{Api, Derive, ExternType, Struct, Type};
|
||||
use crate::syntax::{Api, Derive, Enum, ExternType, Struct, Type};
|
||||
use proc_macro2::Ident;
|
||||
use quote::quote;
|
||||
use std::collections::BTreeMap as Map;
|
||||
@ -9,6 +9,7 @@ use syn::{Error, Result};
|
||||
pub struct Types<'a> {
|
||||
pub all: Set<'a, Type>,
|
||||
pub structs: Map<Ident, &'a Struct>,
|
||||
pub enums: Map<Ident, &'a Enum>,
|
||||
pub cxx: Set<'a, Ident>,
|
||||
pub rust: Set<'a, Ident>,
|
||||
}
|
||||
@ -17,6 +18,7 @@ impl<'a> Types<'a> {
|
||||
pub fn collect(apis: &'a [Api]) -> Result<Self> {
|
||||
let mut all = Set::new();
|
||||
let mut structs = Map::new();
|
||||
let mut enums = Map::new();
|
||||
let mut cxx = Set::new();
|
||||
let mut rust = Set::new();
|
||||
|
||||
@ -46,7 +48,11 @@ impl<'a> Types<'a> {
|
||||
Api::Include(_) => {}
|
||||
Api::Struct(strct) => {
|
||||
let ident = &strct.ident;
|
||||
if structs.contains_key(ident) || cxx.contains(ident) || rust.contains(ident) {
|
||||
if structs.contains_key(ident)
|
||||
|| enums.contains_key(ident)
|
||||
|| cxx.contains(ident)
|
||||
|| rust.contains(ident)
|
||||
{
|
||||
return Err(duplicate_struct(strct));
|
||||
}
|
||||
structs.insert(strct.ident.clone(), strct);
|
||||
@ -54,16 +60,35 @@ impl<'a> Types<'a> {
|
||||
visit(&mut all, &field.ty);
|
||||
}
|
||||
}
|
||||
Api::Enum(enm) => {
|
||||
let ident = &enm.ident;
|
||||
if structs.contains_key(ident)
|
||||
|| enums.contains_key(ident)
|
||||
|| cxx.contains(ident)
|
||||
|| rust.contains(ident)
|
||||
{
|
||||
return Err(duplicate_enum(enm));
|
||||
}
|
||||
enums.insert(enm.ident.clone(), enm);
|
||||
}
|
||||
Api::CxxType(ety) => {
|
||||
let ident = &ety.ident;
|
||||
if structs.contains_key(ident) || cxx.contains(ident) || rust.contains(ident) {
|
||||
if structs.contains_key(ident)
|
||||
|| enums.contains_key(ident)
|
||||
|| cxx.contains(ident)
|
||||
|| rust.contains(ident)
|
||||
{
|
||||
return Err(duplicate_type(ety));
|
||||
}
|
||||
cxx.insert(ident);
|
||||
}
|
||||
Api::RustType(ety) => {
|
||||
let ident = &ety.ident;
|
||||
if structs.contains_key(ident) || cxx.contains(ident) || rust.contains(ident) {
|
||||
if structs.contains_key(ident)
|
||||
|| enums.contains_key(ident)
|
||||
|| cxx.contains(ident)
|
||||
|| rust.contains(ident)
|
||||
{
|
||||
return Err(duplicate_type(ety));
|
||||
}
|
||||
rust.insert(ident);
|
||||
@ -82,6 +107,7 @@ impl<'a> Types<'a> {
|
||||
Ok(Types {
|
||||
all,
|
||||
structs,
|
||||
enums,
|
||||
cxx,
|
||||
rust,
|
||||
})
|
||||
@ -126,6 +152,13 @@ fn duplicate_struct(strct: &Struct) -> Error {
|
||||
Error::new_spanned(range, "duplicate type")
|
||||
}
|
||||
|
||||
fn duplicate_enum(enm: &Enum) -> Error {
|
||||
let enum_token = enm.enum_token;
|
||||
let ident = &enm.ident;
|
||||
let range = quote!(#enum_token #ident);
|
||||
Error::new_spanned(range, "duplicate type")
|
||||
}
|
||||
|
||||
fn duplicate_type(ety: &ExternType) -> Error {
|
||||
let type_token = ety.type_token;
|
||||
let ident = &ety.ident;
|
||||
|
@ -13,6 +13,12 @@ pub mod ffi {
|
||||
z: usize,
|
||||
}
|
||||
|
||||
enum Enum {
|
||||
AVal,
|
||||
BVal = 2020,
|
||||
CVal,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
include!("tests/ffi/tests.h");
|
||||
|
||||
@ -36,6 +42,7 @@ pub mod ffi {
|
||||
fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
|
||||
fn c_return_identity(_: usize) -> usize;
|
||||
fn c_return_sum(_: usize, _: usize) -> usize;
|
||||
fn c_return_enum(n: u32) -> Enum;
|
||||
|
||||
fn c_take_primitive(n: usize);
|
||||
fn c_take_shared(shared: Shared);
|
||||
@ -57,6 +64,7 @@ pub mod ffi {
|
||||
fn c_take_ref_rust_vec(v: &Vec<u8>);
|
||||
fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
|
||||
fn c_take_callback(callback: fn(String) -> usize);
|
||||
fn c_take_enum(e: Enum);
|
||||
|
||||
fn c_try_return_void() -> Result<()>;
|
||||
fn c_try_return_primitive() -> Result<usize>;
|
||||
@ -92,6 +100,7 @@ pub mod ffi {
|
||||
fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
|
||||
fn r_return_identity(_: usize) -> usize;
|
||||
fn r_return_sum(_: usize, _: usize) -> usize;
|
||||
fn r_return_enum(n: u32) -> Enum;
|
||||
|
||||
fn r_take_primitive(n: usize);
|
||||
fn r_take_shared(shared: Shared);
|
||||
@ -105,6 +114,7 @@ pub mod ffi {
|
||||
fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
|
||||
fn r_take_rust_vec(v: Vec<u8>);
|
||||
fn r_take_ref_rust_vec(v: &Vec<u8>);
|
||||
fn r_take_enum(e: Enum);
|
||||
|
||||
fn r_try_return_void() -> Result<()>;
|
||||
fn r_try_return_primitive() -> Result<usize>;
|
||||
@ -198,6 +208,16 @@ fn r_return_sum(n1: usize, n2: usize) -> usize {
|
||||
n1 + n2
|
||||
}
|
||||
|
||||
fn r_return_enum(n: u32) -> ffi::Enum {
|
||||
if n <= 0 {
|
||||
ffi::Enum::AVal
|
||||
} else if n <= 2020 {
|
||||
ffi::Enum::BVal
|
||||
} else {
|
||||
ffi::Enum::CVal
|
||||
}
|
||||
}
|
||||
|
||||
fn r_take_primitive(n: usize) {
|
||||
assert_eq!(n, 2020);
|
||||
}
|
||||
@ -247,6 +267,10 @@ fn r_take_ref_rust_vec(v: &Vec<u8>) {
|
||||
let _ = v;
|
||||
}
|
||||
|
||||
fn r_take_enum(e: ffi::Enum) {
|
||||
let _ = e;
|
||||
}
|
||||
|
||||
fn r_try_return_void() -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -106,6 +106,16 @@ size_t c_return_identity(size_t n) { return n; }
|
||||
|
||||
size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
|
||||
|
||||
Enum c_return_enum(uint32_t n) {
|
||||
if (n <= static_cast<uint32_t>(Enum::AVal)) {
|
||||
return Enum::AVal;
|
||||
} else if (n <= static_cast<uint32_t>(Enum::BVal)) {
|
||||
return Enum::BVal;
|
||||
} else {
|
||||
return Enum::CVal;
|
||||
}
|
||||
}
|
||||
|
||||
void c_take_primitive(size_t n) {
|
||||
if (n == 2020) {
|
||||
cxx_test_suite_set_correct();
|
||||
@ -238,6 +248,12 @@ void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
|
||||
callback("2020");
|
||||
}
|
||||
|
||||
void c_take_enum(Enum e) {
|
||||
if (e == Enum::AVal) {
|
||||
cxx_test_suite_set_correct();
|
||||
}
|
||||
}
|
||||
|
||||
void c_try_return_void() {}
|
||||
|
||||
size_t c_try_return_primitive() { return 2020; }
|
||||
@ -295,6 +311,9 @@ extern "C" const char *cxx_run_test() noexcept {
|
||||
ASSERT(*r_return_unique_ptr_string() == "2020");
|
||||
ASSERT(r_return_identity(2020) == 2020);
|
||||
ASSERT(r_return_sum(2020, 1) == 2021);
|
||||
ASSERT(r_return_enum(0) == Enum::AVal);
|
||||
ASSERT(r_return_enum(1) == Enum::BVal);
|
||||
ASSERT(r_return_enum(2021) == Enum::CVal);
|
||||
|
||||
r_take_primitive(2020);
|
||||
r_take_shared(Shared{2020});
|
||||
@ -306,6 +325,7 @@ extern "C" const char *cxx_run_test() noexcept {
|
||||
r_take_rust_string(rust::String("2020"));
|
||||
r_take_unique_ptr_string(
|
||||
std::unique_ptr<std::string>(new std::string("2020")));
|
||||
r_take_enum(Enum::AVal);
|
||||
|
||||
ASSERT(r_try_return_primitive() == 2020);
|
||||
try {
|
||||
|
@ -7,6 +7,7 @@ namespace tests {
|
||||
|
||||
struct R;
|
||||
struct Shared;
|
||||
enum class Enum : uint32_t;
|
||||
|
||||
class C {
|
||||
public:
|
||||
@ -40,6 +41,7 @@ rust::Vec<uint8_t> c_return_rust_vec();
|
||||
const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
|
||||
size_t c_return_identity(size_t n);
|
||||
size_t c_return_sum(size_t n1, size_t n2);
|
||||
Enum c_return_enum(uint32_t n);
|
||||
|
||||
void c_take_primitive(size_t n);
|
||||
void c_take_shared(Shared shared);
|
||||
@ -61,6 +63,7 @@ void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
|
||||
void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
|
||||
void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
|
||||
void c_take_callback(rust::Fn<size_t(rust::String)> callback);
|
||||
void c_take_enum(Enum e);
|
||||
|
||||
void c_try_return_void();
|
||||
size_t c_try_return_primitive();
|
||||
|
@ -51,6 +51,18 @@ fn test_c_return() {
|
||||
);
|
||||
assert_eq!(2020, ffi::c_return_identity(2020));
|
||||
assert_eq!(2021, ffi::c_return_sum(2020, 1));
|
||||
match ffi::c_return_enum(0) {
|
||||
ffi::Enum::AVal => {}
|
||||
_ => assert!(false),
|
||||
}
|
||||
match ffi::c_return_enum(1) {
|
||||
ffi::Enum::BVal => {}
|
||||
_ => assert!(false),
|
||||
}
|
||||
match ffi::c_return_enum(2021) {
|
||||
ffi::Enum::CVal => {}
|
||||
_ => assert!(false),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -106,6 +118,7 @@ fn test_c_take() {
|
||||
]));
|
||||
check!(ffi::c_take_ref_rust_vec(&test_vec));
|
||||
check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
|
||||
check!(ffi::c_take_enum(ffi::Enum::AVal));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
8
tests/ui/data_enums.rs
Normal file
8
tests/ui/data_enums.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
enum A {
|
||||
Field(u64),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
5
tests/ui/data_enums.stderr
Normal file
5
tests/ui/data_enums.stderr
Normal file
@ -0,0 +1,5 @@
|
||||
error: enums with data are not allowed
|
||||
--> $DIR/data_enums.rs:4:9
|
||||
|
|
||||
4 | Field(u64),
|
||||
| ^^^^^^^^^^
|
15
tests/ui/duplicate_enum_discriminants.rs
Normal file
15
tests/ui/duplicate_enum_discriminants.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
enum A {
|
||||
V1 = 10,
|
||||
V2 = 10,
|
||||
}
|
||||
|
||||
enum B {
|
||||
V1 = 10,
|
||||
V2,
|
||||
V3 = 11,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
18
tests/ui/duplicate_enum_discriminants.stderr
Normal file
18
tests/ui/duplicate_enum_discriminants.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
error: discriminant value `10` already exists
|
||||
--> $DIR/duplicate_enum_discriminants.rs:3:5
|
||||
|
|
||||
3 | / enum A {
|
||||
4 | | V1 = 10,
|
||||
5 | | V2 = 10,
|
||||
6 | | }
|
||||
| |_____^
|
||||
|
||||
error: discriminant value `11` already exists
|
||||
--> $DIR/duplicate_enum_discriminants.rs:8:5
|
||||
|
|
||||
8 | / enum B {
|
||||
9 | | V1 = 10,
|
||||
10 | | V2,
|
||||
11 | | V3 = 11,
|
||||
12 | | }
|
||||
| |_____^
|
8
tests/ui/empty_enum.rs
Normal file
8
tests/ui/empty_enum.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
enum A {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
7
tests/ui/empty_enum.stderr
Normal file
7
tests/ui/empty_enum.stderr
Normal file
@ -0,0 +1,7 @@
|
||||
error: enums without any variants are not supported
|
||||
--> $DIR/empty_enum.rs:3:5
|
||||
|
|
||||
3 | / enum A {
|
||||
4 | |
|
||||
5 | | }
|
||||
| |_____^
|
16
tests/ui/enum_match_without_wildcard.rs
Normal file
16
tests/ui/enum_match_without_wildcard.rs
Normal file
@ -0,0 +1,16 @@
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
enum A {
|
||||
FieldA,
|
||||
FieldB,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
fn matcher(a: ffi::A) -> u32 {
|
||||
match a {
|
||||
ffi::A::FieldA => 2020,
|
||||
ffi::A::FieldB => 2021,
|
||||
}
|
||||
}
|
11
tests/ui/enum_match_without_wildcard.stderr
Normal file
11
tests/ui/enum_match_without_wildcard.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0004]: non-exhaustive patterns: `A(2u32..=std::u32::MAX)` not covered
|
||||
--> $DIR/enum_match_without_wildcard.rs:12:11
|
||||
|
|
||||
1 | #[cxx::bridge]
|
||||
| -------------- `ffi::A` defined here
|
||||
...
|
||||
12 | match a {
|
||||
| ^ pattern `A(2u32..=std::u32::MAX)` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `ffi::A`
|
8
tests/ui/generic_enum.rs
Normal file
8
tests/ui/generic_enum.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
enum A<T> {
|
||||
Field,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
5
tests/ui/generic_enum.stderr
Normal file
5
tests/ui/generic_enum.stderr
Normal file
@ -0,0 +1,5 @@
|
||||
error: enums with generic parameters are not allowed
|
||||
--> $DIR/generic_enum.rs:3:5
|
||||
|
|
||||
3 | enum A<T> {
|
||||
| ^^^^^^^^^
|
8
tests/ui/non_integer_discriminant_enum.rs
Normal file
8
tests/ui/non_integer_discriminant_enum.rs
Normal file
@ -0,0 +1,8 @@
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
enum A {
|
||||
Field = 2020 + 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
5
tests/ui/non_integer_discriminant_enum.stderr
Normal file
5
tests/ui/non_integer_discriminant_enum.stderr
Normal file
@ -0,0 +1,5 @@
|
||||
error: enums with non-integer literal discriminants are not supported
|
||||
--> $DIR/non_integer_discriminant_enum.rs:4:9
|
||||
|
|
||||
4 | Field = 2020 + 1,
|
||||
| ^^^^^^^^^^^^^^^^
|
Loading…
Reference in New Issue
Block a user