Upgrade flatbuffers to b2ce86ef8aef9a9caa8bcc99e54591b92d7b2426 am: 6b23ef32f8
am: 1dc713a198

Change-Id: I5df2aacb2d3cd7ba46cc0ecf61b2ab7b2d8db8f0
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index cea328d..13fc184 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -1,5 +1,5 @@
 ---
-buildifier: true
+buildifier: latest
 platforms:
   ubuntu1404:
     build_targets:
@@ -16,8 +16,3 @@
     - "..."
     test_targets:
     - "..."
-  windows:
-    build_targets:
-    - "..."
-    test_targets:
-    - "..."
diff --git a/.editorconfig b/.editorconfig
index be31d8c..6c54966 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,7 +1,7 @@
 root = true
-[*.{cpp,cc,h,sh}]
-end_of_line = LF
+# Don't set line endings to avoid conflict with core.autocrlf flag.
+# Line endings on checkout/checkin are controlled by .gitattributes file.
+[*]
 indent_style = space
 indent_size = 2
 insert_final_newline = true
-
diff --git a/.gitattributes b/.gitattributes
index 176a458..4cab1f4 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,2 @@
+# Set the default behavior, in case people don't have core.autocrlf set.
 * text=auto
diff --git a/.travis/check-sources.sh.py b/.travis/check-sources.sh.py
index 5ad060c..2b001d7 100644
--- a/.travis/check-sources.sh.py
+++ b/.travis/check-sources.sh.py
@@ -18,12 +18,11 @@
         btext.decode(encoding=encoding, errors="strict")
         if encoding == "utf-8" and btext.startswith(b'\xEF\xBB\xBF'):
           raise ValueError("unexpected BOM in file")
-        # check strict CRLF line-ending
-        LF = btext.count(b'\r')
-        CRLF = btext.count(b'\r\n')
-        assert LF >= CRLF, "CRLF logic error"
-        if CRLF != LF:
-          raise ValueError("CRLF violation: found {} LF characters".format(LF - CRLF))
+        # check LF line endings
+        LF = btext.count(b'\n')
+        CR = btext.count(b'\r')
+        if CR!=0:
+          raise ValueError("invalid line endings: LF({})/CR({})".format(LF, CR))
   except Exception as err:
     print("ERROR with [{}]: {}".format(fname, err))
     return -1
diff --git a/BUILD b/BUILD
index be30227..78e07d2 100644
--- a/BUILD
+++ b/BUILD
@@ -159,6 +159,7 @@
         ":tests/prototest/test_union.golden",
         ":tests/unicode_test.json",
         ":tests/union_vector/union_vector.fbs",
+        ":tests/union_vector/union_vector.json",
     ],
     includes = ["include/"],
     deps = [
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9f640ac..b7acbc7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -193,7 +193,7 @@
       "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
   set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
   if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.8)
-    list(APPEND FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wimplicit-fallthrough" "-Wextra-semi" "-Wc++98-compat-extra-semi" "-Werror=unused-private-field") # enable warning
+    list(APPEND FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wimplicit-fallthrough" "-Wextra-semi" "-Werror=unused-private-field") # enable warning
   endif()
   if(FLATBUFFERS_LIBCXX_WITH_CLANG)
     if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
diff --git a/METADATA b/METADATA
index abb1bc0..79954ab 100644
--- a/METADATA
+++ b/METADATA
@@ -9,10 +9,10 @@
     type: GIT
     value: "https://github.com/google/flatbuffers.git"
   }
-  version: "1c7d91cc55a9deb05e7ea93ba10b5ab511d29238"
+  version: "b2ce86ef8aef9a9caa8bcc99e54591b92d7b2426"
   last_upgrade_date {
     year: 2019
-    month: 3
-    day: 4
+    month: 4
+    day: 3
   }
 }
diff --git a/build_defs.bzl b/build_defs.bzl
index c55ab51..af67610 100644
--- a/build_defs.bzl
+++ b/build_defs.bzl
@@ -1,6 +1,10 @@
 # Description:
 #   BUILD rules for generating flatbuffer files in various languages.
 
