mirror of
https://gitee.com/openharmony/third_party_rust_cxx
synced 2024-11-23 23:29:50 +00:00
add initial array support
This commit is contained in:
parent
bf1000f40e
commit
7876235c3f
@ -172,6 +172,9 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
|
||||
out.include.cstdint = true;
|
||||
out.builtin.rust_slice = true;
|
||||
}
|
||||
Type::Array(_) => {
|
||||
out.include.array = true;
|
||||
}
|
||||
Type::Ref(_) | Type::Void(_) => {}
|
||||
}
|
||||
}
|
||||
@ -902,6 +905,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
|
||||
}
|
||||
write!(out, ")>");
|
||||
}
|
||||
Type::Array(a) => {
|
||||
write!(out, "::std::array<");
|
||||
write_type(out, &a.inner);
|
||||
write!(out, ", {}>", &a.len);
|
||||
}
|
||||
Type::Void(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
@ -940,7 +948,8 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
|
||||
| Type::CxxVector(_)
|
||||
| Type::RustVec(_)
|
||||
| Type::SliceRefU8(_)
|
||||
| Type::Fn(_) => write!(out, " "),
|
||||
| Type::Fn(_)
|
||||
| Type::Array(_) => write!(out, " "),
|
||||
Type::Ref(_) => {}
|
||||
Type::Void(_) | Type::Slice(_) => unreachable!(),
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use crate::syntax::atom::Atom::{self, *};
|
||||
use crate::syntax::report::Errors;
|
||||
use crate::syntax::types::TrivialReason;
|
||||
use crate::syntax::{
|
||||
error, ident, Api, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature, Slice,
|
||||
error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature, Slice,
|
||||
Struct, Ty1, Type, Types,
|
||||
};
|
||||
use proc_macro2::{Delimiter, Group, Ident, TokenStream};
|
||||
@ -35,6 +35,7 @@ fn do_typecheck(cx: &mut Check) {
|
||||
Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
|
||||
Type::Ref(ty) => check_type_ref(cx, ty),
|
||||
Type::Slice(ty) => check_type_slice(cx, ty),
|
||||
Type::Array(array) => check_type_array(cx, array),
|
||||
Type::Fn(ty) => check_type_fn(cx, ty),
|
||||
Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
|
||||
}
|
||||
@ -181,6 +182,21 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
|
||||
cx.error(ty, "only &[u8] is supported so far, not other slice types");
|
||||
}
|
||||
|
||||
fn check_type_array(cx: &mut Check, ty: &Array) {
|
||||
match &ty.inner {
|
||||
Type::Ident(ident) => {
|
||||
if cx.types.rust.contains(&ident.rust) || cx.types.cxx.contains(&ident.rust) {
|
||||
cx.error(ty, "Only shared structs are supported in array yet");
|
||||
}
|
||||
}
|
||||
Type::RustBox(ty1) => check_type_box(cx, ty1),
|
||||
Type::RustVec(ty1) => check_type_rust_vec(cx, ty1),
|
||||
Type::CxxVector(ty1) => check_type_cxx_vector(cx, ty1),
|
||||
Type::UniquePtr(ty1) => check_type_unique_ptr(cx, ty1),
|
||||
_ => cx.error(ty, "unsupported array target type"),
|
||||
};
|
||||
}
|
||||
|
||||
fn check_type_fn(cx: &mut Check, ty: &Signature) {
|
||||
if ty.throws {
|
||||
cx.error(ty, "function pointer returning Result is not supported yet");
|
||||
@ -480,5 +496,6 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
|
||||
Type::SliceRefU8(_) => "&[u8]".to_owned(),
|
||||
Type::Fn(_) => "function pointer".to_owned(),
|
||||
Type::Void(_) => "()".to_owned(),
|
||||
Type::Array(_) => "array".to_owned(),
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::syntax::{ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
|
||||
use crate::syntax::{Array, ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
|
||||
use std::borrow::Borrow;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
@ -50,6 +50,7 @@ impl Hash for Type {
|
||||
Type::Fn(t) => t.hash(state),
|
||||
Type::Slice(t) => t.hash(state),
|
||||
Type::SliceRefU8(t) => t.hash(state),
|
||||
Type::Array(t) => t.hash(state),
|
||||
Type::Void(_) => {}
|
||||
}
|
||||
}
|
||||
@ -173,6 +174,37 @@ impl Hash for Slice {
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Array {}
|
||||
impl PartialEq for Array {
|
||||
fn eq(&self, other: &Array) -> bool {
|
||||
let Array {
|
||||
bracket: _,
|
||||
inner,
|
||||
semi_token: _,
|
||||
len,
|
||||
} = self;
|
||||
let Array {
|
||||
bracket: _,
|
||||
inner: inner2,
|
||||
semi_token: _,
|
||||
len: len2,
|
||||
} = other;
|
||||
inner == inner2 && len == len2
|
||||
}
|
||||
}
|
||||
impl Hash for Array {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let Array {
|
||||
bracket: _,
|
||||
inner,
|
||||
semi_token: _,
|
||||
len,
|
||||
} = self;
|
||||
inner.hash(state);
|
||||
len.to_string().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Signature {}
|
||||
|
||||
impl PartialEq for Signature {
|
||||
|
@ -31,6 +31,7 @@ impl<'a> Types<'a> {
|
||||
| Type::SliceRefU8(_) => Definite(true),
|
||||
Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
|
||||
Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
|
||||
Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,6 +165,7 @@ pub enum Type {
|
||||
Void(Span),
|
||||
Slice(Box<Slice>),
|
||||
SliceRefU8(Box<Ref>),
|
||||
Array(Box<Array>),
|
||||
}
|
||||
|
||||
pub struct Ty1 {
|
||||
@ -189,6 +190,13 @@ pub struct Slice {
|
||||
pub inner: Type,
|
||||
}
|
||||
|
||||
pub struct Array {
|
||||
pub bracket: Bracket,
|
||||
pub inner: Type,
|
||||
pub semi_token: Token![;],
|
||||
pub len: usize,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum Lang {
|
||||
Cxx,
|
||||
|
@ -3,7 +3,7 @@ use crate::syntax::file::{Item, ItemForeignMod};
|
||||
use crate::syntax::report::Errors;
|
||||
use crate::syntax::Atom::*;
|
||||
use crate::syntax::{
|
||||
attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
|
||||
attrs, error, Api, Array, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
|
||||
Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
|
||||
Var, Variant,
|
||||
};
|
||||
@ -12,10 +12,10 @@ use quote::{format_ident, quote, quote_spanned};
|
||||
use syn::parse::{ParseStream, Parser};
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::{
|
||||
Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
|
||||
GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, LitStr, Pat,
|
||||
PathArguments, Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath,
|
||||
TypeReference, TypeSlice,
|
||||
Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
|
||||
GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
|
||||
Pat, PathArguments, Result, ReturnType, Token, Type as RustType, TypeArray, TypeBareFn,
|
||||
TypePath, TypeReference, TypeSlice,
|
||||
};
|
||||
|
||||
pub mod kw {
|
||||
@ -623,10 +623,49 @@ fn parse_type(ty: &RustType, namespace: &Namespace) -> Result<Type> {
|
||||
RustType::Slice(ty) => parse_type_slice(ty, namespace),
|
||||
RustType::BareFn(ty) => parse_type_fn(ty, namespace),
|
||||
RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
|
||||
RustType::Array(ty) => parse_type_array(ty, namespace),
|
||||
_ => Err(Error::new_spanned(ty, "unsupported type")),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
|
||||
let inner = parse_type(&ty.elem, namespace)?;
|
||||
match &ty.len {
|
||||
Expr::Lit(lit) => {
|
||||
if !lit.attrs.is_empty() {
|
||||
return Err(Error::new_spanned(
|
||||
ty,
|
||||
"attribute not allowed in length field",
|
||||
));
|
||||
}
|
||||
match &lit.lit {
|
||||
Lit::Int(v) => {
|
||||
let v = match v.base10_parse::<usize>() {
|
||||
Ok(n_v) => n_v,
|
||||
Err(_) => {
|
||||
return Err(Error::new_spanned(
|
||||
ty,
|
||||
"Cannot parse integer literal to base10",
|
||||
))
|
||||
}
|
||||
};
|
||||
Ok(Type::Array(Box::new(Array {
|
||||
bracket: ty.bracket_token,
|
||||
inner,
|
||||
semi_token: ty.semi_token,
|
||||
len: v,
|
||||
})))
|
||||
}
|
||||
_ => Err(Error::new_spanned(ty, "length literal must be a integer")),
|
||||
}
|
||||
}
|
||||
_ => Err(Error::new_spanned(
|
||||
ty,
|
||||
"only literal is currently supported in len field",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Type> {
|
||||
let inner = parse_type(&ty.elem, namespace)?;
|
||||
let which = match &inner {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::syntax::atom::Atom::*;
|
||||
use crate::syntax::{
|
||||
Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName, Signature,
|
||||
Slice, Struct, Ty1, Type, TypeAlias, Var,
|
||||
Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName,
|
||||
Signature, Slice, Struct, Ty1, Type, TypeAlias, Var,
|
||||
};
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use quote::{quote_spanned, ToTokens};
|
||||
@ -22,6 +22,7 @@ impl ToTokens for Type {
|
||||
}
|
||||
Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
|
||||
Type::Slice(s) => s.to_tokens(tokens),
|
||||
Type::Array(a) => a.to_tokens(tokens),
|
||||
Type::Fn(f) => f.to_tokens(tokens),
|
||||
Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
|
||||
}
|
||||
@ -68,6 +69,16 @@ impl ToTokens for Ref {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Array {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.bracket.surround(tokens, |tokens| {
|
||||
self.inner.to_tokens(tokens);
|
||||
self.semi_token.to_tokens(tokens);
|
||||
self.len.to_tokens(tokens);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Slice {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
self.bracket.surround(tokens, |tokens| {
|
||||
|
@ -49,6 +49,7 @@ impl<'a> Types<'a> {
|
||||
| Type::RustVec(ty) => visit(all, &ty.inner),
|
||||
Type::Ref(r) => visit(all, &r.inner),
|
||||
Type::Slice(s) => visit(all, &s.inner),
|
||||
Type::Array(a) => visit(all, &a.inner),
|
||||
Type::Fn(f) => {
|
||||
if let Some(ret) = &f.ret {
|
||||
visit(all, ret);
|
||||
|
@ -116,6 +116,10 @@ pub mod ffi {
|
||||
i: i32,
|
||||
}
|
||||
|
||||
pub struct Array {
|
||||
a: [i32; 4],
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("tests/ffi/tests.h");
|
||||
|
||||
@ -204,6 +208,7 @@ pub mod ffi {
|
||||
fn set_succeed(self: Pin<&mut C>, n: usize) -> Result<usize>;
|
||||
fn get_fail(self: Pin<&mut C>) -> Result<usize>;
|
||||
fn c_method_on_shared(self: &Shared) -> usize;
|
||||
fn c_set_array(self: &mut Array, value: i32);
|
||||
|
||||
#[rust_name = "i32_overloaded_method"]
|
||||
fn cOverloadedMethod(&self, x: i32) -> String;
|
||||
@ -274,6 +279,7 @@ pub mod ffi {
|
||||
fn get(self: &R) -> usize;
|
||||
fn set(self: &mut R, n: usize) -> usize;
|
||||
fn r_method_on_shared(self: &Shared) -> String;
|
||||
fn r_get_array_sum(self: &Array) -> i32;
|
||||
|
||||
#[cxx_name = "rAliasedFunction"]
|
||||
fn r_aliased_function(x: i32) -> String;
|
||||
@ -321,6 +327,12 @@ impl ffi::Shared {
|
||||
}
|
||||
}
|
||||
|
||||
impl ffi::Array {
|
||||
pub fn r_get_array_sum(&self) -> i32 {
|
||||
self.a.iter().sum()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Error;
|
||||
|
||||
|
@ -32,6 +32,10 @@ size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
|
||||
|
||||
size_t Shared::c_method_on_shared() const noexcept { return 2021; }
|
||||
|
||||
void Array::c_set_array(int32_t val) noexcept {
|
||||
this->a = {val, val, val, val};
|
||||
}
|
||||
|
||||
const std::vector<uint8_t> &C::get_v() const { return this->v; }
|
||||
|
||||
std::vector<uint8_t> &C::get_v() { return this->v; }
|
||||
|
@ -197,6 +197,11 @@ fn test_c_method_calls() {
|
||||
);
|
||||
assert!(unique_ptr.as_mut().unwrap().get_fail().is_err());
|
||||
assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
|
||||
|
||||
let val = 42;
|
||||
let mut array = ffi::Array { a: [0, 0, 0, 0] };
|
||||
array.c_set_array(val);
|
||||
assert_eq!(array.a.len() as i32 * val, array.r_get_array_sum());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user