add initial array support
diff --git a/syntax/check.rs b/syntax/check.rs
index 53dd843..06e99fe 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -2,7 +2,7 @@
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 @@
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 @@
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 @@
Type::SliceRefU8(_) => "&[u8]".to_owned(),
Type::Fn(_) => "function pointer".to_owned(),
Type::Void(_) => "()".to_owned(),
+ Type::Array(_) => "array".to_owned(),
}
}
diff --git a/syntax/impls.rs b/syntax/impls.rs
index a9c48c3..6fae2f9 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -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 @@
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 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 {
diff --git a/syntax/improper.rs b/syntax/improper.rs
index 6fd3162..e016884 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -31,6 +31,7 @@
| 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),
}
}
}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 2a3790c..4d65874 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -165,6 +165,7 @@
Void(Span),
Slice(Box<Slice>),
SliceRefU8(Box<Ref>),
+ Array(Box<Array>),
}
pub struct Ty1 {
@@ -189,6 +190,13 @@
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,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index ec89cbb..0099299 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,7 +3,7 @@
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 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 @@
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 {
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 40ab723..27c2693 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -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 @@
}
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 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| {
diff --git a/syntax/types.rs b/syntax/types.rs
index 92c9a75..84b03be 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -49,6 +49,7 @@
| 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);