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);