+"""
+Rules for building C++ flatbuffers with Bazel.
+"""
+
 flatc_path = "@com_github_google_flatbuffers//:flatc"
 
 DEFAULT_INCLUDE_PATHS = [
@@ -46,9 +50,11 @@
         reflection binaries for the schemas.
       reflection_visiblity: The visibility of the generated reflection Fileset.
       output_to_bindir: Passed to genrule for output to bin directory.
-    Outs:
-      filegroup(name): all generated source files.
-      Fileset([reflection_name]): (Optional) all generated reflection binaries.
+
+
+    This rule creates a filegroup(name) with all generated source files, and
+    optionally a Fileset([reflection_name]) with all generated reflection
+    binaries.
     """
     include_paths_cmd = ["-I %s" % (s) for s in include_paths]
 
@@ -145,7 +151,8 @@
           By default, use the value of the visibility parameter above.
       gen_reflections: Optional, if true this will generate the flatbuffer
         reflection binaries for the schemas.
-    Outs:
+
+    This produces:
       filegroup([name]_srcs): all generated .h files.
       filegroup(srcs_filegroup_name if specified, or [name]_includes if not):
           Other flatbuffer_cc_library's can pass this in for their `includes`
diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md
index d7b44c8..90f8d8b 100644
--- a/docs/source/Compiler.md
+++ b/docs/source/Compiler.md
@@ -75,7 +75,7 @@
 -   `--allow-non-utf8` : Pass non-UTF-8 input through parser and emit nonstandard
     \x escapes in JSON. (Default is to raise parse error on non-UTF-8 input.)
 
--  `--natural-utf8` : Output strings with UTF-8 as human-readable strings. 
+-  `--natural-utf8` : Output strings with UTF-8 as human-readable strings.
      By default, UTF-8 characters are printed as \uXXXX escapes."
 
 -   `--defaults-json` : Output fields whose value is equal to the default value
@@ -120,7 +120,13 @@
 -   `--cpp-ptr-type T` : Set object API pointer type (default std::unique_ptr)
 
 -   `--cpp-str-type T` : Set object API string type (default std::string)
--   T::c_str() and T::length() must be supported.
+    T::c_str(), T::length() and T::empty() must be supported.
+    The custom type also needs to be constructible from std::string (see the
+	--cpp-str-flex-ctor option to change this behavior).
+
+-   `--cpp-str-flex-ctor` : Don't construct custom string types by passing
+    std::string from Flatbuffers, but (char* + length). This allows efficient
+	construction of custom string types, including zero-copy construction.
 
 -   `--object-prefix` : Customise class prefix for C++ object-based API.
 
@@ -168,7 +174,7 @@
     an evolution of. Gives errors if not. Useful to check if schema
     modifications don't break schema evolution rules.
 
--   `--conform-includes PATH` : Include path for the schema given with 
+-   `--conform-includes PATH` : Include path for the schema given with
     `--conform PATH`.
 
 -   `--include-prefix PATH` : Prefix this path to any generated include
diff --git a/docs/source/CppUsage.md b/docs/source/CppUsage.md
index 2808c49..6cf36d1 100644
--- a/docs/source/CppUsage.md
+++ b/docs/source/CppUsage.md
@@ -255,14 +255,24 @@
 pointer type specified by the `--cpp-ptr-type` argument to `flatc` from a
 flatbuffer field set the `cpp_ptr_type` attribute to `default_ptr_type`.
 
-
 # Using different string type.
 
 By default the object tree is built out of `std::string`, but you can
 influence this either globally (using the `--cpp-str-type` argument to
 `flatc`) or per field using the `cpp_str_type` attribute.
 
-The type must support T::c_str() and T::length() as member functions.
+The type must support T::c_str(), T::length() and T::empty() as member functions.
+
+Further, the type must be constructible from std::string, as by default a
+std::string instance is constructed and then used to initialize the custom
+string type. This behavior impedes efficient and zero-copy construction of
+custom string types; the `--cpp-str-flex-ctor` argument to `flatc` or the
+per field attribute `cpp_str_flex_ctor` can be used to change this behavior,
+so that the custom string type is constructed by passing the pointer and
+length of the FlatBuffers String. The custom string class will require a
+constructor in the following format: custom_str_class(const char *, size_t).
+Please note that the character array is not guaranteed to be NULL terminated,
+you should always use the provided size to determine end of string.
 
 ## Reflection (& Resizing)
 
diff --git a/docs/source/DartUsage.md b/docs/source/DartUsage.md
index 6be9772..6670cc5 100644
--- a/docs/source/DartUsage.md
+++ b/docs/source/DartUsage.md
@@ -16,7 +16,7 @@
 
 ## FlatBuffers Dart library code location
 
-The code for the FlatBuffers Go library can be found at
+The code for the FlatBuffers Dart library can be found at
 `flatbuffers/dart`. You can browse the library code on the [FlatBuffers
 GitHub page](https://github.com/google/flatbuffers/tree/master/dart).
 
diff --git a/docs/source/Grammar.md b/docs/source/Grammar.md
index 724137e..51cc5f0 100644
--- a/docs/source/Grammar.md
+++ b/docs/source/Grammar.md
@@ -14,7 +14,7 @@
 
 type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
 
-enum\_decl = ( `enum` ident [ `:` type ] | `union` ident )  metadata `{`
+enum\_decl = ( `enum` ident `:` type | `union` ident )  metadata `{`
 commasep( enumval\_decl ) `}`
 
 root\_decl = `root_type` ident `;`
diff --git a/docs/source/RustUsage.md b/docs/source/RustUsage.md
index 80434a4..6819117 100644
--- a/docs/source/RustUsage.md
+++ b/docs/source/RustUsage.md
@@ -68,6 +68,7 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
     extern crate flatbuffers;
 
+    #[allow(dead_code, unused_imports)]
     #[path = "../../monster_test_generated.rs"]
     mod monster_test_generated;
     pub use monster_test_generated::my_game;
diff --git a/docs/source/Tutorial.md b/docs/source/Tutorial.md
index db3efa3..4291c06 100644
--- a/docs/source/Tutorial.md
+++ b/docs/source/Tutorial.md
@@ -274,43 +274,43 @@
 
 <div class="language-cpp">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --cpp monster.fbs
 ~~~
 </div>
 <div class="language-java">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --java monster.fbs
 ~~~
 </div>
 <div class="language-csharp">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --csharp monster.fbs
 ~~~
 </div>
 <div class="language-go">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --go monster.fbs
 ~~~
 </div>
 <div class="language-python">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --python monster.fbs
 ~~~
 </div>
 <div class="language-javascript">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --js monster.fbs
 ~~~
 </div>
 <div class="language-typescript">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --ts monster.fbs
 ~~~
 </div>
@@ -331,25 +331,25 @@
 </div>
 <div class="language-dart">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --dart monster.fbs
 ~~~
 </div>
 <div class="language-lua">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --lua monster.fbs
 ~~~
 </div>
 <div class="language-lobster">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --lobster monster.fbs
 ~~~
 </div>
 <div class="language-rust">
 ~~~{.sh}
-  cd flatbuffers/sample
+  cd flatbuffers/samples
   ./../flatc --rust monster.fbs
 ~~~
 </div>
@@ -495,6 +495,7 @@
   extern crate flatbuffers;
 
   // import the generated code
+  #[allow(dead_code, unused_imports)]
   #[path = "./monster_generated.rs"]
   mod monster_generated;
   pub use monster_generated::my_game::sample::{get_root_as_monster,
@@ -2042,6 +2043,7 @@
   extern crate flatbuffers;
 
   // import the generated code
+  #[allow(dead_code, unused_imports)]
   #[path = "./monster_generated.rs"]
   mod monster_generated;
   pub use monster_generated::my_game::sample::{get_root_as_monster,
diff --git a/include/flatbuffers/hash.h b/include/flatbuffers/hash.h
index a97b231..16536cb 100644
--- a/include/flatbuffers/hash.h
+++ b/include/flatbuffers/hash.h
@@ -39,7 +39,7 @@
   static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
 };
 
-template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1(const char *input) {
+template<typename T> T HashFnv1(const char *input) {
   T hash = FnvTraits<T>::kOffsetBasis;
   for (const char *c = input; *c; ++c) {
     hash *= FnvTraits<T>::kFnvPrime;
@@ -48,7 +48,7 @@
   return hash;
 }
 
-template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1a(const char *input) {
+template<typename T> T HashFnv1a(const char *input) {
   T hash = FnvTraits<T>::kOffsetBasis;
   for (const char *c = input; *c; ++c) {
     hash ^= static_cast<unsigned char>(*c);
@@ -57,12 +57,12 @@
   return hash;
 }
 
-template <> FLATBUFFERS_CONSTEXPR_CPP14 inline uint16_t HashFnv1<uint16_t>(const char *input) {
+template <> inline uint16_t HashFnv1<uint16_t>(const char *input) {
   uint32_t hash = HashFnv1<uint32_t>(input);
   return (hash >> 16) ^ (hash & 0xffff);
 }
 
-template <> FLATBUFFERS_CONSTEXPR_CPP14 inline uint16_t HashFnv1a<uint16_t>(const char *input) {
+template <> inline uint16_t HashFnv1a<uint16_t>(const char *input) {
   uint32_t hash = HashFnv1a<uint32_t>(input);
   return (hash >> 16) ^ (hash & 0xffff);
 }
diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h
index 6b70f3a..05d666c 100644
--- a/include/flatbuffers/idl.h
+++ b/include/flatbuffers/idl.h
@@ -410,6 +410,7 @@
   bool gen_compare;
   std::string cpp_object_api_pointer_type;
   std::string cpp_object_api_string_type;
+  bool cpp_object_api_string_flexible_constructor;
   bool gen_nullable;
   bool gen_generated;
   std::string object_prefix;
@@ -486,6 +487,7 @@
         generate_object_based_api(false),
         gen_compare(false),
         cpp_object_api_pointer_type("std::unique_ptr"),
+        cpp_object_api_string_flexible_constructor(false),
         gen_nullable(false),
         gen_generated(false),
         object_suffix("T"),
@@ -627,6 +629,7 @@
     known_attributes_["cpp_ptr_type"] = true;
     known_attributes_["cpp_ptr_type_get"] = true;
     known_attributes_["cpp_str_type"] = true;
+    known_attributes_["cpp_str_flex_ctor"] = true;
     known_attributes_["native_inline"] = true;
     known_attributes_["native_custom_alloc"] = true;
     known_attributes_["native_type"] = true;
@@ -719,7 +722,9 @@
   FLATBUFFERS_CHECKED_ERROR ParseComma();
   FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
                                           size_t parent_fieldn,
-                                          const StructDef *parent_struct_def);
+                                          const StructDef *parent_struct_def,
+                                          uoffset_t count,
+                                          bool inside_vector = false);
   template<typename F>
   FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
                                                  const StructDef *struct_def,
@@ -728,8 +733,9 @@
                                        std::string *value, uoffset_t *ovalue);
   void SerializeStruct(const StructDef &struct_def, const Value &val);
   template<typename F>
-  FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(size_t &count, F body);
-  FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue);
+  FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
+  FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
+                                        FieldDef *field, size_t fieldn);
   FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
                                                   size_t fieldn,
                                                   const StructDef *parent_struct_def);
@@ -775,7 +781,7 @@
                                        const char *suffix,
                                        BaseType baseType);
 
-  bool SupportsVectorOfUnions() const;
+  bool SupportsAdvancedUnionFeatures() const;
   Namespace *UniqueNamespace(Namespace *ns);
 
   FLATBUFFERS_CHECKED_ERROR RecurseError();
diff --git a/include/flatbuffers/minireflect.h b/include/flatbuffers/minireflect.h
index fc0cc43..9d648ec 100644
--- a/include/flatbuffers/minireflect.h
+++ b/include/flatbuffers/minireflect.h
@@ -287,10 +287,20 @@
   bool q;
   std::string in;
   size_t indent_level;
-  ToStringVisitor(std::string delimiter, bool quotes, std::string indent)
-      : d(delimiter), q(quotes), in(indent), indent_level(0) {}
+  bool vector_delimited;
+  ToStringVisitor(std::string delimiter, bool quotes, std::string indent,
+                  bool vdelimited = true)
+      : d(delimiter),
+        q(quotes),
+        in(indent),
+        indent_level(0),
+        vector_delimited(vdelimited) {}
   ToStringVisitor(std::string delimiter)
-      : d(delimiter), q(false), in(""), indent_level(0) {}
+      : d(delimiter),
+        q(false),
+        in(""),
+        indent_level(0),
+        vector_delimited(true) {}
 
   void append_indent() {
     for (size_t i = 0; i < indent_level; i++) { s += in; }
@@ -350,30 +360,44 @@
   void Unknown(const uint8_t *) { s += "(?)"; }
   void StartVector() {
     s += "[";
-    s += d;
-    indent_level++;
-    append_indent();
+    if (vector_delimited) {
+      s += d;
+      indent_level++;
+      append_indent();
+    } else {
+      s += " ";
+    }
   }
   void EndVector() {
-    s += d;
-    indent_level--;
-    append_indent();
+    if (vector_delimited) {
+      s += d;
+      indent_level--;
+      append_indent();
+    } else {
+      s += " ";
+    }
     s += "]";
   }
   void Element(size_t i, ElementaryType /*type*/,
                const TypeTable * /*type_table*/, const uint8_t * /*val*/) {
     if (i) {
       s += ",";
-      s += d;
-      append_indent();
+      if (vector_delimited) {
+        s += d;
+        append_indent();
+      } else {
+        s += " ";
+      }
     }
   }
 };
 
 inline std::string FlatBufferToString(const uint8_t *buffer,
                                       const TypeTable *type_table,
-                                      bool multi_line = false) {
-  ToStringVisitor tostring_visitor(multi_line ? "\n" : " ");
+                                      bool multi_line = false,
+                                      bool vector_delimited = true) {
+  ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, "",
+                                   vector_delimited);
   IterateFlatBuffer(buffer, type_table, &tostring_visitor);
   return tostring_visitor.s;
 }
diff --git a/include/flatbuffers/reflection_generated.h b/include/flatbuffers/reflection_generated.h
index fc72059..869a9f3 100644
--- a/include/flatbuffers/reflection_generated.h
+++ b/include/flatbuffers/reflection_generated.h
@@ -95,7 +95,7 @@
 
 inline const char *EnumNameBaseType(BaseType e) {
   if (e < None || e > Union) return "";
-  const size_t index = static_cast<int>(e);
+  const size_t index = static_cast<size_t>(e);
   return EnumNamesBaseType()[index];
 }
 
diff --git a/include/flatbuffers/util.h b/include/flatbuffers/util.h
index 275747b..4367bbe 100644
--- a/include/flatbuffers/util.h
+++ b/include/flatbuffers/util.h
@@ -35,19 +35,19 @@
 
 // @locale-independent functions for ASCII characters set.
 
-// Check that integer scalar is in closed range: (a <= x <= b)
+// Fast checking that character lies in closed range: [a <= x <= b]
 // using one compare (conditional branch) operator.
-template<typename T> inline bool check_in_range(T x, T a, T b) {
+inline bool check_ascii_range(char x, char a, char b) {
+  FLATBUFFERS_ASSERT(a <= b);
   // (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`.
-  FLATBUFFERS_ASSERT(a <= b);  // static_assert only if 'a' & 'b' templated
-  typedef typename flatbuffers::make_unsigned<T>::type U;
-  return (static_cast<U>(x - a) <= static_cast<U>(b - a));
+  // The x, a, b will be promoted to int and subtracted without overflow.
+  return static_cast<unsigned int>(x - a) <= static_cast<unsigned int>(b - a);
 }
 
 // Case-insensitive isalpha
 inline bool is_alpha(char c) {
   // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
-  return check_in_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF);
+  return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF);
 }
 
 // Check (case-insensitive) that `c` is equal to alpha.
@@ -62,11 +62,11 @@
 // functions that are not affected by the currently installed C locale. although
 // some implementations (e.g. Microsoft in 1252 codepage) may classify
 // additional single-byte characters as digits.
-inline bool is_digit(char c) { return check_in_range(c, '0', '9'); }
+inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); }
 
 inline bool is_xdigit(char c) {
   // Replace by look-up table.
-  return is_digit(c) || check_in_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF);
+  return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF);
 }
 
 // Case-insensitive isalnum
diff --git a/rust/flatbuffers/src/endian_scalar.rs b/rust/flatbuffers/src/endian_scalar.rs
index 00f2ebe..3e7244e 100644
--- a/rust/flatbuffers/src/endian_scalar.rs
+++ b/rust/flatbuffers/src/endian_scalar.rs
@@ -88,7 +88,7 @@
         }
         #[cfg(not(target_endian = "little"))]
         {
-            byte_swap_f32(&self)
+            byte_swap_f32(self)
         }
     }
     /// Convert f32 from little-endian to host endian-ness.
@@ -100,7 +100,7 @@
         }
         #[cfg(not(target_endian = "little"))]
         {
-            byte_swap_f32(&self)
+            byte_swap_f32(self)
         }
     }
 }
@@ -115,7 +115,7 @@
         }
         #[cfg(not(target_endian = "little"))]
         {
-            byte_swap_f64(&self)
+            byte_swap_f64(self)
         }
     }
     /// Convert f64 from little-endian to host endian-ness.
@@ -127,7 +127,7 @@
         }
         #[cfg(not(target_endian = "little"))]
         {
-            byte_swap_f64(&self)
+            byte_swap_f64(self)
         }
     }
 }
diff --git a/rust/flatbuffers/src/vector.rs b/rust/flatbuffers/src/vector.rs
index 8c2d6d5..397089a 100644
--- a/rust/flatbuffers/src/vector.rs
+++ b/rust/flatbuffers/src/vector.rs
@@ -19,7 +19,9 @@
 use std::slice::from_raw_parts;
 use std::str::from_utf8_unchecked;
 
-use endian_scalar::{EndianScalar, read_scalar};
+#[cfg(target_endian = "little")]
+use endian_scalar::EndianScalar;
+use endian_scalar::read_scalar;
 use follow::Follow;
 use primitives::*;
 
@@ -85,6 +87,7 @@
     impl super::SafeSliceAccess for f64 {}
 }
 
+#[cfg(target_endian = "little")]
 pub use self::le_safe_slice_impls::*;
 
 pub fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
@@ -104,6 +107,7 @@
     }
 }
 
+#[cfg(target_endian = "little")]
 fn follow_slice_helper<T>(buf: &[u8], loc: usize) -> &[T] {
     let sz = size_of::<T>();
     debug_assert!(sz > 0);
diff --git a/samples/monster_generated.h b/samples/monster_generated.h
index 5286ffd..84e8160 100644
--- a/samples/monster_generated.h
+++ b/samples/monster_generated.h
@@ -18,8 +18,11 @@
 struct WeaponT;
 
 bool operator==(const Vec3 &lhs, const Vec3 &rhs);
+bool operator!=(const Vec3 &lhs, const Vec3 &rhs);
 bool operator==(const MonsterT &lhs, const MonsterT &rhs);
+bool operator!=(const MonsterT &lhs, const MonsterT &rhs);
 bool operator==(const WeaponT &lhs, const WeaponT &rhs);
+bool operator!=(const WeaponT &lhs, const WeaponT &rhs);
 
 inline const flatbuffers::TypeTable *Vec3TypeTable();
 
@@ -56,7 +59,7 @@
 
 inline const char *EnumNameColor(Color e) {
   if (e < Color_Red || e > Color_Blue) return "";
-  const size_t index = static_cast<int>(e);
+  const size_t index = static_cast<size_t>(e);
   return EnumNamesColor()[index];
 }
 
@@ -86,7 +89,7 @@
 
 inline const char *EnumNameEquipment(Equipment e) {
   if (e < Equipment_NONE || e > Equipment_Weapon) return "";
-  const size_t index = static_cast<int>(e);
+  const size_t index = static_cast<size_t>(e);
   return EnumNamesEquipment()[index];
 }
 
@@ -155,6 +158,11 @@
     }
   }
 }
+
+inline bool operator!=(const EquipmentUnion &lhs, const EquipmentUnion &rhs) {
+    return !(lhs == rhs);
+}
+
 bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *obj, Equipment type);
 bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
 
@@ -201,6 +209,11 @@
       (lhs.z() == rhs.z());
 }
 
+inline bool operator!=(const Vec3 &lhs, const Vec3 &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct MonsterT : public flatbuffers::NativeTable {
   typedef Monster TableType;
   flatbuffers::unique_ptr<Vec3> pos;
@@ -230,6 +243,11 @@
       (lhs.equipped == rhs.equipped);
 }
 
+inline bool operator!=(const MonsterT &lhs, const MonsterT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef MonsterT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
@@ -441,6 +459,11 @@
       (lhs.damage == rhs.damage);
 }
 
+inline bool operator!=(const WeaponT &lhs, const WeaponT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef WeaponT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
diff --git a/src/flatc.cpp b/src/flatc.cpp
index c5ec70e..3833f3d 100644
--- a/src/flatc.cpp
+++ b/src/flatc.cpp
@@ -100,14 +100,18 @@
     "  --gen-compare      Generate operator== for object-based API types.\n"
     "  --gen-nullable     Add Clang _Nullable for C++ pointer. or @Nullable for Java\n"
     "  --gen-generated    Add @Generated annotation for Java\n"
-    "  --gen-all          Generate not just code for the current schema files,\n" 
+    "  --gen-all          Generate not just code for the current schema files,\n"
     "                     but for all files it includes as well.\n"
     "                     If the language uses a single file for output (by default\n"
     "                     the case for C++ and JS), all code will end up in this one\n"
     "                     file.\n"
     "  --cpp-ptr-type T   Set object API pointer type (default std::unique_ptr).\n"
     "  --cpp-str-type T   Set object API string type (default std::string).\n"
-    "                     T::c_str() and T::length() must be supported.\n"
+    "                     T::c_str(), T::length() and T::empty() must be supported.\n"
+    "                     The custom type also needs to be constructible from std::string\n"
+    "                     (see the --cpp-str-flex-ctor option to change this behavior).\n"
+    "  --cpp-str-flex-ctor Don't construct custom string types by passing std::string\n"
+    "                     from Flatbuffers, but (char* + length).\n"
     "  --object-prefix    Customise class prefix for C++ object-based API.\n"
     "  --object-suffix    Customise class suffix for C++ object-based API.\n"
     "                     Default value is \"T\".\n"
@@ -247,6 +251,8 @@
       } else if (arg == "--cpp-str-type") {
         if (++argi >= argc) Error("missing type following" + arg, true);
         opts.cpp_object_api_string_type = argv[argi];
+      } else if (arg == "--cpp-str-flex-ctor") {
+        opts.cpp_object_api_string_flexible_constructor = true;
       } else if (arg == "--gen-nullable") {
         opts.gen_nullable = true;
       } else if (arg == "--gen-generated") {
diff --git a/src/flathash.cpp b/src/flathash.cpp
index 2194e30..bc3d2df 100644
--- a/src/flathash.cpp
+++ b/src/flathash.cpp
@@ -25,7 +25,7 @@
 int main(int argc, char *argv[]) {
   const char *name = argv[0];
   if (argc <= 1) {
-    printf("%s HASH [OPTION]... STRING... [-- STRING...]\n", name);
+    printf("%s HASH [OPTION]... [--] STRING...\n", name);
     printf("Available hashing algorithms:\n");
     printf("  16 bit:\n");
     size_t size = sizeof(flatbuffers::kHashFunctions16) /
@@ -50,7 +50,7 @@
         "  -x         Output hash in hexadecimal.\n"
         "  -0x        Output hash in hexadecimal and prefix with 0x.\n"
         "  -c         Append the string to the output in a c-style comment.\n");
-    return 0;
+    return 1;
   }
 
   const char *hash_algorithm = argv[1];
@@ -64,7 +64,7 @@
 
   if (!hash_function16 && !hash_function32 && !hash_function64) {
     printf("\"%s\" is not a known hash algorithm.\n", hash_algorithm);
-    return 0;
+    return 1;
   }
 
   OutputFormat output_format = kHexadecimal;
diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp
index efbfe07..50cb82f 100644
--- a/src/idl_gen_cpp.cpp
+++ b/src/idl_gen_cpp.cpp
@@ -43,103 +43,104 @@
         float_const_gen_("std::numeric_limits<double>::",
                          "std::numeric_limits<float>::", "quiet_NaN()",
                          "infinity()") {
-    static const char * const keywords[] = {
-                               "alignas",
-                               "alignof",
-                               "and",
-                               "and_eq",
-                               "asm",
-                               "atomic_cancel",
-                               "atomic_commit",
-                               "atomic_noexcept",
-                               "auto",
-                               "bitand",
-                               "bitor",
-                               "bool",
-                               "break",
-                               "case",
-                               "catch",
-                               "char",
-                               "char16_t",
-                               "char32_t",
-                               "class",
-                               "compl",
-                               "concept",
-                               "const",
-                               "constexpr",
-                               "const_cast",
-                               "continue",
-                               "co_await",
-                               "co_return",
-                               "co_yield",
-                               "decltype",
-                               "default",
-                               "delete",
-                               "do",
-                               "double",
-                               "dynamic_cast",
-                               "else",
-                               "enum",
-                               "explicit",
-                               "export",
-                               "extern",
-                               "false",
-                               "float",
-                               "for",
-                               "friend",
-                               "goto",
-                               "if",
-                               "import",
-                               "inline",
-                               "int",
-                               "long",
-                               "module",
-                               "mutable",
-                               "namespace",
-                               "new",
-                               "noexcept",
-                               "not",
-                               "not_eq",
-                               "nullptr",
-                               "operator",
-                               "or",
-                               "or_eq",
-                               "private",
-                               "protected",
-                               "public",
-                               "register",
-                               "reinterpret_cast",
-                               "requires",
-                               "return",
-                               "short",
-                               "signed",
-                               "sizeof",
-                               "static",
-                               "static_assert",
-                               "static_cast",
-                               "struct",
-                               "switch",
-                               "synchronized",
-                               "template",
-                               "this",
-                               "thread_local",
-                               "throw",
-                               "true",
-                               "try",
-                               "typedef",
-                               "typeid",
-                               "typename",
-                               "union",
-                               "unsigned",
-                               "using",
-                               "virtual",
-                               "void",
-                               "volatile",
-                               "wchar_t",
-                               "while",
-                               "xor",
-                               "xor_eq",
-                               nullptr };
+    static const char *const keywords[] = {
+      "alignas",
+      "alignof",
+      "and",
+      "and_eq",
+      "asm",
+      "atomic_cancel",
+      "atomic_commit",
+      "atomic_noexcept",
+      "auto",
+      "bitand",
+      "bitor",
+      "bool",
+      "break",
+      "case",
+      "catch",
+      "char",
+      "char16_t",
+      "char32_t",
+      "class",
+      "compl",
+      "concept",
+      "const",
+      "constexpr",
+      "const_cast",
+      "continue",
+      "co_await",
+      "co_return",
+      "co_yield",
+      "decltype",
+      "default",
+      "delete",
+      "do",
+      "double",
+      "dynamic_cast",
+      "else",
+      "enum",
+      "explicit",
+      "export",
+      "extern",
+      "false",
+      "float",
+      "for",
+      "friend",
+      "goto",
+      "if",
+      "import",
+      "inline",
+      "int",
+      "long",
+      "module",
+      "mutable",
+      "namespace",
+      "new",
+      "noexcept",
+      "not",
+      "not_eq",
+      "nullptr",
+      "operator",
+      "or",
+      "or_eq",
+      "private",
+      "protected",
+      "public",
+      "register",
+      "reinterpret_cast",
+      "requires",
+      "return",
+      "short",
+      "signed",
+      "sizeof",
+      "static",
+      "static_assert",
+      "static_cast",
+      "struct",
+      "switch",
+      "synchronized",
+      "template",
+      "this",
+      "thread_local",
+      "throw",
+      "true",
+      "try",
+      "typedef",
+      "typeid",
+      "typename",
+      "union",
+      "unsigned",
+      "using",
+      "virtual",
+      "void",
+      "volatile",
+      "wchar_t",
+      "while",
+      "xor",
+      "xor_eq",
+      nullptr,
+    };
     for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
   }
 
@@ -230,10 +231,9 @@
         SetNameSpace(struct_def.defined_namespace);
         code_ += "struct " + Name(struct_def) + ";";
         if (parser_.opts.generate_object_based_api) {
-          auto nativeName = NativeName(Name(struct_def), &struct_def, parser_.opts);
-          if (!struct_def.fixed) {
-            code_ += "struct " + nativeName + ";";
-          }
+          auto nativeName =
+              NativeName(Name(struct_def), &struct_def, parser_.opts);
+          if (!struct_def.fixed) { code_ += "struct " + nativeName + ";"; }
         }
         code_ += "";
       }
@@ -242,12 +242,16 @@
     // Generate forward declarations for all equal operators
     if (parser_.opts.generate_object_based_api && parser_.opts.gen_compare) {
       for (auto it = parser_.structs_.vec.begin();
-          it != parser_.structs_.vec.end(); ++it) {
+           it != parser_.structs_.vec.end(); ++it) {
         const auto &struct_def = **it;
         if (!struct_def.generated) {
           SetNameSpace(struct_def.defined_namespace);
-          auto nativeName = NativeName(Name(struct_def), &struct_def, parser_.opts);
-          code_ += "bool operator==(const " + nativeName + " &lhs, const " + nativeName + " &rhs);";
+          auto nativeName =
+              NativeName(Name(struct_def), &struct_def, parser_.opts);
+          code_ += "bool operator==(const " + nativeName + " &lhs, const " +
+                   nativeName + " &rhs);";
+          code_ += "bool operator!=(const " + nativeName + " &lhs, const " +
+              nativeName + " &rhs);";
         }
       }
       code_ += "";
@@ -357,7 +361,8 @@
 
       code_ += "inline \\";
       code_ +=
-          "const {{CPP_NAME}} *{{NULLABLE_EXT}}GetSizePrefixed{{STRUCT_NAME}}(const void "
+          "const {{CPP_NAME}} "
+          "*{{NULLABLE_EXT}}GetSizePrefixed{{STRUCT_NAME}}(const void "
           "*buf) {";
       code_ += "  return flatbuffers::GetSizePrefixedRoot<{{CPP_NAME}}>(buf);";
       code_ += "}";
@@ -402,7 +407,8 @@
 
       code_ += "inline bool VerifySizePrefixed{{STRUCT_NAME}}Buffer(";
       code_ += "    flatbuffers::Verifier &verifier) {";
-      code_ += "  return verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}>({{ID}});";
+      code_ +=
+          "  return verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}>({{ID}});";
       code_ += "}";
       code_ += "";
 
@@ -494,15 +500,15 @@
 
   // Return a C++ type from the table in idl.h
   std::string GenTypeBasic(const Type &type, bool user_facing_type) const {
-    static const char * const ctypename[] = {
     // clang-format off
+    static const char *const ctypename[] = {
     #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
                            RTYPE) \
             #CTYPE,
         FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
     #undef FLATBUFFERS_TD
-      // clang-format on
     };
+    // clang-format on
     if (user_facing_type) {
       if (type.enum_def) return WrapInNameSpace(*type.enum_def);
       if (type.base_type == BASE_TYPE_BOOL) return "bool";
@@ -577,12 +583,24 @@
     return ret;
   }
 
+  bool FlexibleStringConstructor(const FieldDef *field) {
+    auto attr = field
+                    ? (field->attributes.Lookup("cpp_str_flex_ctor") != nullptr)
+                    : false;
+    auto ret =
+        attr ? attr : parser_.opts.cpp_object_api_string_flexible_constructor;
+    return ret && NativeString(field) !=
+                      "std::string";  // Only for custom string types.
+  }
+
   std::string GenTypeNativePtr(const std::string &type, const FieldDef *field,
                                bool is_constructor) {
     auto &ptr_type = PtrType(field);
     if (ptr_type != "naked") {
-      return (ptr_type != "default_ptr_type" ? ptr_type :
-              parser_.opts.cpp_object_api_pointer_type) + "<" + type + ">";
+      return (ptr_type != "default_ptr_type"
+                  ? ptr_type
+                  : parser_.opts.cpp_object_api_pointer_type) +
+             "<" + type + ">";
     } else if (is_constructor) {
       return "";
     } else {
@@ -592,8 +610,7 @@
 
   std::string GenPtrGet(const FieldDef &field) {
     auto cpp_ptr_type_get = field.attributes.Lookup("cpp_ptr_type_get");
-    if (cpp_ptr_type_get)
-      return cpp_ptr_type_get->constant;
+    if (cpp_ptr_type_get) return cpp_ptr_type_get->constant;
     auto &ptr_type = PtrType(&field);
     return ptr_type == "naked" ? "" : ".get()";
   }
@@ -943,14 +960,15 @@
     code_ += "};";
 
     if (parser_.opts.scoped_enums && enum_def.attributes.Lookup("bit_flags")) {
-      code_ += "FLATBUFFERS_DEFINE_BITMASK_OPERATORS({{ENUM_NAME}}, {{BASE_TYPE}})";
+      code_ +=
+          "FLATBUFFERS_DEFINE_BITMASK_OPERATORS({{ENUM_NAME}}, {{BASE_TYPE}})";
     }
     code_ += "";
 
     // Generate an array of all enumeration values
     auto num_fields = NumToString(enum_def.vals.vec.size());
-    code_ += "inline const {{ENUM_NAME}} (&EnumValues{{ENUM_NAME}}())[" + num_fields +
-             "] {";
+    code_ += "inline const {{ENUM_NAME}} (&EnumValues{{ENUM_NAME}}())[" +
+             num_fields + "] {";
     code_ += "  static const {{ENUM_NAME}} values[] = {";
     for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
          ++it) {
@@ -994,14 +1012,15 @@
 
       code_ += "inline const char *EnumName{{ENUM_NAME}}({{ENUM_NAME}} e) {";
 
-      code_ += "  if (e < " + GetEnumValUse(enum_def, *enum_def.vals.vec.front()) +
+      code_ += "  if (e < " +
+               GetEnumValUse(enum_def, *enum_def.vals.vec.front()) +
                " || e > " + GetEnumValUse(enum_def, *enum_def.vals.vec.back()) +
                ") return \"\";";
 
-      code_ += "  const size_t index = static_cast<int>(e)\\";
+      code_ += "  const size_t index = static_cast<size_t>(e)\\";
       if (enum_def.vals.vec.front()->value) {
         auto vals = GetEnumValUse(enum_def, *enum_def.vals.vec.front());
-        code_ += " - static_cast<int>(" + vals + ")\\";
+        code_ += " - static_cast<size_t>(" + vals + ")\\";
       }
       code_ += ";";
 
@@ -1123,22 +1142,28 @@
 
       if (parser_.opts.gen_compare) {
         code_ += "";
-        code_ += "inline bool operator==(const {{NAME}}Union &lhs, const {{NAME}}Union &rhs) {";
+        code_ +=
+            "inline bool operator==(const {{NAME}}Union &lhs, const "
+            "{{NAME}}Union &rhs) {";
         code_ += "  if (lhs.type != rhs.type) return false;";
         code_ += "  switch (lhs.type) {";
 
         for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
-           ++it) {
+             ++it) {
           const auto &ev = **it;
           code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
           if (ev.value) {
             const auto native_type =
                 NativeName(GetUnionElement(ev, true, true, true),
-                          ev.union_type.struct_def, parser_.opts);
+                           ev.union_type.struct_def, parser_.opts);
             code_.SetValue("NATIVE_TYPE", native_type);
             code_ += "    case {{NATIVE_ID}}: {";
-            code_ += "      return *(reinterpret_cast<const {{NATIVE_TYPE}} *>(lhs.value)) ==";
-            code_ += "             *(reinterpret_cast<const {{NATIVE_TYPE}} *>(rhs.value));";
+            code_ +=
+                "      return *(reinterpret_cast<const {{NATIVE_TYPE}} "
+                "*>(lhs.value)) ==";
+            code_ +=
+                "             *(reinterpret_cast<const {{NATIVE_TYPE}} "
+                "*>(rhs.value));";
             code_ += "    }";
           } else {
             code_ += "    case {{NATIVE_ID}}: {";
@@ -1151,6 +1176,14 @@
         code_ += "    }";
         code_ += "  }";
         code_ += "}";
+
+        code_ += "";
+        code_ +=
+            "inline bool operator!=(const {{NAME}}Union &lhs, const "
+            "{{NAME}}Union &rhs) {";
+        code_ += "    return !(lhs == rhs);";
+        code_ += "}";
+        code_ += "";
       }
     }
 
@@ -1319,7 +1352,8 @@
               "      value = new {{TYPE}}(*reinterpret_cast<{{TYPE}} *>"
               "(u.value));";
         } else {
-          code_ += "      FLATBUFFERS_ASSERT(false);  // {{TYPE}} not copyable.";
+          code_ +=
+              "      FLATBUFFERS_ASSERT(false);  // {{TYPE}} not copyable.";
         }
         code_ += "      break;";
         code_ += "    }";
@@ -1395,7 +1429,7 @@
   }
 
   std::string GenDefaultConstant(const FieldDef &field) {
-    if(IsFloat(field.value.type.base_type))
+    if (IsFloat(field.value.type.base_type))
       return float_const_gen_.GenFloatConstant(field);
     else
       return field.value.constant;
@@ -1460,10 +1494,14 @@
       auto type = GenTypeNative(field.value.type, false, field);
       auto cpp_type = field.attributes.Lookup("cpp_type");
       auto full_type =
-          (cpp_type ? (field.value.type.base_type == BASE_TYPE_VECTOR
-                      ? "std::vector<" + GenTypeNativePtr(cpp_type->constant, &field, false) + "> "
+          (cpp_type
+               ? (field.value.type.base_type == BASE_TYPE_VECTOR
+                      ? "std::vector<" +
+                            GenTypeNativePtr(cpp_type->constant, &field,
+                                             false) +
+                            "> "
                       : GenTypeNativePtr(cpp_type->constant, &field, false))
-                    : type + " ");
+               : type + " ");
       code_.SetValue("FIELD_TYPE", full_type);
       code_.SetValue("FIELD_NAME", Name(field));
       code_ += "  {{FIELD_TYPE}}{{FIELD_NAME}};";
@@ -1485,7 +1523,11 @@
         if (IsScalar(field.value.type.base_type)) {
           if (!initializer_list.empty()) { initializer_list += ",\n        "; }
           initializer_list += Name(field);
-          initializer_list += "(" + (native_default ? std::string(native_default->constant) : GetDefaultScalarValue(field, true)) + ")";
+          initializer_list +=
+              "(" +
+              (native_default ? std::string(native_default->constant)
+                              : GetDefaultScalarValue(field, true)) +
+              ")";
         } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
           if (IsStruct(field.value.type)) {
             if (native_default) {
@@ -1514,18 +1556,17 @@
     code_ += "  }";
   }
 
-  void GenCompareOperator(const StructDef &struct_def, std::string accessSuffix = "") {
+  void GenCompareOperator(const StructDef &struct_def,
+                          std::string accessSuffix = "") {
     std::string compare_op;
     for (auto it = struct_def.fields.vec.begin();
          it != struct_def.fields.vec.end(); ++it) {
       const auto &field = **it;
       if (!field.deprecated &&  // Deprecated fields won't be accessible.
-        field.value.type.base_type != BASE_TYPE_UTYPE &&
-        (field.value.type.base_type != BASE_TYPE_VECTOR ||
-         field.value.type.element != BASE_TYPE_UTYPE)) {
-        if (!compare_op.empty()) {
-          compare_op += " &&\n      ";
-        }
+          field.value.type.base_type != BASE_TYPE_UTYPE &&
+          (field.value.type.base_type != BASE_TYPE_VECTOR ||
+           field.value.type.element != BASE_TYPE_UTYPE)) {
+        if (!compare_op.empty()) { compare_op += " &&\n      "; }
         auto accessor = Name(field) + accessSuffix;
         compare_op += "(lhs." + accessor + " == rhs." + accessor + ")";
       }
@@ -1547,9 +1588,19 @@
     code_.SetValue("CMP_LHS", cmp_lhs);
     code_.SetValue("CMP_RHS", cmp_rhs);
     code_ += "";
-    code_ += "inline bool operator==(const {{NATIVE_NAME}} &{{CMP_LHS}}, const {{NATIVE_NAME}} &{{CMP_RHS}}) {";
+    code_ +=
+        "inline bool operator==(const {{NATIVE_NAME}} &{{CMP_LHS}}, const "
+        "{{NATIVE_NAME}} &{{CMP_RHS}}) {";
     code_ += "{{CMP_OP}}";
     code_ += "}";
+
+    code_ += "";
+    code_ +=
+        "inline bool operator!=(const {{NATIVE_NAME}} &lhs, const "
+        "{{NATIVE_NAME}} &rhs) {";
+    code_ += "    return !(lhs == rhs);";
+    code_ += "}";
+    code_ += "";
   }
 
   void GenOperatorNewDelete(const StructDef &struct_def) {
@@ -1701,12 +1752,12 @@
       code_ += "  typedef {{NATIVE_NAME}} NativeTableType;";
     }
     if (parser_.opts.mini_reflect != IDLOptions::kNone) {
-      code_ += "  static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
+      code_ +=
+          "  static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
       code_ += "    return {{STRUCT_NAME}}TypeTable();";
       code_ += "  }";
     }
 
-
     GenFullyQualifiedNameGetter(struct_def, Name(struct_def));
 
     // Generate field id constants.
@@ -1714,7 +1765,8 @@
       // We need to add a trailing comma to all elements except the last one as
       // older versions of gcc complain about this.
       code_.SetValue("SEP", "");
-      code_ += "  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {";
+      code_ +=
+          "  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {";
       for (auto it = struct_def.fields.vec.begin();
            it != struct_def.fields.vec.end(); ++it) {
         const auto &field = **it;
@@ -1789,9 +1841,8 @@
           auto full_struct_name = GetUnionElement(ev, true, true);
 
           // @TODO: Mby make this decisions more universal? How?
-          code_.SetValue(
-              "U_GET_TYPE",
-              EscapeKeyword(field.name + UnionTypeFieldSuffix()));
+          code_.SetValue("U_GET_TYPE",
+                         EscapeKeyword(field.name + UnionTypeFieldSuffix()));
           code_.SetValue(
               "U_ELEMENT_TYPE",
               WrapInNameSpace(u->defined_namespace, GetEnumValUse(*u, ev)));
@@ -1855,7 +1906,9 @@
         code_.SetValue("CPP_NAME", TranslateNameSpace(qualified_name));
 
         code_ += "  const {{CPP_NAME}} *{{FIELD_NAME}}_nested_root() const {";
-        code_ += "    return flatbuffers::GetRoot<{{CPP_NAME}}>({{FIELD_NAME}}()->Data());";
+        code_ +=
+            "    return "
+            "flatbuffers::GetRoot<{{CPP_NAME}}>({{FIELD_NAME}}()->Data());";
         code_ += "  }";
       }
 
@@ -1863,7 +1916,8 @@
         code_ +=
             "  flexbuffers::Reference {{FIELD_NAME}}_flexbuffer_root()"
             " const {";
-        // Both Data() and size() are const-methods, therefore call order doesn't matter.
+        // Both Data() and size() are const-methods, therefore call order
+        // doesn't matter.
         code_ +=
             "    return flexbuffers::GetRoot({{FIELD_NAME}}()->Data(), "
             "{{FIELD_NAME}}()->size());";
@@ -1871,9 +1925,7 @@
       }
 
       // Generate a comparison function for this field if it is a key.
-      if (field.key) {
-        GenKeyFieldMethods(field);
-      }
+      if (field.key) { GenKeyFieldMethods(field); }
     }
 
     // Generate a verifier function that can check a buffer from an untrusted
@@ -2064,8 +2116,9 @@
 
     // Generate a CreateXDirect function with vector types as parameters
     if (has_string_or_vector_fields) {
-      code_ += "inline flatbuffers::Offset<{{STRUCT_NAME}}> "
-               "Create{{STRUCT_NAME}}Direct(";
+      code_ +=
+          "inline flatbuffers::Offset<{{STRUCT_NAME}}> "
+          "Create{{STRUCT_NAME}}Direct(";
       code_ += "    flatbuffers::FlatBufferBuilder &_fbb\\";
       for (auto it = struct_def.fields.vec.begin();
            it != struct_def.fields.vec.end(); ++it) {
@@ -2128,17 +2181,22 @@
   std::string GenUnionUnpackVal(const FieldDef &afield,
                                 const char *vec_elem_access,
                                 const char *vec_type_access) {
-    return afield.value.type.enum_def->name +
-           "Union::UnPack(" + "_e" + vec_elem_access + ", " +
-           EscapeKeyword(afield.name + UnionTypeFieldSuffix()) +
-           "()" + vec_type_access + ", _resolver)";
+    return afield.value.type.enum_def->name + "Union::UnPack(" + "_e" +
+           vec_elem_access + ", " +
+           EscapeKeyword(afield.name + UnionTypeFieldSuffix()) + "()" +
+           vec_type_access + ", _resolver)";
   }
 
   std::string GenUnpackVal(const Type &type, const std::string &val,
                            bool invector, const FieldDef &afield) {
     switch (type.base_type) {
       case BASE_TYPE_STRING: {
-        return val + "->str()";
+        if (FlexibleStringConstructor(&afield)) {
+          return NativeString(&afield) + "(" + val + "->c_str(), " + val +
+                 "->size())";
+        } else {
+          return val + "->str()";
+        }
       }
       case BASE_TYPE_STRUCT: {
         const auto name = WrapInNameSpace(*type.struct_def);
@@ -2210,26 +2268,29 @@
           code += "//vector resolver, " + PtrType(&field) + "\n";
           code += "if (_resolver) ";
           code += "(*_resolver)";
-          code += "(reinterpret_cast<void **>(&_o->" + name + "[_i]" + access + "), ";
+          code += "(reinterpret_cast<void **>(&_o->" + name + "[_i]" + access +
+                  "), ";
           code += "static_cast<flatbuffers::hash_value_t>(" + indexing + "));";
           if (PtrType(&field) == "naked") {
             code += " else ";
             code += "_o->" + name + "[_i]" + access + " = nullptr";
           } else {
-            //code += " else ";
-            //code += "_o->" + name + "[_i]" + access + " = " + GenTypeNativePtr(cpp_type->constant, &field, true) + "();";
+            // code += " else ";
+            // code += "_o->" + name + "[_i]" + access + " = " +
+            // GenTypeNativePtr(cpp_type->constant, &field, true) + "();";
             code += "/* else do nothing */";
           }
         } else {
           code += "_o->" + name + "[_i]" + access + " = ";
-          code +=
-            GenUnpackVal(field.value.type.VectorType(), indexing, true, field);
+          code += GenUnpackVal(field.value.type.VectorType(), indexing, true,
+                               field);
         }
         code += "; } }";
         break;
       }
       case BASE_TYPE_UTYPE: {
-        FLATBUFFERS_ASSERT(union_field->value.type.base_type == BASE_TYPE_UNION);
+        FLATBUFFERS_ASSERT(union_field->value.type.base_type ==
+                           BASE_TYPE_UNION);
         // Generate code that sets the union type, of the form:
         //   _o->field.type = _e;
         code += "_o->" + union_field->name + ".type = _e;";
@@ -2260,8 +2321,9 @@
             code += " else ";
             code += "_o->" + Name(field) + " = nullptr;";
           } else {
-            //code += " else ";
-            //code += "_o->" + Name(field) + " = " + GenTypeNativePtr(cpp_type->constant, &field, true) + "();";
+            // code += " else ";
+            // code += "_o->" + Name(field) + " = " +
+            // GenTypeNativePtr(cpp_type->constant, &field, true) + "();";
             code += "/* else do nothing */;";
           }
         } else {
@@ -2286,7 +2348,8 @@
     } else {
       value += Name(field);
     }
-    if (field.value.type.base_type != BASE_TYPE_VECTOR && field.attributes.Lookup("cpp_type")) {
+    if (field.value.type.base_type != BASE_TYPE_VECTOR &&
+        field.attributes.Lookup("cpp_type")) {
       auto type = GenTypeBasic(field.value.type, false);
       value =
           "_rehasher ? "
@@ -2294,7 +2357,6 @@
           type + ">((*_rehasher)(" + value + GenPtrGet(field) + ")) : 0";
     }
 
-
     std::string code;
     switch (field.value.type.base_type) {
       // String fields are of the form:
@@ -2332,7 +2394,20 @@
         auto vector_type = field.value.type.VectorType();
         switch (vector_type.base_type) {
           case BASE_TYPE_STRING: {
-            code += "_fbb.CreateVectorOfStrings(" + value + ")";
+            if (NativeString(&field) == "std::string") {
+              code += "_fbb.CreateVectorOfStrings(" + value + ")";
+            } else {
+              // Use by-function serialization to emulate
+              // CreateVectorOfStrings(); this works also with non-std strings.
+              code +=
+                  "_fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>"
+                  " ";
+              code += "(" + value + ".size(), ";
+              code += "[](size_t i, _VectorArgs *__va) { ";
+              code +=
+                  "return __va->__fbb->CreateString(__va->_" + value + "[i]);";
+              code += " }, &_va )";
+            }
             break;
           }
           case BASE_TYPE_STRUCT: {
@@ -2710,9 +2785,7 @@
       }
 
       // Generate a comparison function for this field if it is a key.
-      if (field.key) {
-        GenKeyFieldMethods(field);
-      }
+      if (field.key) { GenKeyFieldMethods(field); }
     }
     code_.SetValue("NATIVE_NAME", Name(struct_def));
     GenOperatorNewDelete(struct_def);
diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp
index 4a40293..7a68e8a 100644
--- a/src/idl_gen_go.cpp
+++ b/src/idl_gen_go.cpp
@@ -620,6 +620,27 @@
     code += "}\n\n";
   }
 
+  // Mutate an element of a vector of scalars.
+  void MutateElementOfVectorOfNonStruct(const StructDef &struct_def,
+                                        const FieldDef &field,
+                                        std::string *code_ptr) {
+    std::string &code = *code_ptr;
+    auto vectortype = field.value.type.VectorType();
+    std::string type = MakeCamel(GenTypeBasic(vectortype));
+    std::string setter = "rcv._tab.Mutate" + type;
+    GenReceiver(struct_def, code_ptr);
+    code += " Mutate" + MakeCamel(field.name);
+    code += "(j int, n " + TypeName(field) + ") bool ";
+    code += OffsetPrefix(field);
+    code += "\t\ta := rcv._tab.Vector(o)\n";
+    code += "\t\treturn " + setter + "(";
+    code += "a+flatbuffers.UOffsetT(j*";
+    code += NumToString(InlineSize(vectortype)) + "), n)\n";
+    code += "\t}\n";
+    code += "\treturn false\n";
+    code += "}\n\n";
+  }
+
   // Generate a struct field setter, conditioned on its child type(s).
   void GenStructMutator(const StructDef &struct_def, const FieldDef &field,
                         std::string *code_ptr) {
@@ -630,6 +651,10 @@
       } else {
         MutateScalarFieldOfTable(struct_def, field, code_ptr);
       }
+    } else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
+      if (IsScalar(field.value.type.element)) {
+        MutateElementOfVectorOfNonStruct(struct_def, field, code_ptr);
+      }
     }
   }
 
diff --git a/src/idl_gen_js_ts.cpp b/src/idl_gen_js_ts.cpp
index ff248fc..9b7942b 100644
--- a/src/idl_gen_js_ts.cpp
+++ b/src/idl_gen_js_ts.cpp
@@ -168,7 +168,8 @@
     for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
          ++it) {
       auto &enum_def = **it;
-      GenEnum(enum_def, enum_code_ptr, exports_code_ptr, reexports);
+      GenEnum(enum_def, enum_code_ptr, exports_code_ptr, reexports, false);
+      GenEnum(enum_def, enum_code_ptr, exports_code_ptr, reexports, true);
     }
   }
 
@@ -322,12 +323,16 @@
 
   // Generate an enum declaration and an enum string lookup table.
   void GenEnum(EnumDef &enum_def, std::string *code_ptr,
-               std::string *exports_ptr, reexport_map &reexports) {
+               std::string *exports_ptr, reexport_map &reexports,
+               bool reverse) {
     if (enum_def.generated) return;
+    if (reverse && lang_.language == IDLOptions::kTs) return;  // FIXME.
     std::string &code = *code_ptr;
     std::string &exports = *exports_ptr;
-    GenDocComment(enum_def.doc_comment, code_ptr, "@enum");
+    GenDocComment(enum_def.doc_comment, code_ptr,
+                  reverse ? "@enum {string}" : "@enum {number}");
     std::string ns = GetNameSpace(enum_def);
+    std::string enum_def_name = enum_def.name + (reverse ? "Name" : "");
     if (lang_.language == IDLOptions::kTs) {
       if (!ns.empty()) { code += "export namespace " + ns + "{\n"; }
       code += "export enum " + enum_def.name + "{\n";
@@ -335,15 +340,15 @@
       if (enum_def.defined_namespace->components.empty()) {
         code += "var ";
         if (parser_.opts.use_goog_js_export_format) {
-          exports += "goog.exportSymbol('" + enum_def.name + "', " +
+          exports += "goog.exportSymbol('" + enum_def_name + "', " +
                      enum_def.name + ");\n";
         } else if (parser_.opts.use_ES6_js_export_format) {
-          exports += "export {" + enum_def.name + "};\n";
+          exports += "export {" + enum_def_name + "};\n";
         } else {
-          exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
+          exports += "this." + enum_def_name + " = " + enum_def_name + ";\n";
         }
       }
-      code += WrapInNameSpace(enum_def) + " = {\n";
+      code += WrapInNameSpace(enum_def) + (reverse ? "Name" : "") + " = {\n";
     }
     for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
          ++it) {
@@ -354,18 +359,14 @@
       }
 
       // Generate mapping between EnumName: EnumValue(int)
-      code += "  " + ev.name;
-      code += lang_.language == IDLOptions::kTs ? "= " : ": ";
-      code += NumToString(ev.value);
-
-      if (lang_.language == IDLOptions::kJs) {
-        // In pure Javascript, generate mapping between EnumValue(int):
-        // 'EnumName' so enums can be looked up by their ID.
-        code += ", ";
-
-        code += NumToString(ev.value);
+      if (reverse) {
+        code += "  " + NumToString(ev.value);
         code += lang_.language == IDLOptions::kTs ? "= " : ": ";
         code += "'" + ev.name + "'";
+      } else {
+        code += "  " + ev.name;
+        code += lang_.language == IDLOptions::kTs ? "= " : ": ";
+        code += NumToString(ev.value);
       }
 
       code += (it + 1) != enum_def.vals.vec.end() ? ",\n" : "\n";
diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp
index fd6a066..e8ecbbc 100644
--- a/src/idl_gen_rust.cpp
+++ b/src/idl_gen_rust.cpp
@@ -586,7 +586,7 @@
     GenComment(enum_def.doc_comment);
     code_ += "#[allow(non_camel_case_types)]";
     code_ += "#[repr({{BASE_TYPE}})]";
-    code_ += "#[derive(Clone, Copy, PartialEq, Debug)]";
+    code_ += "#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]";
     code_ += "pub enum " + Name(enum_def) + " {";
 
     int64_t anyv = 0;
@@ -1027,11 +1027,11 @@
       }
       case ftVectorOfTable: {
         const auto typname = WrapInNameSpace(*type.struct_def);
-        return WrapInOptionIfNotRequired("flatbuffers::Vector<flatbuffers::ForwardsUOffset<" + \
+        return WrapInOptionIfNotRequired("flatbuffers::Vector<" + lifetime + ", flatbuffers::ForwardsUOffset<" + \
                typname + "<" + lifetime + ">>>", field.required);
       }
       case ftVectorOfString: {
-        return WrapInOptionIfNotRequired("flatbuffers::Vector<flatbuffers::ForwardsUOffset<&" + \
+        return WrapInOptionIfNotRequired("flatbuffers::Vector<" + lifetime + ", flatbuffers::ForwardsUOffset<&" + \
                lifetime + " str>>", field.required);
       }
       case ftVectorOfUnionValue: {
@@ -1150,8 +1150,6 @@
   // Generate an accessor struct, builder struct, and create function for a
   // table.
   void GenTable(const StructDef &struct_def) {
-    GenComment(struct_def.doc_comment);
-
     code_.SetValue("STRUCT_NAME", Name(struct_def));
     code_.SetValue("OFFSET_TYPELABEL", Name(struct_def) + "Offset");
     code_.SetValue("STRUCT_NAME_SNAKECASE", MakeSnakeCase(Name(struct_def)));
@@ -1161,6 +1159,9 @@
     code_ += "pub enum {{OFFSET_TYPELABEL}} {}";
     code_ += "#[derive(Copy, Clone, Debug, PartialEq)]";
     code_ += "";
+
+    GenComment(struct_def.doc_comment);
+
     code_ += "pub struct {{STRUCT_NAME}}<'a> {";
     code_ += "  pub _tab: flatbuffers::Table<'a>,";
     code_ += "}";
@@ -1748,8 +1749,6 @@
 
   void GenNamespaceImports(const int white_spaces) {
       std::string indent = std::string(white_spaces, ' ');
-      code_ += indent + "#![allow(dead_code)]";
-      code_ += indent + "#![allow(unused_imports)]";
       code_ += "";
       code_ += indent + "use std::mem;";
       code_ += indent + "use std::cmp::Ordering;";
@@ -1791,6 +1790,7 @@
     // open namespace parts to reach the ns namespace
     // in the previous example, E, then F, then G are opened
     for (auto j = common_prefix_size; j != new_size; ++j) {
+      code_ += "#[allow(unused_imports, dead_code)]";
       code_ += "pub mod " + MakeSnakeCase(ns->components[j]) + " {";
       // Generate local namespace imports.
       GenNamespaceImports(2);
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index 3a8165f..583538f 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -374,7 +374,7 @@
                   "illegal Unicode sequence (unpaired high surrogate)");
             }
             // reset if non-printable
-            attr_is_trivial_ascii_string_ &= check_in_range(*cursor_, ' ', '~');
+            attr_is_trivial_ascii_string_ &= check_ascii_range(*cursor_, ' ', '~');
 
             attribute_ += *cursor_++;
           }
@@ -476,7 +476,7 @@
         }
         std::string ch;
         ch = c;
-        if (false == check_in_range(c, ' ', '~')) ch = "code: " + NumToString(c);
+        if (false == check_ascii_range(c, ' ', '~')) ch = "code: " + NumToString(c);
         return Error("illegal character: " + ch);
     }
   }
@@ -650,7 +650,7 @@
   } else if (type.base_type == BASE_TYPE_VECTOR &&
              type.element == BASE_TYPE_UNION) {
     // Only cpp, js and ts supports the union vector feature so far.
-    if (!SupportsVectorOfUnions()) {
+    if (!SupportsAdvancedUnionFeatures()) {
       return Error(
           "Vectors of unions are not yet supported in all "
           "the specified programming languages.");
@@ -843,25 +843,45 @@
 
 CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
                                    size_t parent_fieldn,
-                                   const StructDef *parent_struct_def) {
+                                   const StructDef *parent_struct_def,
+                                   uoffset_t count,
+                                   bool inside_vector) {
   switch (val.type.base_type) {
     case BASE_TYPE_UNION: {
       FLATBUFFERS_ASSERT(field);
       std::string constant;
+      Vector<uint8_t> *vector_of_union_types = nullptr;
       // Find corresponding type field we may have already parsed.
-      for (auto elem = field_stack_.rbegin();
-           elem != field_stack_.rbegin() + parent_fieldn; ++elem) {
+      for (auto elem = field_stack_.rbegin() + count;
+           elem != field_stack_.rbegin() + parent_fieldn + count; ++elem) {
         auto &type = elem->second->value.type;
-        if (type.base_type == BASE_TYPE_UTYPE &&
-            type.enum_def == val.type.enum_def) {
-          constant = elem->first.constant;
-          break;
+        if (type.enum_def == val.type.enum_def) {
+          if (inside_vector) {
+            if (type.base_type == BASE_TYPE_VECTOR &&
+                type.element == BASE_TYPE_UTYPE) {
+              // Vector of union type field.
+              uoffset_t offset;
+              ECHECK(atot(elem->first.constant.c_str(), *this, &offset));
+              vector_of_union_types = reinterpret_cast<Vector<uint8_t> *>(
+                                        builder_.GetCurrentBufferPointer() +
+                                        builder_.GetSize() - offset);
+              break;
+            }
+          } else {
+            if (type.base_type == BASE_TYPE_UTYPE) {
+              // Union type field.
+              constant = elem->first.constant;
+              break;
+            }
+          }
         }
       }
-      if (constant.empty()) {
+      if (constant.empty() && !inside_vector) {
         // We haven't seen the type field yet. Sadly a lot of JSON writers
         // output these in alphabetical order, meaning it comes after this
         // value. So we scan past the value to find it, then come back here.
+        // We currently don't do this for vectors of unions because the
+        // scanning/serialization logic would get very complicated.
         auto type_name = field->name + UnionTypeFieldSuffix();
         FLATBUFFERS_ASSERT(parent_struct_def);
         auto type_field = parent_struct_def->fields.Lookup(type_name);
@@ -876,18 +896,25 @@
         } else {
           EXPECT(kTokenIdentifier);
         }
-        if (next_name != type_name)
-          return Error("missing type field after this union value: " +
-                       type_name);
-        EXPECT(':');
-        Value type_val = type_field->value;
-        ECHECK(ParseAnyValue(type_val, type_field, 0, nullptr));
-        constant = type_val.constant;
-        // Got the information we needed, now rewind:
-        *static_cast<ParserState *>(this) = backup;
+        if (next_name == type_name) {
+          EXPECT(':');
+          Value type_val = type_field->value;
+          ECHECK(ParseAnyValue(type_val, type_field, 0, nullptr, 0));
+          constant = type_val.constant;
+          // Got the information we needed, now rewind:
+          *static_cast<ParserState *>(this) = backup;
+        }
+      }
+      if (constant.empty() && !vector_of_union_types) {
+        return Error("missing type field for this union value: " +
+                     field->name);
       }
       uint8_t enum_idx;
-      ECHECK(atot(constant.c_str(), *this, &enum_idx));
+      if (vector_of_union_types) {
+        enum_idx = vector_of_union_types->Get(count);
+      } else {
+        ECHECK(atot(constant.c_str(), *this, &enum_idx));
+      }
       auto enum_val = val.type.enum_def->ReverseLookup(enum_idx);
       if (!enum_val) return Error("illegal type id for: " + field->name);
       if (enum_val->union_type.base_type == BASE_TYPE_STRUCT) {
@@ -915,7 +942,7 @@
     }
     case BASE_TYPE_VECTOR: {
       uoffset_t off;
-      ECHECK(ParseVector(val.type.VectorType(), &off));
+      ECHECK(ParseVector(val.type.VectorType(), &off, field, parent_fieldn));
       val.constant = NumToString(off);
       break;
     }
@@ -1026,7 +1053,7 @@
                   ParseNestedFlatbuffer(val, field, fieldn, struct_def_inner));
             } else {
               ECHECK(Recurse([&]() {
-                return ParseAnyValue(val, field, fieldn, struct_def_inner);
+                return ParseAnyValue(val, field, fieldn, struct_def_inner, 0);
               }));
             }
             // Hardcoded insertion-sort with error-check.
@@ -1144,7 +1171,7 @@
 }
 
 template <typename F>
-CheckedError Parser::ParseVectorDelimiters(size_t &count, F body) {
+CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) {
   EXPECT('[');
   for (;;) {
     if ((!opts.strict_json || !count) && Is(']')) break;
@@ -1157,12 +1184,15 @@
   return NoError();
 }
 
-CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) {
-  size_t count = 0;
-  auto err = ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
+CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
+                                 FieldDef *field, size_t fieldn) {
+  uoffset_t count = 0;
+  auto err = ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
     Value val;
     val.type = type;
-    ECHECK(Recurse([&]() { return ParseAnyValue(val, nullptr, 0, nullptr); }));
+    ECHECK(Recurse([&]() {
+      return ParseAnyValue(val, field, fieldn, nullptr, count, true);
+    }));
     field_stack_.push_back(std::make_pair(val, nullptr));
     return NoError();
   });
@@ -1170,7 +1200,7 @@
 
   builder_.StartVector(count * InlineSize(type) / InlineAlignment(type),
                        InlineAlignment(type));
-  for (size_t i = 0; i < count; i++) {
+  for (uoffset_t i = 0; i < count; i++) {
     // start at the back, since we're building the data backwards.
     auto &val = field_stack_.back().first;
     switch (val.type.base_type) {
@@ -1201,7 +1231,7 @@
                                            size_t fieldn,
                                            const StructDef *parent_struct_def) {
   if (token_ == '[') {  // backwards compat for 'legacy' ubyte buffers
-    ECHECK(ParseAnyValue(val, field, fieldn, parent_struct_def));
+    ECHECK(ParseAnyValue(val, field, fieldn, parent_struct_def, 0));
   } else {
     auto cursor_at_value_begin = cursor_;
     ECHECK(SkipAnyJsonValue());
@@ -1757,11 +1787,12 @@
   return NoError();
 }
 
-bool Parser::SupportsVectorOfUnions() const {
+bool Parser::SupportsAdvancedUnionFeatures() const {
   return opts.lang_to_generate != 0 &&
          (opts.lang_to_generate & ~(IDLOptions::kCpp | IDLOptions::kJs |
                                     IDLOptions::kTs | IDLOptions::kPhp |
-                                    IDLOptions::kJava | IDLOptions::kCSharp)) == 0;
+                                    IDLOptions::kJava | IDLOptions::kCSharp |
+                                    IDLOptions::kBinary)) == 0;
 }
 
 Namespace *Parser::UniqueNamespace(Namespace *ns) {
@@ -2284,8 +2315,8 @@
           });
     }
     case '[': {
-      size_t count = 0;
-      return ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
+      uoffset_t count = 0;
+      return ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
         return Recurse([&]() { return SkipAnyJsonValue(); });
       });
     }
@@ -2321,8 +2352,8 @@
     }
     case '[': {
       auto start = builder->StartVector();
-      size_t count = 0;
-      ECHECK(ParseVectorDelimiters(count, [&](size_t &) -> CheckedError {
+      uoffset_t count = 0;
+      ECHECK(ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
         return ParseFlexBufferValue(builder);
       }));
       builder->EndVector(start, false, false);
@@ -2454,7 +2485,7 @@
       for (auto val_it = enum_def.vals.vec.begin();
            val_it != enum_def.vals.vec.end(); ++val_it) {
         auto &val = **val_it;
-        if (!SupportsVectorOfUnions() && val.union_type.struct_def &&
+        if (!SupportsAdvancedUnionFeatures() && val.union_type.struct_def &&
             val.union_type.struct_def->fixed)
           return Error(
               "only tables can be union elements in the generated language: " +
diff --git a/tests/MyGame/Example/Monster.go b/tests/MyGame/Example/Monster.go
index 30b64a0..1eedc5e 100644
--- a/tests/MyGame/Example/Monster.go
+++ b/tests/MyGame/Example/Monster.go
@@ -99,6 +99,15 @@
 	return nil
 }
 
+func (rcv *Monster) MutateInventory(j int, n byte) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateByte(a+flatbuffers.UOffsetT(j*1), n)
+	}
+	return false
+}
+
 func (rcv *Monster) Color() Color {
 	o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
 	if o != 0 {
@@ -230,6 +239,15 @@
 	return nil
 }
 
+func (rcv *Monster) MutateTestnestedflatbuffer(j int, n byte) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(30))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateByte(a+flatbuffers.UOffsetT(j*1), n)
+	}
+	return false
+}
+
 func (rcv *Monster) Testempty(obj *Stat) *Stat {
 	o := flatbuffers.UOffsetT(rcv._tab.Offset(32))
 	if o != 0 {
@@ -368,6 +386,15 @@
 	return 0
 }
 
+func (rcv *Monster) MutateTestarrayofbools(j int, n bool) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(52))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateBool(a+flatbuffers.UOffsetT(j*1), n)
+	}
+	return false
+}
+
 func (rcv *Monster) Testf() float32 {
 	o := flatbuffers.UOffsetT(rcv._tab.Offset(54))
 	if o != 0 {
@@ -465,6 +492,15 @@
 	return nil
 }
 
+func (rcv *Monster) MutateFlex(j int, n byte) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(64))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateByte(a+flatbuffers.UOffsetT(j*1), n)
+	}
+	return false
+}
+
 func (rcv *Monster) Test5(obj *Test, j int) bool {
 	o := flatbuffers.UOffsetT(rcv._tab.Offset(66))
 	if o != 0 {
@@ -501,6 +537,15 @@
 	return 0
 }
 
+func (rcv *Monster) MutateVectorOfLongs(j int, n int64) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(68))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateInt64(a+flatbuffers.UOffsetT(j*8), n)
+	}
+	return false
+}
+
 func (rcv *Monster) VectorOfDoubles(j int) float64 {
 	o := flatbuffers.UOffsetT(rcv._tab.Offset(70))
 	if o != 0 {
@@ -518,6 +563,15 @@
 	return 0
 }
 
+func (rcv *Monster) MutateVectorOfDoubles(j int, n float64) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(70))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateFloat64(a+flatbuffers.UOffsetT(j*8), n)
+	}
+	return false
+}
+
 func (rcv *Monster) ParentNamespaceTest(obj *MyGame.InParentNamespace) *MyGame.InParentNamespace {
 	o := flatbuffers.UOffsetT(rcv._tab.Offset(72))
 	if o != 0 {
@@ -580,6 +634,15 @@
 	return 0
 }
 
+func (rcv *Monster) MutateVectorOfWeakReferences(j int, n uint64) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(78))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateUint64(a+flatbuffers.UOffsetT(j*8), n)
+	}
+	return false
+}
+
 func (rcv *Monster) VectorOfStrongReferrables(obj *Referrable, j int) bool {
 	o := flatbuffers.UOffsetT(rcv._tab.Offset(80))
 	if o != 0 {
@@ -629,6 +692,15 @@
 	return 0
 }
 
+func (rcv *Monster) MutateVectorOfCoOwningReferences(j int, n uint64) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(84))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateUint64(a+flatbuffers.UOffsetT(j*8), n)
+	}
+	return false
+}
+
 func (rcv *Monster) NonOwningReference() uint64 {
 	o := flatbuffers.UOffsetT(rcv._tab.Offset(86))
 	if o != 0 {
@@ -658,6 +730,15 @@
 	return 0
 }
 
+func (rcv *Monster) MutateVectorOfNonOwningReferences(j int, n uint64) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(88))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateUint64(a+flatbuffers.UOffsetT(j*8), n)
+	}
+	return false
+}
+
 func (rcv *Monster) AnyUniqueType() byte {
 	o := flatbuffers.UOffsetT(rcv._tab.Offset(90))
 	if o != 0 {
@@ -717,6 +798,15 @@
 	return 0
 }
 
+func (rcv *Monster) MutateVectorOfEnums(j int, n Color) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(98))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateInt8(a+flatbuffers.UOffsetT(j*1), n)
+	}
+	return false
+}
+
 func MonsterStart(builder *flatbuffers.Builder) {
 	builder.StartObject(48)
 }
diff --git a/tests/MyGame/Example/TypeAliases.go b/tests/MyGame/Example/TypeAliases.go
index f3d6b84..d017b5b 100644
--- a/tests/MyGame/Example/TypeAliases.go
+++ b/tests/MyGame/Example/TypeAliases.go
@@ -163,6 +163,15 @@
 	return 0
 }
 
+func (rcv *TypeAliases) MutateV8(j int, n int8) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(24))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateInt8(a+flatbuffers.UOffsetT(j*1), n)
+	}
+	return false
+}
+
 func (rcv *TypeAliases) Vf64(j int) float64 {
 	o := flatbuffers.UOffsetT(rcv._tab.Offset(26))
 	if o != 0 {
@@ -180,6 +189,15 @@
 	return 0
 }
 
+func (rcv *TypeAliases) MutateVf64(j int, n float64) bool {
+	o := flatbuffers.UOffsetT(rcv._tab.Offset(26))
+	if o != 0 {
+		a := rcv._tab.Vector(o)
+		return rcv._tab.MutateFloat64(a+flatbuffers.UOffsetT(j*8), n)
+	}
+	return false
+}
+
 func TypeAliasesStart(builder *flatbuffers.Builder) {
 	builder.StartObject(12)
 }
diff --git a/tests/RustTest.sh b/tests/RustTest.sh
index ac050c4..0a3974b 100755
--- a/tests/RustTest.sh
+++ b/tests/RustTest.sh
@@ -15,8 +15,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if [[ "$1" == "mips-unknown-linux-gnu" ]]; then
+    TARGET_FLAG="--target mips-unknown-linux-gnu"
+    export CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_LINKER=mips-linux-gnu-gcc
+    export CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_RUNNER="qemu-mips -L /usr/mips-linux-gnu"
+fi
+
 cd ./rust_usage_test
-cargo test -- --quiet
+cargo test $TARGET_FLAG -- --quiet
 TEST_RESULT=$?
 if [[ $TEST_RESULT  == 0 ]]; then
     echo "OK: Rust tests passed."
@@ -25,7 +31,7 @@
     exit 1
 fi
 
-cargo run --bin=alloc_check
+cargo run $TARGET_FLAG --bin=alloc_check
 TEST_RESULT=$?
 if [[ $TEST_RESULT  == 0 ]]; then
     echo "OK: Rust heap alloc test passed."
@@ -34,4 +40,4 @@
     exit 1
 fi
 
-cargo bench
+cargo bench $TARGET_FLAG
diff --git a/tests/docker/languages/Dockerfile.testing.rust.big_endian.1_30_1 b/tests/docker/languages/Dockerfile.testing.rust.big_endian.1_30_1
new file mode 100644
index 0000000..f2e93f4
--- /dev/null
+++ b/tests/docker/languages/Dockerfile.testing.rust.big_endian.1_30_1
@@ -0,0 +1,15 @@
+FROM rust:1.30.1-slim-stretch as base
+RUN apt -qq update -y && apt -qq install -y \
+    gcc-mips-linux-gnu \
+    libexpat1 \
+    libmagic1 \
+    libmpdec2 \
+    libreadline7 \
+    qemu-user
+RUN rustup target add mips-unknown-linux-gnu
+WORKDIR /code
+ADD . .
+RUN cp flatc_debian_stretch flatc
+WORKDIR /code/tests
+RUN rustc --version
+RUN ./RustTest.sh mips-unknown-linux-gnu
diff --git a/tests/go_test.go b/tests/go_test.go
index ec6aaef..0c16da9 100644
--- a/tests/go_test.go
+++ b/tests/go_test.go
@@ -334,6 +334,7 @@
 		testcase{"Pos.Test2'", func() bool { return monster.Pos(nil).Test2() == int8(2) }},
 		testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).A() == int16(5) }},
 		testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).B() == int8(6) }},
+		testcase{"Inventory[2]", func() bool { return monster.Inventory(2) == byte(2) }},
 	}
 
 	testMutability := []testcase{
@@ -347,6 +348,7 @@
 		testcase{"Pos.Test2", func() bool { return monster.Pos(nil).MutateTest2(20) }},
 		testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).MutateA(50) }},
 		testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).MutateB(60) }},
+		testcase{"Inventory[2]", func() bool { return monster.MutateInventory(2, 200) }},
 	}
 
 	testForMutatedValues := []testcase{
@@ -360,6 +362,7 @@
 		testcase{"Pos.Test2'", func() bool { return monster.Pos(nil).Test2() == int8(20) }},
 		testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).A() == int16(50) }},
 		testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).B() == int8(60) }},
+		testcase{"Inventory[2]", func() bool { return monster.Inventory(2) == byte(200) }},
 	}
 
 	// make sure original values are okay
@@ -412,6 +415,7 @@
 	monster.Pos(nil).MutateTest2(2)
 	monster.Pos(nil).Test3(nil).MutateA(5)
 	monster.Pos(nil).Test3(nil).MutateB(6)
+	monster.MutateInventory(2, 2)
 
 	for _, t := range testForOriginalValues {
 		if !t.testfn() {
diff --git a/tests/monster_extra_generated.h b/tests/monster_extra_generated.h
index ac316d6..8599b81 100644
--- a/tests/monster_extra_generated.h
+++ b/tests/monster_extra_generated.h
@@ -12,6 +12,7 @@
 struct MonsterExtraT;
 
 bool operator==(const MonsterExtraT &lhs, const MonsterExtraT &rhs);
+bool operator!=(const MonsterExtraT &lhs, const MonsterExtraT &rhs);
 
 inline const flatbuffers::TypeTable *MonsterExtraTypeTable();
 
@@ -43,6 +44,11 @@
       (lhs.testd_ninf == rhs.testd_ninf);
 }
 
+inline bool operator!=(const MonsterExtraT &lhs, const MonsterExtraT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct MonsterExtra FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef MonsterExtraT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h
index f8c82f5..f98e86b 100644
--- a/tests/monster_test_generated.h
+++ b/tests/monster_test_generated.h
@@ -45,21 +45,31 @@
 }  // namespace Example
 
 bool operator==(const InParentNamespaceT &lhs, const InParentNamespaceT &rhs);
+bool operator!=(const InParentNamespaceT &lhs, const InParentNamespaceT &rhs);
 namespace Example2 {
 
 bool operator==(const MonsterT &lhs, const MonsterT &rhs);
+bool operator!=(const MonsterT &lhs, const MonsterT &rhs);
 }  // namespace Example2
 
 namespace Example {
 
 bool operator==(const Test &lhs, const Test &rhs);
+bool operator!=(const Test &lhs, const Test &rhs);
 bool operator==(const TestSimpleTableWithEnumT &lhs, const TestSimpleTableWithEnumT &rhs);
+bool operator!=(const TestSimpleTableWithEnumT &lhs, const TestSimpleTableWithEnumT &rhs);
 bool operator==(const Vec3 &lhs, const Vec3 &rhs);
+bool operator!=(const Vec3 &lhs, const Vec3 &rhs);
 bool operator==(const Ability &lhs, const Ability &rhs);
+bool operator!=(const Ability &lhs, const Ability &rhs);
 bool operator==(const StatT &lhs, const StatT &rhs);
+bool operator!=(const StatT &lhs, const StatT &rhs);
 bool operator==(const ReferrableT &lhs, const ReferrableT &rhs);
+bool operator!=(const ReferrableT &lhs, const ReferrableT &rhs);
 bool operator==(const MonsterT &lhs, const MonsterT &rhs);
+bool operator!=(const MonsterT &lhs, const MonsterT &rhs);
 bool operator==(const TypeAliasesT &lhs, const TypeAliasesT &rhs);
+bool operator!=(const TypeAliasesT &lhs, const TypeAliasesT &rhs);
 
 }  // namespace Example
 
@@ -123,7 +133,7 @@
 
 inline const char *EnumNameColor(Color e) {
   if (e < Color_Red || e > Color_Blue) return "";
-  const size_t index = static_cast<int>(e) - static_cast<int>(Color_Red);
+  const size_t index = static_cast<size_t>(e) - static_cast<size_t>(Color_Red);
   return EnumNamesColor()[index];
 }
 
@@ -159,7 +169,7 @@
 
 inline const char *EnumNameAny(Any e) {
   if (e < Any_NONE || e > Any_MyGame_Example2_Monster) return "";
-  const size_t index = static_cast<int>(e);
+  const size_t index = static_cast<size_t>(e);
   return EnumNamesAny()[index];
 }
 
@@ -260,6 +270,11 @@
     }
   }
 }
+
+inline bool operator!=(const AnyUnion &lhs, const AnyUnion &rhs) {
+    return !(lhs == rhs);
+}
+
 bool VerifyAny(flatbuffers::Verifier &verifier, const void *obj, Any type);
 bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
 
@@ -295,7 +310,7 @@
 
 inline const char *EnumNameAnyUniqueAliases(AnyUniqueAliases e) {
   if (e < AnyUniqueAliases_NONE || e > AnyUniqueAliases_M2) return "";
-  const size_t index = static_cast<int>(e);
+  const size_t index = static_cast<size_t>(e);
   return EnumNamesAnyUniqueAliases()[index];
 }
 
@@ -396,6 +411,11 @@
     }
   }
 }
+
+inline bool operator!=(const AnyUniqueAliasesUnion &lhs, const AnyUniqueAliasesUnion &rhs) {
+    return !(lhs == rhs);
+}
+
 bool VerifyAnyUniqueAliases(flatbuffers::Verifier &verifier, const void *obj, AnyUniqueAliases type);
 bool VerifyAnyUniqueAliasesVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
 
@@ -431,7 +451,7 @@
 
 inline const char *EnumNameAnyAmbiguousAliases(AnyAmbiguousAliases e) {
   if (e < AnyAmbiguousAliases_NONE || e > AnyAmbiguousAliases_M3) return "";
-  const size_t index = static_cast<int>(e);
+  const size_t index = static_cast<size_t>(e);
   return EnumNamesAnyAmbiguousAliases()[index];
 }
 
@@ -505,6 +525,11 @@
     }
   }
 }
+
+inline bool operator!=(const AnyAmbiguousAliasesUnion &lhs, const AnyAmbiguousAliasesUnion &rhs) {
+    return !(lhs == rhs);
+}
+
 bool VerifyAnyAmbiguousAliases(flatbuffers::Verifier &verifier, const void *obj, AnyAmbiguousAliases type);
 bool VerifyAnyAmbiguousAliasesVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
 
@@ -545,6 +570,11 @@
       (lhs.b() == rhs.b());
 }
 
+inline bool operator!=(const Test &lhs, const Test &rhs) {
+    return !(lhs == rhs);
+}
+
+
 FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Vec3 FLATBUFFERS_FINAL_CLASS {
  private:
   float x_;
@@ -624,6 +654,11 @@
       (lhs.test3() == rhs.test3());
 }
 
+inline bool operator!=(const Vec3 &lhs, const Vec3 &rhs) {
+    return !(lhs == rhs);
+}
+
+
 FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Ability FLATBUFFERS_FINAL_CLASS {
  private:
   uint32_t id_;
@@ -664,6 +699,11 @@
       (lhs.distance() == rhs.distance());
 }
 
+inline bool operator!=(const Ability &lhs, const Ability &rhs) {
+    return !(lhs == rhs);
+}
+
+
 }  // namespace Example
 
 struct InParentNamespaceT : public flatbuffers::NativeTable {
@@ -676,6 +716,11 @@
   return true;
 }
 
+inline bool operator!=(const InParentNamespaceT &lhs, const InParentNamespaceT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct InParentNamespace FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef InParentNamespaceT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
@@ -725,6 +770,11 @@
   return true;
 }
 
+inline bool operator!=(const MonsterT &lhs, const MonsterT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef MonsterT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
@@ -779,6 +829,11 @@
       (lhs.color == rhs.color);
 }
 
+inline bool operator!=(const TestSimpleTableWithEnumT &lhs, const TestSimpleTableWithEnumT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef TestSimpleTableWithEnumT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
@@ -849,6 +904,11 @@
       (lhs.count == rhs.count);
 }
 
+inline bool operator!=(const StatT &lhs, const StatT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef StatT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
@@ -954,6 +1014,11 @@
       (lhs.id == rhs.id);
 }
 
+inline bool operator!=(const ReferrableT &lhs, const ReferrableT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct Referrable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef ReferrableT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
@@ -1128,6 +1193,11 @@
       (lhs.vector_of_enums == rhs.vector_of_enums);
 }
 
+inline bool operator!=(const MonsterT &lhs, const MonsterT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 /// an example documentation comment: monster object
 struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef MonsterT NativeTableType;
@@ -2040,6 +2110,11 @@
       (lhs.vf64 == rhs.vf64);
 }
 
+inline bool operator!=(const TypeAliasesT &lhs, const TypeAliasesT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct TypeAliases FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef TypeAliasesT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
diff --git a/tests/monster_test_generated.js b/tests/monster_test_generated.js
index 730bb21..cfa82d1 100644
--- a/tests/monster_test_generated.js
+++ b/tests/monster_test_generated.js
@@ -25,42 +25,81 @@
 MyGame.OtherNameSpace = MyGame.OtherNameSpace || {};
 
 /**
- * @enum
+ * @enum {number}
  */
 MyGame.Example.Color = {
-  Red: 1, 1: 'Red',
-  Green: 2, 2: 'Green',
-  Blue: 8, 8: 'Blue'
+  Red: 1,
+  Green: 2,
+  Blue: 8
 };
 
 /**
- * @enum
+ * @enum {string}
+ */
+MyGame.Example.ColorName = {
+  1: 'Red',
+  2: 'Green',
+  8: 'Blue'
+};
+
+/**
+ * @enum {number}
  */
 MyGame.Example.Any = {
-  NONE: 0, 0: 'NONE',
-  Monster: 1, 1: 'Monster',
-  TestSimpleTableWithEnum: 2, 2: 'TestSimpleTableWithEnum',
-  MyGame_Example2_Monster: 3, 3: 'MyGame_Example2_Monster'
+  NONE: 0,
+  Monster: 1,
+  TestSimpleTableWithEnum: 2,
+  MyGame_Example2_Monster: 3
 };
 
 /**
- * @enum
+ * @enum {string}
+ */
+MyGame.Example.AnyName = {
+  0: 'NONE',
+  1: 'Monster',
+  2: 'TestSimpleTableWithEnum',
+  3: 'MyGame_Example2_Monster'
+};
+
+/**
+ * @enum {number}
  */
 MyGame.Example.AnyUniqueAliases = {
-  NONE: 0, 0: 'NONE',
-  M: 1, 1: 'M',
-  T: 2, 2: 'T',
-  M2: 3, 3: 'M2'
+  NONE: 0,
+  M: 1,
+  T: 2,
+  M2: 3
 };
 
 /**
- * @enum
+ * @enum {string}
+ */
+MyGame.Example.AnyUniqueAliasesName = {
+  0: 'NONE',
+  1: 'M',
+  2: 'T',
+  3: 'M2'
+};
+
+/**
+ * @enum {number}
  */
 MyGame.Example.AnyAmbiguousAliases = {
-  NONE: 0, 0: 'NONE',
-  M1: 1, 1: 'M1',
-  M2: 2, 2: 'M2',
-  M3: 3, 3: 'M3'
+  NONE: 0,
+  M1: 1,
+  M2: 2,
+  M3: 3
+};
+
+/**
+ * @enum {string}
+ */
+MyGame.Example.AnyAmbiguousAliasesName = {
+  0: 'NONE',
+  1: 'M1',
+  2: 'M2',
+  3: 'M3'
 };
 
 /**
diff --git a/tests/monster_test_generated.rs b/tests/monster_test_generated.rs
index a538eae..558985e 100644
--- a/tests/monster_test_generated.rs
+++ b/tests/monster_test_generated.rs
@@ -1,8 +1,6 @@
 // automatically generated by the FlatBuffers compiler, do not modify
 
 
-#![allow(dead_code)]
-#![allow(unused_imports)]
 
 use std::mem;
 use std::cmp::Ordering;
@@ -10,9 +8,8 @@
 extern crate flatbuffers;
 use self::flatbuffers::EndianScalar;
 
+#[allow(unused_imports, dead_code)]
 pub mod my_game {
-  #![allow(dead_code)]
-  #![allow(unused_imports)]
 
   use std::mem;
   use std::cmp::Ordering;
@@ -83,9 +80,8 @@
   }
 }
 
+#[allow(unused_imports, dead_code)]
 pub mod example_2 {
-  #![allow(dead_code)]
-  #![allow(unused_imports)]
 
   use std::mem;
   use std::cmp::Ordering;
@@ -158,9 +154,8 @@
 
 }  // pub mod Example2
 
+#[allow(unused_imports, dead_code)]
 pub mod example {
-  #![allow(dead_code)]
-  #![allow(unused_imports)]
 
   use std::mem;
   use std::cmp::Ordering;
@@ -170,7 +165,7 @@
 
 #[allow(non_camel_case_types)]
 #[repr(i8)]
-#[derive(Clone, Copy, PartialEq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 pub enum Color {
   Red = 1,
   Green = 2,
@@ -238,7 +233,7 @@
 
 #[allow(non_camel_case_types)]
 #[repr(u8)]
-#[derive(Clone, Copy, PartialEq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 pub enum Any {
   NONE = 0,
   Monster = 1,
@@ -305,7 +300,7 @@
 pub struct AnyUnionTableOffset {}
 #[allow(non_camel_case_types)]
 #[repr(u8)]
-#[derive(Clone, Copy, PartialEq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 pub enum AnyUniqueAliases {
   NONE = 0,
   M = 1,
@@ -372,7 +367,7 @@
 pub struct AnyUniqueAliasesUnionTableOffset {}
 #[allow(non_camel_case_types)]
 #[repr(u8)]
-#[derive(Clone, Copy, PartialEq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 pub enum AnyAmbiguousAliases {
   NONE = 0,
   M1 = 1,
@@ -920,10 +915,10 @@
   }
 }
 
-/// an example documentation comment: monster object
 pub enum MonsterOffset {}
 #[derive(Copy, Clone, Debug, PartialEq)]
 
+/// an example documentation comment: monster object
 pub struct Monster<'a> {
   pub _tab: flatbuffers::Table<'a>,
 }
@@ -1095,13 +1090,13 @@
     self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<Test>>>(Monster::VT_TEST4, None).map(|v| v.safe_slice() )
   }
   #[inline]
-  pub fn testarrayofstring(&self) -> Option<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&'a str>>> {
+  pub fn testarrayofstring(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>> {
     self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&'a str>>>>(Monster::VT_TESTARRAYOFSTRING, None)
   }
   /// an example documentation comment: this will end up in the generated code
   /// multiline too
   #[inline]
-  pub fn testarrayoftables(&self) -> Option<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Monster<'a>>>> {
+  pub fn testarrayoftables(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Monster<'a>>>> {
     self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Monster<'a>>>>>(Monster::VT_TESTARRAYOFTABLES, None)
   }
   #[inline]
@@ -1178,7 +1173,7 @@
     self._tab.get::<f32>(Monster::VT_TESTF3, Some(0.0)).unwrap()
   }
   #[inline]
-  pub fn testarrayofstring2(&self) -> Option<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&'a str>>> {
+  pub fn testarrayofstring2(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>> {
     self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&'a str>>>>(Monster::VT_TESTARRAYOFSTRING2, None)
   }
   #[inline]
@@ -1206,7 +1201,7 @@
     self._tab.get::<flatbuffers::ForwardsUOffset<super::InParentNamespace<'a>>>(Monster::VT_PARENT_NAMESPACE_TEST, None)
   }
   #[inline]
-  pub fn vector_of_referrables(&self) -> Option<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Referrable<'a>>>> {
+  pub fn vector_of_referrables(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Referrable<'a>>>> {
     self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Referrable<'a>>>>>(Monster::VT_VECTOR_OF_REFERRABLES, None)
   }
   #[inline]
@@ -1218,7 +1213,7 @@
     self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, u64>>>(Monster::VT_VECTOR_OF_WEAK_REFERENCES, None)
   }
   #[inline]
-  pub fn vector_of_strong_referrables(&self) -> Option<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Referrable<'a>>>> {
+  pub fn vector_of_strong_referrables(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Referrable<'a>>>> {
     self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Referrable<'a>>>>>(Monster::VT_VECTOR_OF_STRONG_REFERRABLES, None)
   }
   #[inline]
diff --git a/tests/monster_test_generated.ts b/tests/monster_test_generated.ts
index 89cf6f1..3784a19 100644
--- a/tests/monster_test_generated.ts
+++ b/tests/monster_test_generated.ts
@@ -1,7 +1,7 @@
 // automatically generated by the FlatBuffers compiler, do not modify
 
 /**
- * @enum
+ * @enum {number}
  */
 export namespace MyGame.Example{
 export enum Color{
@@ -11,7 +11,7 @@
 }};
 
 /**
- * @enum
+ * @enum {number}
  */
 export namespace MyGame.Example{
 export enum Any{
@@ -22,7 +22,7 @@
 }};
 
 /**
- * @enum
+ * @enum {number}
  */
 export namespace MyGame.Example{
 export enum AnyUniqueAliases{
@@ -33,7 +33,7 @@
 }};
 
 /**
- * @enum
+ * @enum {number}
  */
 export namespace MyGame.Example{
 export enum AnyAmbiguousAliases{
diff --git a/tests/namespace_test/namespace_test1_generated.h b/tests/namespace_test/namespace_test1_generated.h
index d26bf43..12b344d 100644
--- a/tests/namespace_test/namespace_test1_generated.h
+++ b/tests/namespace_test/namespace_test1_generated.h
@@ -46,7 +46,7 @@
 
 inline const char *EnumNameEnumInNestedNS(EnumInNestedNS e) {
   if (e < EnumInNestedNS_A || e > EnumInNestedNS_C) return "";
-  const size_t index = static_cast<int>(e);
+  const size_t index = static_cast<size_t>(e);
   return EnumNamesEnumInNestedNS()[index];
 }
 
diff --git a/tests/namespace_test/namespace_test1_generated.js b/tests/namespace_test/namespace_test1_generated.js
index d318f22..3eaaace 100644
--- a/tests/namespace_test/namespace_test1_generated.js
+++ b/tests/namespace_test/namespace_test1_generated.js
@@ -13,12 +13,21 @@
 NamespaceA.NamespaceB = NamespaceA.NamespaceB || {};
 
 /**
- * @enum
+ * @enum {number}
  */
 NamespaceA.NamespaceB.EnumInNestedNS = {
-  A: 0, 0: 'A',
-  B: 1, 1: 'B',
-  C: 2, 2: 'C'
+  A: 0,
+  B: 1,
+  C: 2
+};
+
+/**
+ * @enum {string}
+ */
+NamespaceA.NamespaceB.EnumInNestedNSName = {
+  0: 'A',
+  1: 'B',
+  2: 'C'
 };
 
 /**
diff --git a/tests/namespace_test/namespace_test1_generated.rs b/tests/namespace_test/namespace_test1_generated.rs
index 7fb6c97..3ffcde4 100644
--- a/tests/namespace_test/namespace_test1_generated.rs
+++ b/tests/namespace_test/namespace_test1_generated.rs
@@ -1,8 +1,6 @@
 // automatically generated by the FlatBuffers compiler, do not modify
 
 
-#![allow(dead_code)]
-#![allow(unused_imports)]
 
 use std::mem;
 use std::cmp::Ordering;
@@ -10,18 +8,16 @@
 extern crate flatbuffers;
 use self::flatbuffers::EndianScalar;
 
+#[allow(unused_imports, dead_code)]
 pub mod namespace_a {
-  #![allow(dead_code)]
-  #![allow(unused_imports)]
 
   use std::mem;
   use std::cmp::Ordering;
 
   extern crate flatbuffers;
   use self::flatbuffers::EndianScalar;
+#[allow(unused_imports, dead_code)]
 pub mod namespace_b {
-  #![allow(dead_code)]
-  #![allow(unused_imports)]
 
   use std::mem;
   use std::cmp::Ordering;
@@ -31,7 +27,7 @@
 
 #[allow(non_camel_case_types)]
 #[repr(i8)]
-#[derive(Clone, Copy, PartialEq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 pub enum EnumInNestedNS {
   A = 0,
   B = 1,
diff --git a/tests/namespace_test/namespace_test1_generated.ts b/tests/namespace_test/namespace_test1_generated.ts
index 46bd20e..33dbb6d 100644
--- a/tests/namespace_test/namespace_test1_generated.ts
+++ b/tests/namespace_test/namespace_test1_generated.ts
@@ -1,7 +1,7 @@
 // automatically generated by the FlatBuffers compiler, do not modify
 
 /**
- * @enum
+ * @enum {number}
  */
 export namespace NamespaceA.NamespaceB{
 export enum EnumInNestedNS{
diff --git a/tests/namespace_test/namespace_test2_generated.rs b/tests/namespace_test/namespace_test2_generated.rs
index c2e7021..3c04c0f 100644
--- a/tests/namespace_test/namespace_test2_generated.rs
+++ b/tests/namespace_test/namespace_test2_generated.rs
@@ -1,8 +1,6 @@
 // automatically generated by the FlatBuffers compiler, do not modify
 
 
-#![allow(dead_code)]
-#![allow(unused_imports)]
 
 use std::mem;
 use std::cmp::Ordering;
@@ -10,9 +8,8 @@
 extern crate flatbuffers;
 use self::flatbuffers::EndianScalar;
 
+#[allow(unused_imports, dead_code)]
 pub mod namespace_a {
-  #![allow(dead_code)]
-  #![allow(unused_imports)]
 
   use std::mem;
   use std::cmp::Ordering;
@@ -198,9 +195,8 @@
 
 }  // pub mod NamespaceA
 
+#[allow(unused_imports, dead_code)]
 pub mod namespace_c {
-  #![allow(dead_code)]
-  #![allow(unused_imports)]
 
   use std::mem;
   use std::cmp::Ordering;
diff --git a/tests/rust_usage_test/benches/flatbuffers_benchmarks.rs b/tests/rust_usage_test/benches/flatbuffers_benchmarks.rs
index 3ad45c2..2c6be1f 100644
--- a/tests/rust_usage_test/benches/flatbuffers_benchmarks.rs
+++ b/tests/rust_usage_test/benches/flatbuffers_benchmarks.rs
@@ -20,6 +20,7 @@
 
 extern crate flatbuffers;
 
+#[allow(dead_code, unused_imports)]
 #[path = "../../monster_test_generated.rs"]
 mod monster_test_generated;
 pub use monster_test_generated::my_game;
diff --git a/tests/rust_usage_test/bin/alloc_check.rs b/tests/rust_usage_test/bin/alloc_check.rs
index 7fb3ef3..ae1039c 100644
--- a/tests/rust_usage_test/bin/alloc_check.rs
+++ b/tests/rust_usage_test/bin/alloc_check.rs
@@ -28,6 +28,7 @@
 
 // import the flatbuffers generated code:
 extern crate flatbuffers;
+#[allow(dead_code, unused_imports)]
 #[path = "../../monster_test_generated.rs"]
 mod monster_test_generated;
 pub use monster_test_generated::my_game;
diff --git a/tests/rust_usage_test/bin/monster_example.rs b/tests/rust_usage_test/bin/monster_example.rs
index e415a95..3c9a0a0 100644
--- a/tests/rust_usage_test/bin/monster_example.rs
+++ b/tests/rust_usage_test/bin/monster_example.rs
@@ -1,5 +1,6 @@
 extern crate flatbuffers;
 
+#[allow(dead_code, unused_imports)]
 #[path = "../../monster_test_generated.rs"]
 mod monster_test_generated;
 pub use monster_test_generated::my_game;
diff --git a/tests/rust_usage_test/tests/integration_test.rs b/tests/rust_usage_test/tests/integration_test.rs
index f4db4ff..0dace96 100644
--- a/tests/rust_usage_test/tests/integration_test.rs
+++ b/tests/rust_usage_test/tests/integration_test.rs
@@ -19,6 +19,7 @@
 
 extern crate flatbuffers;
 
+#[allow(dead_code, unused_imports)]
 #[path = "../../monster_test_generated.rs"]
 mod monster_test_generated;
 pub use monster_test_generated::my_game;
@@ -780,7 +781,13 @@
 
         const N: u64 = 20;
 
-        fn prop<T: PartialEq + ::std::fmt::Debug + Copy + flatbuffers::EndianScalar + flatbuffers::Push>(xs: Vec<T>) {
+        fn prop<T>(xs: Vec<T>)
+        where
+            T: for<'a> flatbuffers::Follow<'a, Inner = T>
+                + flatbuffers::EndianScalar
+                + flatbuffers::Push
+                + ::std::fmt::Debug,
+        {
             use flatbuffers::Follow;
 
             let mut b = flatbuffers::FlatBufferBuilder::new();
@@ -793,8 +800,12 @@
 
             let buf = b.finished_data();
 
-            let got = <flatbuffers::ForwardsUOffset<&[T]>>::follow(buf, 0);
-            assert_eq!(got, &xs[..]);
+            let got = <flatbuffers::ForwardsUOffset<flatbuffers::Vector<T>>>::follow(&buf[..], 0);
+            let mut result_vec: Vec<T> = Vec::with_capacity(got.len());
+            for i in 0..got.len() {
+                result_vec.push(got.get(i));
+            }
+            assert_eq!(result_vec, xs);
         }
 
         #[test]
@@ -1139,8 +1150,10 @@
             let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0);
 
             for i in 0..xs.len() {
-                let v = tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(i as flatbuffers::VOffsetT), None);
-                assert_eq!(v, Some(&xs[i][..]));
+                let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(i as flatbuffers::VOffsetT), None);
+                assert!(v.is_some());
+                let v2 = v.unwrap().safe_slice();
+                assert_eq!(v2, &xs[i][..]);
             }
         }
         prop(vec![vec![1,2,3]]);
@@ -1187,7 +1200,13 @@
 
         const N: u64 = 20;
 
-        fn prop<'a, T: flatbuffers::Follow<'a> + 'a + flatbuffers::EndianScalar + flatbuffers::Push + ::std::fmt::Debug>(vecs: Vec<Vec<T>>) {
+        fn prop<T>(vecs: Vec<Vec<T>>)
+        where
+            T: for<'a> flatbuffers::Follow<'a, Inner = T>
+                + flatbuffers::EndianScalar
+                + flatbuffers::Push
+                + ::std::fmt::Debug,
+        {
             use flatbuffers::field_index_to_field_offset as fi2fo;
             use flatbuffers::Follow;
 
@@ -1218,10 +1237,14 @@
             let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0);
 
             for i in 0..vecs.len() {
-                let got = tab.get::<flatbuffers::ForwardsUOffset<&[T]>>(fi2fo(i as flatbuffers::VOffsetT), None);
+                let got = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<T>>>(fi2fo(i as flatbuffers::VOffsetT), None);
                 assert!(got.is_some());
                 let got2 = got.unwrap();
-                assert_eq!(&vecs[i][..], got2);
+                let mut got3: Vec<T> = Vec::with_capacity(got2.len());
+                for i in 0..got2.len() {
+                    got3.push(got2.get(i));
+                }
+                assert_eq!(vecs[i], got3);
             }
         }
 
@@ -1631,6 +1654,43 @@
     use flatbuffers::Follow;
     use flatbuffers::field_index_to_field_offset as fi2fo;
 
+    // Define a test struct to use in a few tests. This replicates the work that the code generator
+    // would normally do when defining a FlatBuffer struct. For reference, compare the following
+    // `FooStruct` code with the code generated for the `Vec3` struct in
+    // `../../monster_test_generated.rs`.
+    use flatbuffers::EndianScalar;
+    #[derive(Copy, Clone, Debug, PartialEq)]
+    #[repr(C, packed)]
+    struct FooStruct {
+        a: i8,
+        b: u8,
+        c: i16,
+    }
+    impl FooStruct {
+        fn new(_a: i8, _b: u8, _c: i16) -> Self {
+            FooStruct {
+                a: _a.to_little_endian(),
+                b: _b.to_little_endian(),
+                c: _c.to_little_endian(),
+            }
+        }
+    }
+    impl flatbuffers::SafeSliceAccess for FooStruct {}
+    impl<'a> flatbuffers::Follow<'a> for FooStruct {
+        type Inner = &'a FooStruct;
+        #[inline(always)]
+        fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
+            <&'a FooStruct>::follow(buf, loc)
+        }
+    }
+    impl<'a> flatbuffers::Follow<'a> for &'a FooStruct {
+        type Inner = &'a FooStruct;
+        #[inline(always)]
+        fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
+            flatbuffers::follow_cast_ref::<FooStruct>(buf, loc)
+        }
+    }
+
     #[test]
     fn to_u8() {
         let vec: Vec<u8> = vec![255, 3];
@@ -1662,8 +1722,8 @@
     #[test]
     fn to_byte_slice() {
         let vec: Vec<u8> = vec![255, 255, 255, 255, 4, 0, 0, 0, 1, 2, 3, 4];
-        let off: flatbuffers::FollowStart<&[u8]> = flatbuffers::FollowStart::new();
-        assert_eq!(off.self_follow(&vec[..], 4), &[1, 2, 3, 4][..]);
+        let off: flatbuffers::FollowStart<flatbuffers::Vector<u8>> = flatbuffers::FollowStart::new();
+        assert_eq!(off.self_follow(&vec[..], 4).safe_slice(), &[1, 2, 3, 4][..]);
     }
 
     #[test]
@@ -1676,8 +1736,8 @@
     #[test]
     fn to_byte_string_zero_teriminated() {
         let vec: Vec<u8> = vec![255, 255, 255, 255, 3, 0, 0, 0, 1, 2, 3, 0];
-        let off: flatbuffers::FollowStart<&[u8]> = flatbuffers::FollowStart::new();
-        assert_eq!(off.self_follow(&vec[..], 4), &[1, 2, 3][..]);
+        let off: flatbuffers::FollowStart<flatbuffers::Vector<u8>> = flatbuffers::FollowStart::new();
+        assert_eq!(off.self_follow(&vec[..], 4).safe_slice(), &[1, 2, 3][..]);
     }
 
     #[cfg(target_endian = "little")]
@@ -1699,24 +1759,9 @@
 
     #[test]
     fn to_struct() {
-        #[derive(Copy, Clone, Debug, PartialEq)]
-        #[repr(C, packed)]
-        struct FooStruct {
-            a: i8,
-            b: u8,
-            c: i16,
-        }
-        impl<'a> flatbuffers::Follow<'a> for &'a FooStruct {
-            type Inner = &'a FooStruct;
-            #[inline(always)]
-            fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
-                flatbuffers::follow_cast_ref::<FooStruct>(buf, loc)
-            }
-        }
-
         let vec: Vec<u8> = vec![255, 255, 255, 255, 1, 2, 3, 4];
         let off: flatbuffers::FollowStart<&FooStruct> = flatbuffers::FollowStart::new();
-        assert_eq!(*off.self_follow(&vec[..], 4), FooStruct{a: 1, b: 2, c: 1027});
+        assert_eq!(*off.self_follow(&vec[..], 4), FooStruct::new(1, 2, 1027));
     }
 
     #[test]
@@ -1729,48 +1774,17 @@
 
     #[test]
     fn to_slice_of_struct_elements() {
-        #[derive(Copy, Clone, Debug, PartialEq)]
-        #[repr(C, packed)]
-        struct FooStruct {
-            a: i8,
-            b: u8,
-            c: i16,
-        }
-        impl flatbuffers::SafeSliceAccess for FooStruct {}
-        impl<'a> flatbuffers::Follow<'a> for FooStruct {
-            type Inner = &'a FooStruct;
-            #[inline(always)]
-            fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
-                flatbuffers::follow_cast_ref::<FooStruct>(buf, loc)
-            }
-        }
-
         let buf: Vec<u8> = vec![1, 0, 0, 0, /* struct data */ 1, 2, 3, 4];
         let fs: flatbuffers::FollowStart<flatbuffers::Vector<FooStruct>> = flatbuffers::FollowStart::new();
-        assert_eq!(fs.self_follow(&buf[..], 0).safe_slice(), &vec![FooStruct{a: 1, b: 2, c: 1027}][..]);
+        assert_eq!(fs.self_follow(&buf[..], 0).safe_slice(), &vec![FooStruct::new(1, 2, 1027)][..]);
     }
 
     #[test]
     fn to_vector_of_struct_elements() {
-        #[derive(Copy, Clone, Debug, PartialEq)]
-        #[repr(C, packed)]
-        struct FooStruct {
-            a: i8,
-            b: u8,
-            c: i16,
-        }
-        impl<'a> flatbuffers::Follow<'a> for FooStruct {
-            type Inner = &'a FooStruct;
-            #[inline(always)]
-            fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
-                flatbuffers::follow_cast_ref::<FooStruct>(buf, loc)
-            }
-        }
-
         let buf: Vec<u8> = vec![1, 0, 0, 0, /* struct data */ 1, 2, 3, 4];
         let fs: flatbuffers::FollowStart<flatbuffers::Vector<FooStruct>> = flatbuffers::FollowStart::new();
         assert_eq!(fs.self_follow(&buf[..], 0).len(), 1);
-        assert_eq!(fs.self_follow(&buf[..], 0).get(0), &FooStruct{a: 1, b: 2, c: 1027});
+        assert_eq!(fs.self_follow(&buf[..], 0).get(0), &FooStruct::new(1, 2, 1027));
     }
 
     #[test]
@@ -1858,7 +1872,8 @@
         ];
         let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
         assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), None), Some("moo"));
-        assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), None), Some(&vec![109, 111, 111][..]));
+        let byte_vec = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), None).unwrap().safe_slice();
+        assert_eq!(byte_vec, &vec![109, 111, 111][..]);
         let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), None).unwrap();
         assert_eq!(v.len(), 3);
         assert_eq!(v.get(0), 109);
@@ -1879,7 +1894,10 @@
         ];
         let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
         assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), Some("abc")), Some("abc"));
-        assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..]));
+        #[cfg(target_endian = "little")]
+        {
+            assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..]));
+        }
 
         let default_vec_buf: Vec<u8> = vec![3, 0, 0, 0, 70, 71, 72, 0];
         let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0);
@@ -1904,7 +1922,10 @@
         ];
         let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
         assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), Some("abc")), Some("abc"));
-        assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..]));
+        #[cfg(target_endian = "little")]
+        {
+            assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..]));
+        }
 
         let default_vec_buf: Vec<u8> = vec![3, 0, 0, 0, 70, 71, 72, 0];
         let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0);
diff --git a/tests/test.cpp b/tests/test.cpp
index 003f825..6da1dff 100644
--- a/tests/test.cpp
+++ b/tests/test.cpp
@@ -1508,6 +1508,27 @@
 }
 
 void IntegerBoundaryTest() {
+  // Check numerical compatibility with non-C++ languages.
+  // By the C++ standard, std::numerical_limits<int64_t>::min() == -9223372036854775807 (-2^63+1) or less*
+  // The Flatbuffers grammar and most of the languages (C#, Java, Rust) expect
+  // that minimum values are: -128, -32768,.., -9223372036854775808.
+  // Since C++20, static_cast<int64>(0x8000000000000000ULL) is well-defined two's complement cast.
+  // Therefore -9223372036854775808 should be valid negative value.
+  TEST_EQ(flatbuffers::numeric_limits<int8_t>::min(), -128);
+  TEST_EQ(flatbuffers::numeric_limits<int8_t>::max(), 127);
+  TEST_EQ(flatbuffers::numeric_limits<int16_t>::min(), -32768);
+  TEST_EQ(flatbuffers::numeric_limits<int16_t>::max(), 32767);
+  TEST_EQ(flatbuffers::numeric_limits<int32_t>::min() + 1, -2147483647);
+  TEST_EQ(flatbuffers::numeric_limits<int32_t>::max(), 2147483647ULL);
+  TEST_EQ(flatbuffers::numeric_limits<int64_t>::min() + 1LL,
+          -9223372036854775807LL);
+  TEST_EQ(flatbuffers::numeric_limits<int64_t>::max(), 9223372036854775807ULL);
+  TEST_EQ(flatbuffers::numeric_limits<uint8_t>::max(), 255);
+  TEST_EQ(flatbuffers::numeric_limits<uint16_t>::max(), 65535);
+  TEST_EQ(flatbuffers::numeric_limits<uint32_t>::max(), 4294967295ULL);
+  TEST_EQ(flatbuffers::numeric_limits<uint64_t>::max(),
+          18446744073709551615ULL);
+
   TEST_EQ(TestValue<int8_t>("{ Y:127 }", "byte"), 127);
   TEST_EQ(TestValue<int8_t>("{ Y:-128 }", "byte"), -128);
   TEST_EQ(TestValue<uint8_t>("{ Y:255 }", "ubyte"), 255);
@@ -1517,15 +1538,15 @@
   TEST_EQ(TestValue<uint16_t>("{ Y:65535 }", "ushort"), 65535);
   TEST_EQ(TestValue<uint16_t>("{ Y:0 }", "ushort"), 0);
   TEST_EQ(TestValue<int32_t>("{ Y:2147483647 }", "int"), 2147483647);
-  TEST_EQ(TestValue<int32_t>("{ Y:-2147483648 }", "int"), (-2147483647 - 1));
+  TEST_EQ(TestValue<int32_t>("{ Y:-2147483648 }", "int") + 1, -2147483647);
   TEST_EQ(TestValue<uint32_t>("{ Y:4294967295 }", "uint"), 4294967295);
   TEST_EQ(TestValue<uint32_t>("{ Y:0 }", "uint"), 0);
   TEST_EQ(TestValue<int64_t>("{ Y:9223372036854775807 }", "long"),
-          9223372036854775807);
-  TEST_EQ(TestValue<int64_t>("{ Y:-9223372036854775808 }", "long"),
-          (-9223372036854775807 - 1));
+          9223372036854775807LL);
+  TEST_EQ(TestValue<int64_t>("{ Y:-9223372036854775808 }", "long") + 1LL,
+          -9223372036854775807LL);
   TEST_EQ(TestValue<uint64_t>("{ Y:18446744073709551615 }", "ulong"),
-          18446744073709551615U);
+          18446744073709551615ULL);
   TEST_EQ(TestValue<uint64_t>("{ Y:0 }", "ulong"), 0);
   TEST_EQ(TestValue<uint64_t>("{ Y: 18446744073709551615 }", "uint64"),
           18446744073709551615ULL);
@@ -2017,17 +2038,20 @@
 }
 
 void UnionVectorTest() {
-  // load FlatBuffer fbs schema.
-  // TODO: load a JSON file with such a vector when JSON support is ready.
-  std::string schemafile;
+  // load FlatBuffer fbs schema and json.
+  std::string schemafile, jsonfile;
   TEST_EQ(flatbuffers::LoadFile(
-              (test_data_path + "union_vector/union_vector.fbs").c_str(), false,
-              &schemafile),
+              (test_data_path + "union_vector/union_vector.fbs").c_str(),
+              false, &schemafile),
+          true);
+  TEST_EQ(flatbuffers::LoadFile(
+              (test_data_path + "union_vector/union_vector.json").c_str(),
+              false, &jsonfile),
           true);
 
   // parse schema.
   flatbuffers::IDLOptions idl_opts;
-  idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kCpp;
+  idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
   flatbuffers::Parser parser(idl_opts);
   TEST_EQ(parser.Parse(schemafile.c_str()), true);
 
@@ -2093,6 +2117,13 @@
 
   TestMovie(flat_movie);
 
+  // Also test the JSON we loaded above.
+  TEST_EQ(parser.Parse(jsonfile.c_str()), true);
+  auto jbuf = parser.builder_.GetBufferPointer();
+  flatbuffers::Verifier jverifier(jbuf, parser.builder_.GetSize());
+  TEST_EQ(VerifyMovieBuffer(jverifier), true);
+  TestMovie(GetMovie(jbuf));
+
   auto movie_object = flat_movie->UnPack();
   TEST_EQ(movie_object->main_character.AsRapunzel()->hair_length(), 6);
   TEST_EQ(movie_object->characters[0].AsBelle()->books_read(), 7);
@@ -2150,6 +2181,13 @@
       "    \"Unused\"\n"
       "  ]\n"
       "}");
+
+  flatbuffers::Parser parser2(idl_opts);
+  TEST_EQ(parser2.Parse("struct Bool { b:bool; }"
+                        "union Any { Bool }"
+                        "table Root { a:Any; }"
+                        "root_type Root;"), true);
+  TEST_EQ(parser2.Parse("{a_type:Bool,a:{b:true}}"), true);
 }
 
 void ConformTest() {
@@ -2406,19 +2444,25 @@
   MonsterT a;
   MonsterT b;
   TEST_EQ(b == a, true);
+  TEST_EQ(b != a, false);
 
   b.mana = 33;
   TEST_EQ(b == a, false);
+  TEST_EQ(b != a, true);
   b.mana = 150;
   TEST_EQ(b == a, true);
+  TEST_EQ(b != a, false);
 
   b.inventory.push_back(3);
   TEST_EQ(b == a, false);
+  TEST_EQ(b != a, true);
   b.inventory.clear();
   TEST_EQ(b == a, true);
+  TEST_EQ(b != a, false);
 
   b.test.type = Any_Monster;
   TEST_EQ(b == a, false);
+  TEST_EQ(b != a, true);
 }
 
 // For testing any binaries, e.g. from fuzzing.
diff --git a/tests/union_vector/union_vector.json b/tests/union_vector/union_vector.json
new file mode 100644
index 0000000..af0c9cb
--- /dev/null
+++ b/tests/union_vector/union_vector.json
@@ -0,0 +1,26 @@
+{
+  "main_character_type": "Rapunzel",
+  "main_character": {
+    "hair_length": 6
+  },
+  "characters_type": [
+    "Belle",
+    "MuLan",
+    "BookFan",
+    "Other",
+    "Unused"
+  ],
+  "characters": [
+    {
+      "books_read": 7
+    },
+    {
+      "sword_attack_damage": 5
+    },
+    {
+      "books_read": 2
+    },
+    "Other",
+    "Unused"
+  ]
+}
diff --git a/tests/union_vector/union_vector_generated.h b/tests/union_vector/union_vector_generated.h
index 8629d4e..962c98b 100644
--- a/tests/union_vector/union_vector_generated.h
+++ b/tests/union_vector/union_vector_generated.h
@@ -17,9 +17,13 @@
 struct MovieT;
 
 bool operator==(const AttackerT &lhs, const AttackerT &rhs);
+bool operator!=(const AttackerT &lhs, const AttackerT &rhs);
 bool operator==(const Rapunzel &lhs, const Rapunzel &rhs);
+bool operator!=(const Rapunzel &lhs, const Rapunzel &rhs);
 bool operator==(const BookReader &lhs, const BookReader &rhs);
+bool operator!=(const BookReader &lhs, const BookReader &rhs);
 bool operator==(const MovieT &lhs, const MovieT &rhs);
+bool operator!=(const MovieT &lhs, const MovieT &rhs);
 
 inline const flatbuffers::TypeTable *AttackerTypeTable();
 
@@ -70,7 +74,7 @@
 
 inline const char *EnumNameCharacter(Character e) {
   if (e < Character_NONE || e > Character_Unused) return "";
-  const size_t index = static_cast<int>(e);
+  const size_t index = static_cast<size_t>(e);
   return EnumNamesCharacter()[index];
 }
 
@@ -180,6 +184,11 @@
     }
   }
 }
+
+inline bool operator!=(const CharacterUnion &lhs, const CharacterUnion &rhs) {
+    return !(lhs == rhs);
+}
+
 bool VerifyCharacter(flatbuffers::Verifier &verifier, const void *obj, Character type);
 bool VerifyCharacterVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
 
@@ -208,6 +217,11 @@
       (lhs.hair_length() == rhs.hair_length());
 }
 
+inline bool operator!=(const Rapunzel &lhs, const Rapunzel &rhs) {
+    return !(lhs == rhs);
+}
+
+
 FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) BookReader FLATBUFFERS_FINAL_CLASS {
  private:
   int32_t books_read_;
@@ -233,6 +247,11 @@
       (lhs.books_read() == rhs.books_read());
 }
 
+inline bool operator!=(const BookReader &lhs, const BookReader &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct AttackerT : public flatbuffers::NativeTable {
   typedef Attacker TableType;
   int32_t sword_attack_damage;
@@ -246,6 +265,11 @@
       (lhs.sword_attack_damage == rhs.sword_attack_damage);
 }
 
+inline bool operator!=(const AttackerT &lhs, const AttackerT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct Attacker FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef AttackerT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
@@ -312,6 +336,11 @@
       (lhs.characters == rhs.characters);
 }
 
+inline bool operator!=(const MovieT &lhs, const MovieT &rhs) {
+    return !(lhs == rhs);
+}
+
+
 struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef MovieT NativeTableType;
   static const flatbuffers::TypeTable *MiniReflectTypeTable() {
diff --git a/tests/union_vector/union_vector_generated.js b/tests/union_vector/union_vector_generated.js
index 5c1a579..380da2d 100644
--- a/tests/union_vector/union_vector_generated.js
+++ b/tests/union_vector/union_vector_generated.js
@@ -1,16 +1,29 @@
 // automatically generated by the FlatBuffers compiler, do not modify
 
 /**
- * @enum
+ * @enum {number}
  */
 var Character = {
-  NONE: 0, 0: 'NONE',
-  MuLan: 1, 1: 'MuLan',
-  Rapunzel: 2, 2: 'Rapunzel',
-  Belle: 3, 3: 'Belle',
-  BookFan: 4, 4: 'BookFan',
-  Other: 5, 5: 'Other',
-  Unused: 6, 6: 'Unused'
+  NONE: 0,
+  MuLan: 1,
+  Rapunzel: 2,
+  Belle: 3,
+  BookFan: 4,
+  Other: 5,
+  Unused: 6
+};
+
+/**
+ * @enum {string}
+ */
+var CharacterName = {
+  0: 'NONE',
+  1: 'MuLan',
+  2: 'Rapunzel',
+  3: 'Belle',
+  4: 'BookFan',
+  5: 'Other',
+  6: 'Unused'
 };
 
 /**
@@ -459,6 +472,7 @@
 
 // Exports for Node.js and RequireJS
 this.Character = Character;
+this.CharacterName = CharacterName;
 this.Attacker = Attacker;
 this.Rapunzel = Rapunzel;
 this.BookReader = BookReader;
diff --git a/tests/union_vector/union_vector_generated.ts b/tests/union_vector/union_vector_generated.ts
index 608f8fd..44ffbcf 100644
--- a/tests/union_vector/union_vector_generated.ts
+++ b/tests/union_vector/union_vector_generated.ts
@@ -1,7 +1,7 @@
 // automatically generated by the FlatBuffers compiler, do not modify
 
 /**
- * @enum
+ * @enum {number}
  */
 export enum Character{
   NONE= 0,