Squashed 'third_party/flatbuffers/' changes from e5f331db9..bc44fad35

bc44fad35 UnPackTo disable merge by default (#7527)
4fca4dc60 [TS/JS] Move TS tests to dedicated folder and deps upgrade (#7508)
036032373 Bump junit from 4.13 to 4.13.1 in /java (#7526)
89dfb43f3 Replace `bash JavaTest.sh` with `mvn test` (#7500)
c49aff4b6 enabled cpp17 tests in CI (#7524)
56e60223c prevent force_align attribute on enums (#7523)
89b1f5aa1 remove travis config (#7522)
b90159823 [Java][Flexbuffers] Add API to add nullables into the buffer. (#7521)
8cdc6a288 Install BuildFlatBuffers.cmake (#7519)
a67e35aff Moves all of the swift test code into tests/swift (#7509)
f124e41ae Updated Readme
4c954181c [Java][FlexBuffers] throwing exception for untyped fixed vectors (#7507)
7f7547737 [Android] Remove maven dependency of flatbuffers and use source folder (#7503)
a79d61ea8 Fixes issue with cocoapods failing to be published because of docc (#7505)
d465b39c3 [CMake]: fix breaking find_package change (#7499) (#7502)
c5a609dc2 [C#] Prepares for official Nuget release (#7496)
5634dc3d0 [ISSUE-6268] returns NaN insteadof nan (#7498)
37e37b8ca Updates cocoapods version (#7497)
8fd4534fb update android multidex setting (#7495)
d5427da52 Disable Android Build (#7494)
06c5c7ed0 FlatBuffers Version 2.0.8 (#7492)
b190ce11b Verifier Refinements (#7490)
bf5d23230 Namer applied to Typescript generator (#7488)
ce382d6dd [TS/JS] Add rollup and config to generate iife flatbuffers bundle (#7449)
41d9add7e C++: Add option to skip verifying nested flatbuffers (#7489)
6a8742754 [C++] support native_inline attribute for vector of tables (#7479)
694add668 Refactor test.cpp (#7487)
7edf8c908 Update scorecard to 1.1.2
b86387442 Fix typos (#7483)
e2eb5ee67 Include <array> head in stl_emulation.h (#7480)
994502b6d Version number in file package.json updated to 2.0.7 (#7476)
fa41e8367 [C++] Fixed crash when copying table with empty shared strings (#7477)
799cc8f7b Use type traits for specialization (#7475)
b7eb44147 Disable RTTI and rework use in idl_gen_ts.cpp (#7474)
8d01c5859 CMake project version detection made more robust (#7473)
237e8b71f Moved compiler warnings around (#7471)
eeb8fd60d Include builder.addOffset for vector of structs (#7470)
fef2ffc4d Use schema include name for keep-prefix (#7469)
8367664f1 Flatbuffers Version 2.0.7 (#7462)
d6f06c33f Reworked keep prefix (#7456)
627e8bf36 update grpc version (#7457)
883c42b7d disabling unpackto optimization (#7459)
7aae0af30 Remove old GRPC bash script and convert to python3 (#7454)
b057aa917 Grouped anonymous namespaces together, (#7455)
f1b26ff7f Change to GetTypeName (#7453)
9610a666b Generate SLSA signatures for Released zip files (#7450)
1e0f75a64 [WIP] speedup (#7452)
82b75407a Wrap types in namespace for --ts-flat-files and --gen-all (#7451)
f7c511957 Audit and fixups for GCC and Clang (#7212)
a66de58af Partial support for --ts-flat-files and --gen-all (#7446)
a3508f36d [Kotlin] Make sure namespace path exist for code generation (#7357)
137fec716 Stop using __has_trivial_copy on recent clang versions. (#7443)
214125e41 [C#] Rework how sorted vectors are looked up (#7441)
44a7dc999 Define minimum buffer size (#7440)
3cc2daa78 make_span overloads for pointer to vector (#7374) (#7435)
fa1174aa7 [TypeScript] Fix namespaceless schema generation (#7432)
83d4e2a10 Add checks to verifier (#7438)
8a09f3fb0 Fix FlexBuffers JS/TS bug https://github.com/google/flatbuffers/issues/6934 (#7434)
9dbe819ef Add flatc python tests to CI (#7437)
67c414958 Update TypeScriptTest.py to work better cross platform (#7436)
8b8c7dbdf Update gitingore to reflect name change (#7431)
2ee20a5f3 Remove auto including locale functions (#7430)
4be605604 [C++] Set StructDef::has_key property when deserializing from binary schema (#7386) (#7428)
fc5d86f1e [C++] Make template parameter in stl_emulation.h more explicit to avoid conflicts with cpprestsdk U macro (#7424)
9dce287ad Issue#6959 :Updated Automatically generated rust files. (#7425)
7798be3bb avoid zero-as-null-pointer warning (#7423)
966362e07 [C++] Vector of Tables equality (#7415)
a89c279ed [golang] Perform keyword escaping after case conversion (#7421)
a212b3c03 Turn of fail fast for C++ CI
9230f600d Remove stringop-overflow from error (#7422)
c79362156 [golang] Add support for text parsing with json struct tags (#7353)
ee2ced236 Moved TypeScriptTests to python script (#7411)
468c00a3f Rebased: grpc/compiler: Respect filename suffix and extension during code generation (#7414)
47c757f71 Add tests for flatc (#7405)
9a5ff8900 Add FLATBUFFERS_STRICT_MODE (#7408)
950444a34 [TS] Use TextEncoder and TextDecoder (#7400)
30d76198c Compilation issue msys2 #7399 (#7409)
cce3a66f0 Delete .travis directory
8d1cc6ac7 Revert "Compilation issue msys2 (#7403)" (#7407)
5b207639a Update readme.md
359e0f9d6 Revert "grpc/compiler: Respect filename suffix and extension during code generation (#7343)" (#7406)
ebbed0513 Delete cpp-linter.yml
aa395e5a5 (#7323) Rename CMake files according to project name (#7378)
32328075d Fix error msg format when generate GRPC failed (#7350)
97e89c5ac grpc/compiler: Respect filename suffix and extension during code generation (#7343)
5f6672be4 Fix Clang-Cl compile on Windows (#7308)
28e858c85 [TS/Bazel] Minor improvements to typescript.bzl (#7300)
987bebe67 [TS] fix incorrect reverse when writting array of structs (#7271)
ec0129369 Fix FlexBuffers Verifier tracking vectors reuse at wrong offset
50dd385b3 Add missing const (#7401)
da702cfd8 Compilation issue msys2 (#7403)
6e2791640 keep-prefix keeps relative pathing (#7394)
52fce5e53 fix(#7360): grpc used deprecated functions (#7361)
b7f13cd8e cpp_generator: comment out unused parameter to avoid warnings (#7381)
e42985e5a Updated Newtonsoft.Json to 13.0.1 (#7393)
0a8064637 Fix references to LICENSE file (#7377)
b9eea76a8 [Dart] Implement putBool to fix errors when serializing structs with bools (#7359)
1b9030015 Bump Newtonsoft.Json from 12.0.3 to 13.0.1 in /tests/FlatBuffers.Test (#7363)
83a43fc79 Reenable optional json (#7352)
5f0137602 Only include direct included filed (#7348)
9a1913a87 Revert "Implement optional scalars for JSON (#7322)" (#7351)
b4647beb8 Revert "Move reflection_ts_fbs into a separate directory (#7342)" (#7349)
d6060977a Remove asserting in verifier for flattests
987aa5b5e move -Wextra-semi to GCC 8.0+
42acdb63c [TS] Don't generate self-imports with --ts-flat-file (#7340)
0cc1aeb8c [golang] Create missing namespace directory structure (#7324) (#7325)
ba6c67170 [Kotlin] Remove download benchmark files dependency (#7314)
d2f33fc45 Disable Android on Linux CI build
0d1b72cbc [TS] fix ts import path issue (#7298)
9fce2fbf2 replace io/ioutil to os (#7281)
a18ea40d6 Implement optional scalars for JSON (#7322)
090caa280 Move reflection_ts_fbs into a separate directory (#7342)
49e1ea333 Implement optional scalars for Python (#7318)
11a198870 Started implementation for private flags in rust (#7269)
967df08b1 Adds full supposed for Wasm in the swift lib (#7328)
9aa08a429 Use keep case for Rust union discriminant type. (#7321)
9e8c758f5 Add explicit return types to lobster generated code (#7312)
74a25536b Add size check to fix out of bounds read risk (#7304)
12917af8a Update Rust docs page (#7296)
1ea2472f7 [swift] add had<ArrayName> property for arrays to check presence in a message (#7280)
0fe13cb28 Remove span ConstIterator/cbegin()/cend(). (#7295)
385dddc66 Namerkot (#7245)
750dde766 Make `flatc` generate Rust files not requiring `std` (#7273)
9917a168c [swift] Make swift module public (#7274)
76d3cca19 Rust: fix a name conflict when building with "no_std" feature (#7268)
c86e6d0e3 json inf parsing
d34dc32c2 fix include order
234d86c92 fixed off-by-one in parser
746c73b91 Add Annotations for Monster schema and example buffer
0bbfd4b2e fixes for annotator
716521953 Update readme.md (#7257)
a45f564cf [performance] Add aggressive systematic inlining in ByteBuffer and FlatBufferBuilder (#7253)
9d45a6403 more google merge fixes
ccfb4c20b Handle +/-inf in protos (#7256)
7bcd857b8 Specialize CreateVector with std::initializer_list (#7254)
23c8ab34c Swift update performance benchmark infrastructure (#7255)
70002dc5c various fixes for google merge
6e0e79f24 Add test for nested buffer verifier (#7252)
b856368d7 Turn off go modules temporary until we get a proper fix (#7251)
e37156a30 Keep the underlying storage capacity when clearing the FlatBufferBuilder. Gives a significant performance boost for serialisation of many small messages. (#7250)
a10b0e546 Java namer variable keep case (#7249)
275b73994 allow overriding FLATBUFFERS_MAX_ALIGNMENT
9d1ce9a10 Add parameter back to EndVector (#7246)
79afe6c3d Make Java namespaces keep case by default (#7243)
c6dbb2230 Add write permissions for labeller
18bacd3ea Expand test to make sure {}-initializers are properly understood by template. (#7242)
a2c913aec Add -Wnon-virtual-dtor
67b33b294 set workflows permissions to read-only (#7239)
7b5fd2bd0 [Kotlin] Fix key lookup returning null clashing with default value (#7237)
7181d7770 [Java] Fix key lookup returning null clashing with default value (#7236)
7f663b120 Allow CreateVectorOfStrings() to work with any string-type. (#7238)
173ebb694 Fixes a bug where the create function doesnt optional + required items (#7228)
d65823948 [Kotlin] Update gradle to 7.4.1 and simplify config files. (#7231)
ab4bf59e8 remove toascii (#7234)
eee44bbb2 disable cpp-linter (#7229)
a63fa51a1 Create cpp-linter.yml (#7208)
2049e5210 Adds a way to verify/exposes Entities ids (#7221)
832c618f5 Adds implementation flag for swift (#7202)
14615699f Started to migrate to target_compile_options (#7222)
20aad0c41 [C++] stl_emulation span::count_ is not const anymore (#7226) (#7227)
f083b33f2 code gen flexbuffer verifier (#7207)
bf17df346 [C++] generate sorted #include directives (#7213)
35281dedb Fix for [C++] flatc generates invalid Code in the default constructor for structs, when --cpp-field-case-style is used #7209 (#7211)
c9651b742 Add overloads for C# ByteBuffer/FlatBufferBuilder to allow adding vector blocks from ArraySegments or IntPtr (#7193)
26c3b3ada Update codeql.yml
da6e1b985 Update codeql.yml
ad27d751e Added Oss fuzz badge
0aab623cb Create codeql.yml
6a446bdd8 maximize parallel builds in CI (#7206)
21fb5cbbc Create scorecards.yml
0da6f9486 [C++] Static assert on Flatbuffers Version (#7203)
59e971308 reduce fuzzing time to 1 minute in CI
40866a892 fixed padding in struct for annotated binary (#7199)
b71d968fa Apply Namer prefix/suffix to other generators (#7197)
fac0d7be0 Apply Namer to Java. (#7194)
6c5603fd9 [C#] Fix collision of field name and type name (#7149)
2d21853a7 monster fuzzer fix for json default scalars
fec1a8d01 [swift] Add bazel configuration for Swift (#7195)
7fd857623 structured comments (#7192)
a4cb1599d Namerdart (#7187)
ae4ce7265 fuzzed binary annotator (#7188)
e2be0c0b0 Handle root offset and root table vtable invalidation (#7177)
2ad408697 [TS] Fix generation of struct members in object api (#7148)
4213d9105 VerifySizePrefixed (reflection::Schema) and GetAnySizePrefixedRoot added (#7181)
5a13f622c Correctly parse lists of enums in Dart generated code (#7157)
23a7e4e0b Adds no-includes flags to the swift code generator (#7182)
eeb49c275 Move flatbuffer_ts_library to typescript.bzl (#7183)
824763b31 Typo in flatc options (warning-as-errors instead of warnings-as-errors) (#7180)
d3aeee32b Annotated Flatbuffer Binary (#7174)
0bceba24d [Lua] Apply Namer to Lua (#7171)
b8c77d404 Make inclusion of header <optional> opt-out via macro (#7168)
8468eab83 Namersw (#7167)
2b2e8d4ae Nameroverloads (#7164)
b80b32bfa Use DESCRIPTION only if CMake version >= 3.9 (#7166)

Change-Id: Ic2681dabb1a798b7515e62753ee06aecb9933260
git-subtree-dir: third_party/flatbuffers
git-subtree-split: bc44fad35271e43fd7a79b4d691ac9e41708797f
Signed-off-by: Austin Schuh <austin.schuh@bluerivertech.com>
diff --git a/tests/monster_test.cpp b/tests/monster_test.cpp
new file mode 100644
index 0000000..4fc9e14
--- /dev/null
+++ b/tests/monster_test.cpp
@@ -0,0 +1,845 @@
+#include "monster_test.h"
+
+#include <vector>
+
+#include "flatbuffers/flatbuffer_builder.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/registry.h"
+#include "flatbuffers/verifier.h"
+#include "is_quiet_nan.h"
+#include "monster_extra_generated.h"
+#include "monster_test_generated.h"
+#include "test_assert.h"
+
+namespace flatbuffers {
+namespace tests {
+
+// Shortcuts for the infinity.
+static const auto infinity_f = std::numeric_limits<float>::infinity();
+static const auto infinity_d = std::numeric_limits<double>::infinity();
+
+using namespace MyGame::Example;
+
+// example of how to build up a serialized buffer algorithmically:
+flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) {
+  flatbuffers::FlatBufferBuilder builder;
+
+  auto vec = Vec3(1, 2, 3, 0, Color_Red, Test(10, 20));
+
+  auto name = builder.CreateString("MyMonster");
+
+  // Use the initializer_list specialization of CreateVector.
+  auto inventory =
+      builder.CreateVector<uint8_t>({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
+
+  // Alternatively, create the vector first, and fill in data later:
+  // unsigned char *inv_buf = nullptr;
+  // auto inventory = builder.CreateUninitializedVector<unsigned char>(
+  //                                                              10, &inv_buf);
+  // memcpy(inv_buf, inv_data, 10);
+
+  Test tests[] = { Test(10, 20), Test(30, 40) };
+  auto testv = builder.CreateVectorOfStructs(tests, 2);
+
+  // Create a vector of structures from a lambda.
+  auto testv2 = builder.CreateVectorOfStructs<Test>(
+      2, [&](size_t i, Test *s) -> void { *s = tests[i]; });
+
+  // create monster with very few fields set:
+  // (same functionality as CreateMonster below, but sets fields manually)
+  flatbuffers::Offset<Monster> mlocs[3];
+  auto fred = builder.CreateString("Fred");
+  auto barney = builder.CreateString("Barney");
+  auto wilma = builder.CreateString("Wilma");
+  MonsterBuilder mb1(builder);
+  mb1.add_name(fred);
+  mlocs[0] = mb1.Finish();
+  MonsterBuilder mb2(builder);
+  mb2.add_name(barney);
+  mb2.add_hp(1000);
+  mlocs[1] = mb2.Finish();
+  MonsterBuilder mb3(builder);
+  mb3.add_name(wilma);
+  mlocs[2] = mb3.Finish();
+
+  // Create an array of strings. Also test string pooling, and lambdas.
+  auto vecofstrings =
+      builder.CreateVector<flatbuffers::Offset<flatbuffers::String>>(
+          4,
+          [](size_t i, flatbuffers::FlatBufferBuilder *b)
+              -> flatbuffers::Offset<flatbuffers::String> {
+            static const char *names[] = { "bob", "fred", "bob", "fred" };
+            return b->CreateSharedString(names[i]);
+          },
+          &builder);
+
+  // Creating vectors of strings in one convenient call.
+  std::vector<std::string> names2;
+  names2.push_back("jane");
+  names2.push_back("mary");
+  auto vecofstrings2 = builder.CreateVectorOfStrings(names2);
+
+  // Creating vectors from types that are different from std::string
+  std::vector<const char *> names3;
+  names3.push_back("foo");
+  names3.push_back("bar");
+  builder.CreateVectorOfStrings(names3);  // Also an accepted type
+
+#ifdef FLATBUFFERS_HAS_STRING_VIEW
+  std::vector<flatbuffers::string_view> names4;
+  names3.push_back("baz");
+  names3.push_back("quux");
+  builder.CreateVectorOfStrings(names4);  // Also an accepted type
+#endif
+
+  // Make sure the template deduces an initializer as std::vector<std::string>
+  builder.CreateVectorOfStrings({ "hello", "world" });
+
+  // Create many vectors of strings
+  std::vector<std::string> manyNames;
+  for (auto i = 0; i < 100; i++) { manyNames.push_back("john_doe"); }
+  auto manyNamesVec = builder.CreateVectorOfStrings(manyNames);
+  TEST_EQ(false, manyNamesVec.IsNull());
+  auto manyNamesVec2 =
+      builder.CreateVectorOfStrings(manyNames.cbegin(), manyNames.cend());
+  TEST_EQ(false, manyNamesVec2.IsNull());
+
+  // Create an array of sorted tables, can be used with binary search when read:
+  auto vecoftables = builder.CreateVectorOfSortedTables(mlocs, 3);
+
+  // Create an array of sorted structs,
+  // can be used with binary search when read:
+  std::vector<Ability> abilities;
+  abilities.push_back(Ability(4, 40));
+  abilities.push_back(Ability(3, 30));
+  abilities.push_back(Ability(2, 20));
+  abilities.push_back(Ability(0, 0));
+  auto vecofstructs = builder.CreateVectorOfSortedStructs(&abilities);
+
+  flatbuffers::Offset<Stat> mlocs_stats[1];
+  auto miss = builder.CreateString("miss");
+  StatBuilder mb_miss(builder);
+  mb_miss.add_id(miss);
+  mb_miss.add_val(0);
+  mb_miss.add_count(0);  // key
+  mlocs_stats[0] = mb_miss.Finish();
+  auto vec_of_stats = builder.CreateVectorOfSortedTables(mlocs_stats, 1);
+
+  // Create a nested FlatBuffer.
+  // Nested FlatBuffers are stored in a ubyte vector, which can be convenient
+  // since they can be memcpy'd around much easier than other FlatBuffer
+  // values. They have little overhead compared to storing the table directly.
+  // As a test, create a mostly empty Monster buffer:
+  flatbuffers::FlatBufferBuilder nested_builder;
+  auto nmloc = CreateMonster(nested_builder, nullptr, 0, 0,
+                             nested_builder.CreateString("NestedMonster"));
+  FinishMonsterBuffer(nested_builder, nmloc);
+  // Now we can store the buffer in the parent. Note that by default, vectors
+  // are only aligned to their elements or size field, so in this case if the
+  // buffer contains 64-bit elements, they may not be correctly aligned. We fix
+  // that with:
+  builder.ForceVectorAlignment(nested_builder.GetSize(), sizeof(uint8_t),
+                               nested_builder.GetBufferMinAlignment());
+  // If for whatever reason you don't have the nested_builder available, you
+  // can substitute flatbuffers::largest_scalar_t (64-bit) for the alignment, or
+  // the largest force_align value in your schema if you're using it.
+  auto nested_flatbuffer_vector = builder.CreateVector(
+      nested_builder.GetBufferPointer(), nested_builder.GetSize());
+
+  // Test a nested FlexBuffer:
+  flexbuffers::Builder flexbuild;
+  flexbuild.Int(1234);
+  flexbuild.Finish();
+  auto flex = builder.CreateVector(flexbuild.GetBuffer());
+  // Test vector of enums.
+  Color colors[] = { Color_Blue, Color_Green };
+  // We use this special creation function because we have an array of
+  // pre-C++11 (enum class) enums whose size likely is int, yet its declared
+  // type in the schema is byte.
+  auto vecofcolors = builder.CreateVectorScalarCast<uint8_t, Color>(colors, 2);
+
+  // shortcut for creating monster with all fields set:
+  auto mloc = CreateMonster(
+      builder, &vec, 150, 80, name, inventory, Color_Blue, Any_Monster,
+      mlocs[1].Union(),  // Store a union.
+      testv, vecofstrings, vecoftables, 0, nested_flatbuffer_vector, 0, false,
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 3.14159f, 3.0f, 0.0f, vecofstrings2,
+      vecofstructs, flex, testv2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      AnyUniqueAliases_NONE, 0, AnyAmbiguousAliases_NONE, 0, vecofcolors,
+      MyGame::Example::Race_None, 0, vec_of_stats);
+
+  FinishMonsterBuffer(builder, mloc);
+
+  // clang-format off
+  #ifdef FLATBUFFERS_TEST_VERBOSE
+  // print byte data for debugging:
+  auto p = builder.GetBufferPointer();
+  for (flatbuffers::uoffset_t i = 0; i < builder.GetSize(); i++)
+    printf("%d ", p[i]);
+  #endif
+  // clang-format on
+
+  // return the buffer for the caller to use.
+  auto bufferpointer =
+      reinterpret_cast<const char *>(builder.GetBufferPointer());
+  buffer.assign(bufferpointer, bufferpointer + builder.GetSize());
+
+  return builder.Release();
+}
+
+//  example of accessing a buffer loaded in memory:
+void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length, bool pooled) {
+  // First, verify the buffers integrity (optional)
+  flatbuffers::Verifier verifier(flatbuf, length);
+  std::vector<uint8_t> flex_reuse_tracker;
+  verifier.SetFlexReuseTracker(&flex_reuse_tracker);
+  TEST_EQ(VerifyMonsterBuffer(verifier), true);
+
+  // clang-format off
+  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+    std::vector<uint8_t> test_buff;
+    test_buff.resize(length * 2);
+    std::memcpy(&test_buff[0], flatbuf, length);
+    std::memcpy(&test_buff[length], flatbuf, length);
+
+    flatbuffers::Verifier verifier1(&test_buff[0], length);
+    TEST_EQ(VerifyMonsterBuffer(verifier1), true);
+    TEST_EQ(verifier1.GetComputedSize(), length);
+
+    flatbuffers::Verifier verifier2(&test_buff[length], length);
+    TEST_EQ(VerifyMonsterBuffer(verifier2), true);
+    TEST_EQ(verifier2.GetComputedSize(), length);
+  #endif
+  // clang-format on
+
+  TEST_EQ(strcmp(MonsterIdentifier(), "MONS"), 0);
+  TEST_EQ(MonsterBufferHasIdentifier(flatbuf), true);
+  TEST_EQ(strcmp(MonsterExtension(), "mon"), 0);
+
+  // Access the buffer from the root.
+  auto monster = GetMonster(flatbuf);
+
+  TEST_EQ(monster->hp(), 80);
+  TEST_EQ(monster->mana(), 150);  // default
+  TEST_EQ_STR(monster->name()->c_str(), "MyMonster");
+  // Can't access the following field, it is deprecated in the schema,
+  // which means accessors are not generated:
+  // monster.friendly()
+
+  auto pos = monster->pos();
+  TEST_NOTNULL(pos);
+  TEST_EQ(pos->z(), 3);
+  TEST_EQ(pos->test3().a(), 10);
+  TEST_EQ(pos->test3().b(), 20);
+
+  auto inventory = monster->inventory();
+  TEST_EQ(VectorLength(inventory), 10UL);  // Works even if inventory is null.
+  TEST_NOTNULL(inventory);
+  unsigned char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+  // Check compatibilty of iterators with STL.
+  std::vector<unsigned char> inv_vec(inventory->begin(), inventory->end());
+  size_t n = 0;
+  for (auto it = inventory->begin(); it != inventory->end(); ++it, ++n) {
+    auto indx = it - inventory->begin();
+    TEST_EQ(*it, inv_vec.at(indx));  // Use bounds-check.
+    TEST_EQ(*it, inv_data[indx]);
+  }
+  TEST_EQ(n, inv_vec.size());
+
+  n = 0;
+  for (auto it = inventory->cbegin(); it != inventory->cend(); ++it, ++n) {
+    auto indx = it - inventory->cbegin();
+    TEST_EQ(*it, inv_vec.at(indx));  // Use bounds-check.
+    TEST_EQ(*it, inv_data[indx]);
+  }
+  TEST_EQ(n, inv_vec.size());
+
+  n = 0;
+  for (auto it = inventory->rbegin(); it != inventory->rend(); ++it, ++n) {
+    auto indx = inventory->rend() - it - 1;
+    TEST_EQ(*it, inv_vec.at(indx));  // Use bounds-check.
+    TEST_EQ(*it, inv_data[indx]);
+  }
+  TEST_EQ(n, inv_vec.size());
+
+  n = 0;
+  for (auto it = inventory->crbegin(); it != inventory->crend(); ++it, ++n) {
+    auto indx = inventory->crend() - it - 1;
+    TEST_EQ(*it, inv_vec.at(indx));  // Use bounds-check.
+    TEST_EQ(*it, inv_data[indx]);
+  }
+  TEST_EQ(n, inv_vec.size());
+
+  TEST_EQ(monster->color(), Color_Blue);
+
+  // Example of accessing a union:
+  TEST_EQ(monster->test_type(), Any_Monster);  // First make sure which it is.
+  auto monster2 = reinterpret_cast<const Monster *>(monster->test());
+  TEST_NOTNULL(monster2);
+  TEST_EQ_STR(monster2->name()->c_str(), "Fred");
+
+  // Example of accessing a vector of strings:
+  auto vecofstrings = monster->testarrayofstring();
+  TEST_EQ(vecofstrings->size(), 4U);
+  TEST_EQ_STR(vecofstrings->Get(0)->c_str(), "bob");
+  TEST_EQ_STR(vecofstrings->Get(1)->c_str(), "fred");
+  if (pooled) {
+    // These should have pointer equality because of string pooling.
+    TEST_EQ(vecofstrings->Get(0)->c_str(), vecofstrings->Get(2)->c_str());
+    TEST_EQ(vecofstrings->Get(1)->c_str(), vecofstrings->Get(3)->c_str());
+  }
+
+  auto vecofstrings2 = monster->testarrayofstring2();
+  if (vecofstrings2) {
+    TEST_EQ(vecofstrings2->size(), 2U);
+    TEST_EQ_STR(vecofstrings2->Get(0)->c_str(), "jane");
+    TEST_EQ_STR(vecofstrings2->Get(1)->c_str(), "mary");
+  }
+
+  // Example of accessing a vector of tables:
+  auto vecoftables = monster->testarrayoftables();
+  TEST_EQ(vecoftables->size(), 3U);
+  for (auto it = vecoftables->begin(); it != vecoftables->end(); ++it) {
+    TEST_EQ(strlen(it->name()->c_str()) >= 4, true);
+  }
+  TEST_EQ_STR(vecoftables->Get(0)->name()->c_str(), "Barney");
+  TEST_EQ(vecoftables->Get(0)->hp(), 1000);
+  TEST_EQ_STR(vecoftables->Get(1)->name()->c_str(), "Fred");
+  TEST_EQ_STR(vecoftables->Get(2)->name()->c_str(), "Wilma");
+  TEST_NOTNULL(vecoftables->LookupByKey("Barney"));
+  TEST_NOTNULL(vecoftables->LookupByKey("Fred"));
+  TEST_NOTNULL(vecoftables->LookupByKey("Wilma"));
+
+  // Test accessing a vector of sorted structs
+  auto vecofstructs = monster->testarrayofsortedstruct();
+  if (vecofstructs) {  // not filled in monster_test.bfbs
+    for (flatbuffers::uoffset_t i = 0; i < vecofstructs->size() - 1; i++) {
+      auto left = vecofstructs->Get(i);
+      auto right = vecofstructs->Get(i + 1);
+      TEST_EQ(true, (left->KeyCompareLessThan(right)));
+    }
+    TEST_NOTNULL(vecofstructs->LookupByKey(0));  // test default value
+    TEST_NOTNULL(vecofstructs->LookupByKey(3));
+    TEST_EQ(static_cast<const Ability *>(nullptr),
+            vecofstructs->LookupByKey(5));
+  }
+
+  if (auto vec_of_stat = monster->scalar_key_sorted_tables()) {
+    auto stat_0 = vec_of_stat->LookupByKey(static_cast<uint16_t>(0u));
+    TEST_NOTNULL(stat_0);
+    TEST_NOTNULL(stat_0->id());
+    TEST_EQ(0, stat_0->count());
+    TEST_EQ_STR("miss", stat_0->id()->c_str());
+  }
+
+  // Test nested FlatBuffers if available:
+  auto nested_buffer = monster->testnestedflatbuffer();
+  if (nested_buffer) {
+    // nested_buffer is a vector of bytes you can memcpy. However, if you
+    // actually want to access the nested data, this is a convenient
+    // accessor that directly gives you the root table:
+    auto nested_monster = monster->testnestedflatbuffer_nested_root();
+    TEST_EQ_STR(nested_monster->name()->c_str(), "NestedMonster");
+  }
+
+  // Test flexbuffer if available:
+  auto flex = monster->flex();
+  // flex is a vector of bytes you can memcpy etc.
+  TEST_EQ(flex->size(), 4);  // Encoded FlexBuffer bytes.
+  // However, if you actually want to access the nested data, this is a
+  // convenient accessor that directly gives you the root value:
+  TEST_EQ(monster->flex_flexbuffer_root().AsInt16(), 1234);
+
+  // Test vector of enums:
+  auto colors = monster->vector_of_enums();
+  if (colors) {
+    TEST_EQ(colors->size(), 2);
+    TEST_EQ(colors->Get(0), Color_Blue);
+    TEST_EQ(colors->Get(1), Color_Green);
+  }
+
+  // Since Flatbuffers uses explicit mechanisms to override the default
+  // compiler alignment, double check that the compiler indeed obeys them:
+  // (Test consists of a short and byte):
+  TEST_EQ(flatbuffers::AlignOf<Test>(), 2UL);
+  TEST_EQ(sizeof(Test), 4UL);
+
+  const flatbuffers::Vector<const Test *> *tests_array[] = {
+    monster->test4(),
+    monster->test5(),
+  };
+  for (size_t i = 0; i < sizeof(tests_array) / sizeof(tests_array[0]); ++i) {
+    auto tests = tests_array[i];
+    TEST_NOTNULL(tests);
+    auto test_0 = tests->Get(0);
+    auto test_1 = tests->Get(1);
+    TEST_EQ(test_0->a(), 10);
+    TEST_EQ(test_0->b(), 20);
+    TEST_EQ(test_1->a(), 30);
+    TEST_EQ(test_1->b(), 40);
+    for (auto it = tests->begin(); it != tests->end(); ++it) {
+      TEST_EQ(it->a() == 10 || it->a() == 30, true);  // Just testing iterators.
+    }
+  }
+
+  // Checking for presence of fields:
+  TEST_EQ(flatbuffers::IsFieldPresent(monster, Monster::VT_HP), true);
+  TEST_EQ(flatbuffers::IsFieldPresent(monster, Monster::VT_MANA), false);
+
+  // Obtaining a buffer from a root:
+  TEST_EQ(GetBufferStartFromRootPointer(monster), flatbuf);
+}
+
+// Change a FlatBuffer in-place, after it has been constructed.
+void MutateFlatBuffersTest(uint8_t *flatbuf, std::size_t length) {
+  // Get non-const pointer to root.
+  auto monster = GetMutableMonster(flatbuf);
+
+  // Each of these tests mutates, then tests, then set back to the original,
+  // so we can test that the buffer in the end still passes our original test.
+  auto hp_ok = monster->mutate_hp(10);
+  TEST_EQ(hp_ok, true);  // Field was present.
+  TEST_EQ(monster->hp(), 10);
+  // Mutate to default value
+  auto hp_ok_default = monster->mutate_hp(100);
+  TEST_EQ(hp_ok_default, true);  // Field was present.
+  TEST_EQ(monster->hp(), 100);
+  // Test that mutate to default above keeps field valid for further mutations
+  auto hp_ok_2 = monster->mutate_hp(20);
+  TEST_EQ(hp_ok_2, true);
+  TEST_EQ(monster->hp(), 20);
+  monster->mutate_hp(80);
+
+  // Monster originally at 150 mana (default value)
+  auto mana_default_ok = monster->mutate_mana(150);  // Mutate to default value.
+  TEST_EQ(mana_default_ok,
+          true);  // Mutation should succeed, because default value.
+  TEST_EQ(monster->mana(), 150);
+  auto mana_ok = monster->mutate_mana(10);
+  TEST_EQ(mana_ok, false);  // Field was NOT present, because default value.
+  TEST_EQ(monster->mana(), 150);
+
+  // Mutate structs.
+  auto pos = monster->mutable_pos();
+  auto test3 = pos->mutable_test3();  // Struct inside a struct.
+  test3.mutate_a(50);                 // Struct fields never fail.
+  TEST_EQ(test3.a(), 50);
+  test3.mutate_a(10);
+
+  // Mutate vectors.
+  auto inventory = monster->mutable_inventory();
+  inventory->Mutate(9, 100);
+  TEST_EQ(inventory->Get(9), 100);
+  inventory->Mutate(9, 9);
+
+  auto tables = monster->mutable_testarrayoftables();
+  auto first = tables->GetMutableObject(0);
+  TEST_EQ(first->hp(), 1000);
+  first->mutate_hp(0);
+  TEST_EQ(first->hp(), 0);
+  first->mutate_hp(1000);
+
+  // Mutate via LookupByKey
+  TEST_NOTNULL(tables->MutableLookupByKey("Barney"));
+  TEST_EQ(static_cast<Monster *>(nullptr),
+          tables->MutableLookupByKey("DoesntExist"));
+  TEST_EQ(tables->MutableLookupByKey("Barney")->hp(), 1000);
+  TEST_EQ(tables->MutableLookupByKey("Barney")->mutate_hp(0), true);
+  TEST_EQ(tables->LookupByKey("Barney")->hp(), 0);
+  TEST_EQ(tables->MutableLookupByKey("Barney")->mutate_hp(1000), true);
+
+  // Run the verifier and the regular test to make sure we didn't trample on
+  // anything.
+  AccessFlatBufferTest(flatbuf, length);
+}
+
+// Unpack a FlatBuffer into objects.
+void ObjectFlatBuffersTest(uint8_t *flatbuf) {
+  // Optional: we can specify resolver and rehasher functions to turn hashed
+  // strings into object pointers and back, to implement remote references
+  // and such.
+  auto resolver = flatbuffers::resolver_function_t(
+      [](void **pointer_adr, flatbuffers::hash_value_t hash) {
+        (void)pointer_adr;
+        (void)hash;
+        // Don't actually do anything, leave variable null.
+      });
+  auto rehasher = flatbuffers::rehasher_function_t(
+      [](void *pointer) -> flatbuffers::hash_value_t {
+        (void)pointer;
+        return 0;
+      });
+
+  // Turn a buffer into C++ objects.
+  auto monster1 = UnPackMonster(flatbuf, &resolver);
+
+  // Re-serialize the data.
+  flatbuffers::FlatBufferBuilder fbb1;
+  fbb1.Finish(CreateMonster(fbb1, monster1.get(), &rehasher),
+              MonsterIdentifier());
+
+  // Unpack again, and re-serialize again.
+  auto monster2 = UnPackMonster(fbb1.GetBufferPointer(), &resolver);
+  flatbuffers::FlatBufferBuilder fbb2;
+  fbb2.Finish(CreateMonster(fbb2, monster2.get(), &rehasher),
+              MonsterIdentifier());
+
+  // Now we've gone full round-trip, the two buffers should match.
+  const auto len1 = fbb1.GetSize();
+  const auto len2 = fbb2.GetSize();
+  TEST_EQ(len1, len2);
+  TEST_EQ(memcmp(fbb1.GetBufferPointer(), fbb2.GetBufferPointer(), len1), 0);
+
+  // Test it with the original buffer test to make sure all data survived.
+  AccessFlatBufferTest(fbb2.GetBufferPointer(), len2, false);
+
+  // Test accessing fields, similar to AccessFlatBufferTest above.
+  CheckMonsterObject(monster2.get());
+
+  // Test object copy.
+  auto monster3 = *monster2;
+  flatbuffers::FlatBufferBuilder fbb3;
+  fbb3.Finish(CreateMonster(fbb3, &monster3, &rehasher), MonsterIdentifier());
+  const auto len3 = fbb3.GetSize();
+  TEST_EQ(len2, len3);
+  TEST_EQ(memcmp(fbb2.GetBufferPointer(), fbb3.GetBufferPointer(), len2), 0);
+  // Delete monster1 and monster2, then test accessing fields in monster3.
+  monster1.reset();
+  monster2.reset();
+  CheckMonsterObject(&monster3);
+}
+
+// Utility function to check a Monster object.
+void CheckMonsterObject(MonsterT *monster2) {
+  TEST_EQ(monster2->hp, 80);
+  TEST_EQ(monster2->mana, 150);  // default
+  TEST_EQ_STR(monster2->name.c_str(), "MyMonster");
+
+  auto &pos = monster2->pos;
+  TEST_NOTNULL(pos);
+  TEST_EQ(pos->z(), 3);
+  TEST_EQ(pos->test3().a(), 10);
+  TEST_EQ(pos->test3().b(), 20);
+
+  auto &inventory = monster2->inventory;
+  TEST_EQ(inventory.size(), 10UL);
+  unsigned char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+  for (auto it = inventory.begin(); it != inventory.end(); ++it)
+    TEST_EQ(*it, inv_data[it - inventory.begin()]);
+
+  TEST_EQ(monster2->color, Color_Blue);
+
+  auto monster3 = monster2->test.AsMonster();
+  TEST_NOTNULL(monster3);
+  TEST_EQ_STR(monster3->name.c_str(), "Fred");
+
+  auto &vecofstrings = monster2->testarrayofstring;
+  TEST_EQ(vecofstrings.size(), 4U);
+  TEST_EQ_STR(vecofstrings[0].c_str(), "bob");
+  TEST_EQ_STR(vecofstrings[1].c_str(), "fred");
+
+  auto &vecofstrings2 = monster2->testarrayofstring2;
+  TEST_EQ(vecofstrings2.size(), 2U);
+  TEST_EQ_STR(vecofstrings2[0].c_str(), "jane");
+  TEST_EQ_STR(vecofstrings2[1].c_str(), "mary");
+
+  auto &vecoftables = monster2->testarrayoftables;
+  TEST_EQ(vecoftables.size(), 3U);
+  TEST_EQ_STR(vecoftables[0]->name.c_str(), "Barney");
+  TEST_EQ(vecoftables[0]->hp, 1000);
+  TEST_EQ_STR(vecoftables[1]->name.c_str(), "Fred");
+  TEST_EQ_STR(vecoftables[2]->name.c_str(), "Wilma");
+
+  auto &tests = monster2->test4;
+  TEST_EQ(tests[0].a(), 10);
+  TEST_EQ(tests[0].b(), 20);
+  TEST_EQ(tests[1].a(), 30);
+  TEST_EQ(tests[1].b(), 40);
+}
+
+// Prefix a FlatBuffer with a size field.
+void SizePrefixedTest() {
+  // Create size prefixed buffer.
+  flatbuffers::FlatBufferBuilder fbb;
+  FinishSizePrefixedMonsterBuffer(
+      fbb, CreateMonster(fbb, nullptr, 200, 300, fbb.CreateString("bob")));
+
+  // Verify it.
+  flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
+  TEST_EQ(VerifySizePrefixedMonsterBuffer(verifier), true);
+
+  // Access it.
+  auto m = GetSizePrefixedMonster(fbb.GetBufferPointer());
+  TEST_EQ(m->mana(), 200);
+  TEST_EQ(m->hp(), 300);
+  TEST_EQ_STR(m->name()->c_str(), "bob");
+}
+
+void TestMonsterExtraFloats(const std::string &tests_data_path) {
+#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
+  TEST_EQ(is_quiet_nan(1.0), false);
+  TEST_EQ(is_quiet_nan(infinity_d), false);
+  TEST_EQ(is_quiet_nan(-infinity_f), false);
+  TEST_EQ(is_quiet_nan(std::numeric_limits<float>::quiet_NaN()), true);
+  TEST_EQ(is_quiet_nan(std::numeric_limits<double>::quiet_NaN()), true);
+
+  using namespace flatbuffers;
+  using namespace MyGame;
+  // Load FlatBuffer schema (.fbs) from disk.
+  std::string schemafile;
+  TEST_EQ(LoadFile((tests_data_path + "monster_extra.fbs").c_str(), false,
+                   &schemafile),
+          true);
+  // Parse schema first, so we can use it to parse the data after.
+  Parser parser;
+  auto include_test_path = ConCatPathFileName(tests_data_path, "include_test");
+  const char *include_directories[] = { tests_data_path.c_str(),
+                                        include_test_path.c_str(), nullptr };
+  TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
+  // Create empty extra and store to json.
+  parser.opts.output_default_scalars_in_json = true;
+  parser.opts.output_enum_identifiers = true;
+  FlatBufferBuilder builder;
+  const auto def_root = MonsterExtraBuilder(builder).Finish();
+  FinishMonsterExtraBuffer(builder, def_root);
+  const auto def_obj = builder.GetBufferPointer();
+  const auto def_extra = GetMonsterExtra(def_obj);
+  TEST_NOTNULL(def_extra);
+  TEST_EQ(is_quiet_nan(def_extra->f0()), true);
+  TEST_EQ(is_quiet_nan(def_extra->f1()), true);
+  TEST_EQ(def_extra->f2(), +infinity_f);
+  TEST_EQ(def_extra->f3(), -infinity_f);
+  TEST_EQ(is_quiet_nan(def_extra->d0()), true);
+  TEST_EQ(is_quiet_nan(def_extra->d1()), true);
+  TEST_EQ(def_extra->d2(), +infinity_d);
+  TEST_EQ(def_extra->d3(), -infinity_d);
+  std::string jsongen;
+  auto result = GenerateText(parser, def_obj, &jsongen);
+  TEST_EQ(result, true);
+  // Check expected default values.
+  TEST_EQ(std::string::npos != jsongen.find("f0: nan"), true);
+  TEST_EQ(std::string::npos != jsongen.find("f1: nan"), true);
+  TEST_EQ(std::string::npos != jsongen.find("f2: inf"), true);
+  TEST_EQ(std::string::npos != jsongen.find("f3: -inf"), true);
+  TEST_EQ(std::string::npos != jsongen.find("d0: nan"), true);
+  TEST_EQ(std::string::npos != jsongen.find("d1: nan"), true);
+  TEST_EQ(std::string::npos != jsongen.find("d2: inf"), true);
+  TEST_EQ(std::string::npos != jsongen.find("d3: -inf"), true);
+  // Parse 'mosterdata_extra.json'.
+  const auto extra_base = tests_data_path + "monsterdata_extra";
+  jsongen = "";
+  TEST_EQ(LoadFile((extra_base + ".json").c_str(), false, &jsongen), true);
+  TEST_EQ(parser.Parse(jsongen.c_str()), true);
+  const auto test_file = parser.builder_.GetBufferPointer();
+  const auto test_size = parser.builder_.GetSize();
+  Verifier verifier(test_file, test_size);
+  TEST_ASSERT(VerifyMonsterExtraBuffer(verifier));
+  const auto extra = GetMonsterExtra(test_file);
+  TEST_NOTNULL(extra);
+  TEST_EQ(is_quiet_nan(extra->f0()), true);
+  TEST_EQ(is_quiet_nan(extra->f1()), true);
+  TEST_EQ(extra->f2(), +infinity_f);
+  TEST_EQ(extra->f3(), -infinity_f);
+  TEST_EQ(is_quiet_nan(extra->d0()), true);
+  TEST_EQ(extra->d1(), +infinity_d);
+  TEST_EQ(extra->d2(), -infinity_d);
+  TEST_EQ(is_quiet_nan(extra->d3()), true);
+  TEST_NOTNULL(extra->fvec());
+  TEST_EQ(extra->fvec()->size(), 4);
+  TEST_EQ(extra->fvec()->Get(0), 1.0f);
+  TEST_EQ(extra->fvec()->Get(1), -infinity_f);
+  TEST_EQ(extra->fvec()->Get(2), +infinity_f);
+  TEST_EQ(is_quiet_nan(extra->fvec()->Get(3)), true);
+  TEST_NOTNULL(extra->dvec());
+  TEST_EQ(extra->dvec()->size(), 4);
+  TEST_EQ(extra->dvec()->Get(0), 2.0);
+  TEST_EQ(extra->dvec()->Get(1), +infinity_d);
+  TEST_EQ(extra->dvec()->Get(2), -infinity_d);
+  TEST_EQ(is_quiet_nan(extra->dvec()->Get(3)), true);
+#endif
+}
+
+void EnumNamesTest() {
+  TEST_EQ_STR("Red", EnumNameColor(Color_Red));
+  TEST_EQ_STR("Green", EnumNameColor(Color_Green));
+  TEST_EQ_STR("Blue", EnumNameColor(Color_Blue));
+  // Check that Color to string don't crash while decode a mixture of Colors.
+  // 1) Example::Color enum is enum with unfixed underlying type.
+  // 2) Valid enum range: [0; 2^(ceil(log2(Color_ANY))) - 1].
+  // Consequence: A value is out of this range will lead to UB (since C++17).
+  // For details see C++17 standard or explanation on the SO:
+  // stackoverflow.com/questions/18195312/what-happens-if-you-static-cast-invalid-value-to-enum-class
+  TEST_EQ_STR("", EnumNameColor(static_cast<Color>(0)));
+  TEST_EQ_STR("", EnumNameColor(static_cast<Color>(Color_ANY - 1)));
+  TEST_EQ_STR("", EnumNameColor(static_cast<Color>(Color_ANY + 1)));
+}
+
+void TypeAliasesTest() {
+  flatbuffers::FlatBufferBuilder builder;
+
+  builder.Finish(CreateTypeAliases(
+      builder, flatbuffers::numeric_limits<int8_t>::min(),
+      flatbuffers::numeric_limits<uint8_t>::max(),
+      flatbuffers::numeric_limits<int16_t>::min(),
+      flatbuffers::numeric_limits<uint16_t>::max(),
+      flatbuffers::numeric_limits<int32_t>::min(),
+      flatbuffers::numeric_limits<uint32_t>::max(),
+      flatbuffers::numeric_limits<int64_t>::min(),
+      flatbuffers::numeric_limits<uint64_t>::max(), 2.3f, 2.3));
+
+  auto p = builder.GetBufferPointer();
+  auto ta = flatbuffers::GetRoot<TypeAliases>(p);
+
+  TEST_EQ(ta->i8(), flatbuffers::numeric_limits<int8_t>::min());
+  TEST_EQ(ta->u8(), flatbuffers::numeric_limits<uint8_t>::max());
+  TEST_EQ(ta->i16(), flatbuffers::numeric_limits<int16_t>::min());
+  TEST_EQ(ta->u16(), flatbuffers::numeric_limits<uint16_t>::max());
+  TEST_EQ(ta->i32(), flatbuffers::numeric_limits<int32_t>::min());
+  TEST_EQ(ta->u32(), flatbuffers::numeric_limits<uint32_t>::max());
+  TEST_EQ(ta->i64(), flatbuffers::numeric_limits<int64_t>::min());
+  TEST_EQ(ta->u64(), flatbuffers::numeric_limits<uint64_t>::max());
+  TEST_EQ(ta->f32(), 2.3f);
+  TEST_EQ(ta->f64(), 2.3);
+  using namespace flatbuffers;  // is_same
+  static_assert(is_same<decltype(ta->i8()), int8_t>::value, "invalid type");
+  static_assert(is_same<decltype(ta->i16()), int16_t>::value, "invalid type");
+  static_assert(is_same<decltype(ta->i32()), int32_t>::value, "invalid type");
+  static_assert(is_same<decltype(ta->i64()), int64_t>::value, "invalid type");
+  static_assert(is_same<decltype(ta->u8()), uint8_t>::value, "invalid type");
+  static_assert(is_same<decltype(ta->u16()), uint16_t>::value, "invalid type");
+  static_assert(is_same<decltype(ta->u32()), uint32_t>::value, "invalid type");
+  static_assert(is_same<decltype(ta->u64()), uint64_t>::value, "invalid type");
+  static_assert(is_same<decltype(ta->f32()), float>::value, "invalid type");
+  static_assert(is_same<decltype(ta->f64()), double>::value, "invalid type");
+}
+
+// example of parsing text straight into a buffer, and generating
+// text back from it:
+void ParseAndGenerateTextTest(const std::string &tests_data_path, bool binary) {
+  // load FlatBuffer schema (.fbs) and JSON from disk
+  std::string schemafile;
+  std::string jsonfile;
+  TEST_EQ(flatbuffers::LoadFile(
+              (tests_data_path + "monster_test." + (binary ? "bfbs" : "fbs"))
+                  .c_str(),
+              binary, &schemafile),
+          true);
+  TEST_EQ(flatbuffers::LoadFile(
+              (tests_data_path + "monsterdata_test.golden").c_str(), false,
+              &jsonfile),
+          true);
+
+  auto include_test_path =
+      flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
+  const char *include_directories[] = { tests_data_path.c_str(),
+                                        include_test_path.c_str(), nullptr };
+
+  // parse schema first, so we can use it to parse the data after
+  flatbuffers::Parser parser;
+  if (binary) {
+    flatbuffers::Verifier verifier(
+        reinterpret_cast<const uint8_t *>(schemafile.c_str()),
+        schemafile.size());
+    TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
+    // auto schema = reflection::GetSchema(schemafile.c_str());
+    TEST_EQ(parser.Deserialize(
+                reinterpret_cast<const uint8_t *>(schemafile.c_str()),
+                schemafile.size()),
+            true);
+  } else {
+    TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
+  }
+  TEST_EQ(parser.ParseJson(jsonfile.c_str()), true);
+
+  // here, parser.builder_ contains a binary buffer that is the parsed data.
+
+  // First, verify it, just in case:
+  flatbuffers::Verifier verifier(parser.builder_.GetBufferPointer(),
+                                 parser.builder_.GetSize());
+  TEST_EQ(VerifyMonsterBuffer(verifier), true);
+
+  AccessFlatBufferTest(parser.builder_.GetBufferPointer(),
+                       parser.builder_.GetSize(), false);
+
+  // to ensure it is correct, we now generate text back from the binary,
+  // and compare the two:
+  std::string jsongen;
+  auto result =
+      GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
+  TEST_EQ(result, true);
+  TEST_EQ_STR(jsongen.c_str(), jsonfile.c_str());
+
+  // We can also do the above using the convenient Registry that knows about
+  // a set of file_identifiers mapped to schemas.
+  flatbuffers::Registry registry;
+  // Make sure schemas can find their includes.
+  registry.AddIncludeDirectory(tests_data_path.c_str());
+  registry.AddIncludeDirectory(include_test_path.c_str());
+  // Call this with many schemas if possible.
+  registry.Register(MonsterIdentifier(),
+                    (tests_data_path + "monster_test.fbs").c_str());
+  // Now we got this set up, we can parse by just specifying the identifier,
+  // the correct schema will be loaded on the fly:
+  auto buf = registry.TextToFlatBuffer(jsonfile.c_str(), MonsterIdentifier());
+  // If this fails, check registry.lasterror_.
+  TEST_NOTNULL(buf.data());
+  // Test the buffer, to be sure:
+  AccessFlatBufferTest(buf.data(), buf.size(), false);
+  // We can use the registry to turn this back into text, in this case it
+  // will get the file_identifier from the binary:
+  std::string text;
+  auto ok = registry.FlatBufferToText(buf.data(), buf.size(), &text);
+  // If this fails, check registry.lasterror_.
+  TEST_EQ(ok, true);
+  TEST_EQ_STR(text.c_str(), jsonfile.c_str());
+
+  // Generate text for UTF-8 strings without escapes.
+  std::string jsonfile_utf8;
+  TEST_EQ(flatbuffers::LoadFile((tests_data_path + "unicode_test.json").c_str(),
+                                false, &jsonfile_utf8),
+          true);
+  TEST_EQ(parser.Parse(jsonfile_utf8.c_str(), include_directories), true);
+  // To ensure it is correct, generate utf-8 text back from the binary.
+  std::string jsongen_utf8;
+  // request natural printing for utf-8 strings
+  parser.opts.natural_utf8 = true;
+  parser.opts.strict_json = true;
+  TEST_EQ(
+      GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen_utf8),
+      true);
+  TEST_EQ_STR(jsongen_utf8.c_str(), jsonfile_utf8.c_str());
+}
+
+void UnPackTo(const uint8_t *flatbuf) {
+  // Get a monster that has a name and no enemy
+  auto orig_monster = GetMonster(flatbuf);
+  TEST_EQ_STR(orig_monster->name()->c_str(), "MyMonster");
+  TEST_ASSERT(orig_monster->enemy() == nullptr);
+
+  // Create an enemy
+  MonsterT *enemy = new MonsterT();
+  enemy->name = "Enemy";
+
+  // And create another monster owning the enemy,
+  MonsterT mon;
+  mon.name = "I'm monster 1";
+  mon.enemy.reset(enemy);
+  TEST_ASSERT(mon.enemy != nullptr);
+
+  // Assert that all the Monster objects are correct.
+  TEST_EQ_STR(mon.name.c_str(), "I'm monster 1");
+  TEST_EQ_STR(enemy->name.c_str(), "Enemy");
+  TEST_EQ_STR(mon.enemy->name.c_str(), "Enemy");
+
+  // Now unpack monster ("MyMonster") into monster
+  orig_monster->UnPackTo(&mon);
+
+  // Monster name should be from monster
+  TEST_EQ_STR(mon.name.c_str(), "MyMonster");
+
+  // The monster shouldn't have any enemies, because monster didn't.
+  TEST_ASSERT(mon.enemy == nullptr);
+}
+
+}  // namespace tests
+}  // namespace flatbuffers
\ No newline at end of file