Adding &[u8] support.
This change adds specifically, support for &[u8] with a corresponding
rust::Slice<uint8_t> type. No other types of slice are permitted. The
rationale is that it may be common to pass binary data back and forth
across the FFI boundary, so it's more urgent to get this in place sooner.
Broader support for other slices can wait for the future.
But, both C++ and Rust-side bindings should allow the existing support
to be broadened to other Slice types in future without code changes.
A few specific notes:
* The name "rust::Slice" might be better as "rust::SliceRef" but I'm
  following the precedent of "rust::Str".
* It would be good to add constructors from std::span but as that's
  a C++20 feature, that may have to wait until C++ feature detection
  is resolved.
* Internally, this follows the pattern of &str, where the parser will
  initially recognize this as Type::Ref (of Type::Slice) but then
  will replace that with Type::SliceRefU8. Type::Slice should not
  persist through later stages. As we later come to support other
  types of slice, we would probably want to remove Type::SliceRefU8.
diff --git a/syntax/check.rs b/syntax/check.rs
index 2826a85..c71295e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -245,6 +245,8 @@
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
+        Type::Slice(_) => "slice".to_owned(),
+        Type::SliceRefU8(_) => "&[u8]".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
     }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 34fb851..b040753 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{ExternFn, Receiver, Ref, Signature, Ty1, Type};
+use crate::syntax::{ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type};
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::Deref;
@@ -21,6 +21,8 @@
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::Fn(t) => t.hash(state),
+            Type::Slice(t) => t.hash(state),
+            Type::SliceRefU8(t) => t.hash(state),
             Type::Void(_) => {}
         }
     }
@@ -37,6 +39,8 @@
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
             (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
+            (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs,
+            (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
             (Type::Void(_), Type::Void(_)) => true,
             (_, _) => false,
         }
@@ -106,6 +110,32 @@
     }
 }
 
+impl Eq for Slice {}
+
+impl PartialEq for Slice {
+    fn eq(&self, other: &Slice) -> bool {
+        let Slice {
+            bracket: _,
+            inner,
+        } = self;
+        let Slice {
+            bracket: _,
+            inner: inner2,
+        } = other;
+        inner == inner2
+    }
+}
+
+impl Hash for Slice {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Slice {
+            bracket: _,
+            inner,
+        } = self;
+        inner.hash(state);
+    }
+}
+
 impl Eq for Signature {}
 
 impl PartialEq for Signature {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 0d0328b..4eaf81e 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -15,7 +15,7 @@
 use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
-use syn::token::{Brace, Paren};
+use syn::token::{Brace, Bracket, Paren};
 use syn::{LitStr, Token};
 
 pub use self::atom::Atom;
@@ -84,6 +84,8 @@
     Str(Box<Ref>),
     Fn(Box<Signature>),
     Void(Span),
+    Slice(Box<Slice>),
+    SliceRefU8(Box<Ref>),
 }
 
 pub struct Ty1 {
@@ -99,6 +101,11 @@
     pub inner: Type,
 }
 
+pub struct Slice {
+    pub bracket: Bracket,
+    pub inner: Type,
+}
+
 #[derive(Copy, Clone, PartialEq)]
 pub enum Lang {
     Cxx,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8e674bd..6156a69 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,6 +1,6 @@
 use crate::syntax::{
-    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Struct,
-    Ty1, Type, Var,
+    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
+    Struct, Ty1, Type, Var,
 };
 use proc_macro2::Ident;
 use quote::{format_ident, quote};
@@ -8,7 +8,7 @@
 use syn::{
     Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
     ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token, Type as RustType,
-    TypeBareFn, TypePath, TypeReference,
+    TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -222,10 +222,25 @@
         RustType::Path(ty) => parse_type_path(ty),
         RustType::BareFn(ty) => parse_type_fn(ty),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
+        RustType::Slice(ty) => parse_type_slice(ty),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
+fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
+    let which = match &inner {
+        Type::Ident(ident) if ident == "u8" => {
+            Type::Slice
+        },
+        _ => return Err(Error::new_spanned(ty, "unsupported type"))
+    };
+    Ok(which(Box::new(Slice {
+        bracket: ty.bracket_token,
+        inner
+    })))
+}
+
 fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     let inner = parse_type(&ty.elem)?;
     let which = match &inner {
@@ -236,6 +251,14 @@
                 Type::Str
             }
         }
+        Type::Slice(inner2) => {
+            match &inner2.inner {
+                Type::Ident(ident) if ident == "u8" => {
+                    Type::SliceRefU8
+                }
+                _ => return Err(Error::new_spanned(ty, "unsupported type"))
+            }
+        }
         _ => Type::Ref,
     };
     Ok(which(Box::new(Ref {
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 51592dd..df11852 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::*;
-use crate::syntax::{Derive, ExternFn, Ref, Signature, Ty1, Type, Var};
+use crate::syntax::{Derive, ExternFn, Ref, Signature, Slice, Ty1, Type, Var};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
 use syn::Token;
@@ -15,7 +15,8 @@
                 ident.to_tokens(tokens);
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
-            Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
+            Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
+            Type::Slice(s) => s.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
@@ -51,6 +52,14 @@
     }
 }
 
+impl ToTokens for Slice {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.bracket.surround(tokens, |tokens| {
+            self.inner.to_tokens(tokens);
+        });
+    }
+}
+
 impl ToTokens for Derive {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let name = match self {
diff --git a/syntax/types.rs b/syntax/types.rs
index f65b12f..6f3af09 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -23,9 +23,10 @@
         fn visit<'a>(all: &mut Set<'a, Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
-                Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
+                Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
                 Type::RustBox(ty) | Type::UniquePtr(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
+                Type::Slice(s) => visit(all, &s.inner),
                 Type::Fn(f) => {
                     if let Some(ret) = &f.ret {
                         visit(all, ret);