Squashed 'third_party/flatbuffers/' changes from acc9990ab..d6a8dbd26

d6a8dbd26 Experimental fix for failing oss-fuzz coverage build (#6259)
ed391e177 BREAKING: Rust flexbuffers serde human readable set to false (#6257)
a49531414 Update to flags in fuzzing-cmake file (#6256)
de1f0342c Remove _POSIX_C_SOURCE and _XOPEN_SOURCE definitions when compiling o… (#6205)
d0d51e2a5 flatc should support --binary --schema with optional scalar fields. (#6252)
33ab26017 Bump version of rules_go to 0.24.5 (#6234)
febb9d87c Union As Accessors for C# (#6251)
8778dc7c2 Resets buffer without deallocating current pointer (#6247)
aae376e9a Add GetBufferSpan() function to bufferbuilder (#6235)
0ff047148 Modernize android build and sample (#6229)
46a8c7e95 Added required-nested-flatbuffer to monster_test and fixed rust (#6236)
bc56c553e Notify based on Labelling issues and PR (#6241)
07d7cd78a Converted globs to use single quotes (#6240)
cdef70e24 More adjustments to the auto labeler (#6239)
9dd44df35 Updated Lua labeller glob (#6238)
c9b29d088 Support size-prefixed buffers and add tests for size-prefixed messages (#6232)
fba93e0ab Removes duplicate swift in labeler (#6228)
d1a545b1f Added more labels for auto labeler (#6227)
ea92a668d [C#] Optional Scalars (#6217)
6034de286 [Label Bot] Add Java and Kotlin support for the label bot (#6226)
b08b0a440 Implement `Debug` trait for Rust flatbuffers. (#6207)
17ae48dec [Label Bot] Adds some languages to labeler bot (#6222)
fc8097925 Auto Labeler Setup, Just C# for now (#6221)
55658f523 Auto Labeler Setup, Just C# for now (#6218)
14ecfe423 Updated comments and fixed a fundamental type error. (#6214)
a0182cdb1 optional scalars for ts/js (#6215)
0dfcc0a37 Adds NetTest.bat to run .NET Core tests on Windows (#6216)
f9a18ea63 [Java] Implement optional scalars (#6212)
c7586e85a Empties the sharedString map on reset on go and csharp (#6187)
914c64601 Removed C# references from java generator. Move annotations closer to definitions (#6204)
42d7c7997 Adds readable size to asserts in read functions (#6210)
e68e8d7de Refactor idl_gen_rust (#6206)
84809be7e Fix typo in flatbuffers::span declaration. (#6202)
1606fb637 Kotlin test optional enum (#6201)
fe8e3c7e5 Mass Refactoring to use `IsString` and other BASE_TYPE helpers (#6193)
8f6fa4b71 Updated SupportsAdvancedUnionFeatures to look out for string (#6190)
b46db38f5 [JS/TS] Rewrite flexbuffers JS to TS (#6148)
9fa1d2705 Rework enums in rust. (#6098)
a402b3aba idl_gen_json_schema Fix generation of arrays of enums (#6184)
0e1415b99 fix(go_test): remove deprecated grpc call (#6183)
5cd713710 Add generation of JSON Schema to library (#6165)
5be777e1d Bump junit from 4.12 to 4.13.1 in /grpc/tests (#6173)
a49d440ec Bump junit from 4.12 to 4.13.1 in /grpc (#6172)
4ec5e8db9 [C++] Add option to not generate direct copy methods. (#6166)
04bec23a3 Add Array initialization from struct constructor (#5865) (#6147)
77d57fd07 Cast to right type for reserved_ subtraction (#6167)
543c1bbeb Fixed rust nested flatbuffers for tables other than self (#6062)
cb971eece [C++] Fix -Wnarrowing and -Woverflow due to signed bitfields on G++ ARM (#6163)
7b9e61fcc [TS] GRPC  Implementation (#6141)
3359e3042 Moved C++ to optional_scalars2 and added some tests. (#6162)
187a4787f [Rust] Upgrade flatbuffers library to 2018 edition (#6159)
08943aa26 Flatbuffer C++ UnpackTo optimization for vectors of non-bool bytes. (#6154)
5975658eb Enables optional enums in swift (#6160)
5d3cf440e Updated Lobster test for optional bools/enums
8ec8322f0 Ruopt enum (#6156)
bbcc85fd4 Fix generation of C++ code with Optional<Enum> (#6155)
0bdf2fa15 [C#] Fix and improve project files (#6142)
2eedc769d possibility to create a vector from an iterator (#6135)
ab01ae162 flatc should output a warning, when an attribute is attached more than once (#6146)
689bfafa7 [Python/JS/TS] Codegen SizeOf method for structs (#6136)
641309a5b unix2dos on tests/FlatBuffers.Test/FlatBuffers.Core.Test.csproj (#6133)
52e362879 SpanT is available in .Net Standard 2.0. (#6137)
dca12522a Add static cast to avoid implicit double promotion. (#6132)
e0bbaa6f9 [C#]Change to ENABLE_SPAN_T that doesn't require UNSAFE_BYTEBUFFER. (#6073)
ab139d6be Revert "[C#] Fix and improve project files (#6116)" (#6130)
34d67b425 Minireflect fixed array (#6129)
96d5e3597 [JS/TS] fix flatbuffers default export (#6123)
eb686a86f Add missed file generated by optional_scalar.fbs (#6125)
750281630 [C#] Fix and improve project files (#6116)
fb4e1c34f Add CharToLower and CharToUpper into util.s (#6126)
8c67b5b12 Add support of Optional<T> scalars to C++ code generator (#6092)
6228b66d3 [Kotlin] Support for optional scalars. (#6115)
e1be8aaad Bump version for latest swift version (#6121)
94873e595 [JS/TS] Modernize TypeScript / JavaScript flatbuffers support (#6095)
b8e87fafe [JS] Add getFullyQualifiedName() (#6119)
f96d1ef74 [Java] allowing larger buffer sizes when growing a byte buffer (#6118)
89435303b [Swift] Migrates struct write APIS to write directly to the buffer (#6093)
c75ae2429 Optional-ness in reflection (#6097)
338944d3d Rename Nullable scalars to Optional scalars (#6112)
f5ab24bc4 Avoid memcpy call for empty vectors (#6111)
92a8c1a0f [JS] FlexBuffers Fix for wrong type of offset and length values (#6107)
6cea45dcd fix c# json serializer commandline argument docs (#6104)
fec58aa12 Fix for issue 6100: incorrect shrinking logic in ResizeContext() (#6102)
71aca81ff [JS] FlexBuffers Support (#5973)
04d87ffec [C++] Small refactoring of the C++ code generator (#6091)
bb25956f0 Wrap verify file id condition in Check call (#6085)
49f4948f0 + Add `removable-media` plug to the snapcraft config (#6083)
eeacc53d2 Adds proper access types for swift object api & flatbuffers & grpc (#6081)
f3003e08d [Lobster] missed a test
d713a0084 [CMake] enabled multi-core builds in VS projects
77f966f89 [Lobster] optional scalars support
e86d5b8e9 [Kotlin] Attach JvmStatic annotation to each method in companion object (#6052)
db2aa9b4e [C#] Cleaned up .NET testing script for Mono (#6016)
63cc0eec4 Adds a serialize helper function to native table (#6059)
c30a87de6 [TS] Fix four bugs with imported types in TypeScript. (#6054)
a0fb30575 [Swift] Append namespace for Swift Grpc implementation (#6049)
77c18c1d6 export a __version__ variable for python module (#5309)
f1f23d08e adding fb import when no other imports are present (#6030)
f1025b284 [Feature] Checks for Nullable strings (#6050)
5d052f4e5 [Swift] RFC: Switch Swift namespace from public enum to ordinary concat with _ (#6045)
18b015d25 Rust codegen improvements and lint fixes (#6046)
d76e93f27 adds code gen for optional scalars in swift (#6038)
82fac326c [C++] Fix compiler error from deleted assignment operator (#6036) (#6047)
043b52bd4 Optional Scalars support for Rust (#6034)
c8fa0afdf Allow to run cpp tests under grpc/tests/ using bazel. (#6040)
6d0aae73c Fix git command executed in wrong folder when doing cmake superbuild (#6039)
ff1b73128 [Swift] Optional Scalars Preparation (#6028)
2e48c8dd3 tests: Check for both quiet and signaling NaN on mipsel/hppa (#6029)
6942704f2 support deprecated flag in json schema (#6022)
9ecd2e16c Flatc parser support for nullable scalars (#6026)
33e2d8079 [Dart] Generate constant values map for enums (#6025)
969d0f7a6 Using proper symbol name for reexport (#6021)
515a4052a Silence false positive "-Wstringop-overflow" on GCC 10.0 to 11.0 (#6020)
36fbe6f13 Updated FB import (#6019)
b69fc8cc9 [Java] Add support for shared strings on FlatBufferBuilder. (#6012)
ab6af18d9 Not using non-existent create method for obj api (#6015)
37a5dee10 Code cleanup + updates test and readme (#6004)
8a721f69a Serde with bytes maps to Blob (#6009)
e810635ea [Swift] FlatBuffers createMonster method doesn't treat struct properly (#5992)
4995e1527 Manage grpc dependency in Bazel's WORKSPACE file. (#5995)
60b6066fe Add warning to schema parser if field name is not snake_case. (#6005)
35d45cac7 [Rust] Flexbuffers dependency cleanup and fixes (#5998)
165a6e3d1 Re-added Evolution Schema Code Generation Command (#5999)
13d3fb2ea Fix RPM install conflict (#6003)
d64078eb2 [Swift] Initialize memory when clear ByteBuffer (#5982)
ca1190a3d [TS] Use proper TypedArray in create*Vector (#5991)
7571b2ac5 [C++] Updates real_path to be truly portable (#5787)
e5a8f76a4 [C++] Generate default member initializers for >= C++11 (#5989)
413bb9b55 [Kotlin] Fix Access to union of vector element (#5994)
f35184aef [Swift] Add parsing from unowned UnsafeMutableRawPointer for ByteBuffer (#5981)
b124b7625 Removed requirement that enums be declared in ascending order. (#5887)
0ec7600c6 Do not remove the last digit from float values (#5974)
14baf45c9 Mark GetBufferMinAlignment() const (#5985)
9abb2ec2c TypeScript/JavaScript docs improvements (#5984)
2e57d80b1 [Swift] Internal library improvements (#5965)
cfc7753a4 [Doc] Added missing letters to compiler options (#5976)
12ddc8a92 Rust Flexbuffers Documentation update (#5979)
24ad35709 [docs] typo: updates monsterdata.json to be valid json (#5978)
cc44a4442 [idl_parser] Mark typefield as deprecated (#5958)
9ab4a5c0e Deleted old stale bot
6682cfe87 Increased Operations per run in stale.yml
64922904b Adding Stale Action to clean up PR and Issues
8e505cb67 [C++] Fixed/Enabled --cpp-ptr-type std::shared_ptr [#5813] (#5959)
a28357d7a Propagate boolean default values from proto to fbs (#5964)
7cb4762a6 [Swift] Improving reallocation time by using memcpy and moving reallocation code to storage (#5960)
4e45f7c9e Fix error in SimpleQSort (#5955)
7ac026405 fix error on GRPC Python - ignore namespace tree if not specified (#5862) (#5922)
108e981db Required is now implemented in swift (#5952)
94a78e385 Fixed: Access violation and ASAN/UNSAN failures with sorted tables
53fb453e0 [rust] Add FlatBufferBuilder::force_defaults API (#5946)
17c1f35fa [FlexBuffer][Java] ReadWriteBuf and ReadBuf interface public (#5948)
2eaf57778 [Java] Grow ArrayReadWriteBuf enough to match requested capacity. (#5921)
666800da3 Adds bool support in structs + updates grpc support + CI upgrades (#5943)
38ed69eb3 fixed mutating inline values (#5942)
d026e6f07 Add static asserts to ensure that reflection API arrays are kept in sync (#5934)
988164f6e [C++] Got rid of memset's in constructors (#5938)
7179a5a8b General Codebase clean up (#5939)
a0da0c08c Add GetStringView like GetString, GetCstring (#5937)
ac203b209 [C#] Add file identifier to ObjectAPI Serialization Utility. (#5920)
8dd1bf25b not creating creation methods when using structs (#5919)
5aa443d98 [Dart] Adding FlexBuffers support (#5853)
0fa087657 [Dart] Getting tests/DartTest.sh to work on master. (#5915)
424a473e1 Schema parser: prohibit declaration of an array of pointers inside structs (#5907)
c3faa8346 Fix Cargo.toml dependencies (#5911)
91399ad05 fix union type names (#5902)
32782e4ad Update Rust Flexbuffers metadata before publishing (#5905)
e7f3b1690 [TS] Make Obj-API work with --short-names (#5898)
12ed1fe4a fixed invalid imports with --gen-all (#5895)
85ee4df7a [C#] Thread safe reads of Double and Float values from a ByteBuffer (#5900)
de89bd193 Implement flexbuffers in python (#5880)
8be05f6bd Rust Flexbuffers (#5669)
870ecbc09 [swift] Moves code to use VTablesStorage (#5888)
c2da8d5d8 [Java][FlexBuffers] Make FlexBuffersBuilder reusable by adding clear() (#5889) (#5890)
e84cbff67 Align package name to FindFlatBuffers.cmake (#5899)
f94e6c84e Small tutorial improvements - documentation only (#5894)
f12cca8bc Attempt at adding Github Actions CI
7e4124d6e Handle git program or .git folder absence (#5878)
a875d247a only add native_include_files if object based api is enabled (#5886)
6e9f5d981 Respect shared attribute in Parser (#5885)
ff1c78233 include/flatbuffers: typo fixes in comments (#5884)
2e9a19673 Updates swift docs for package management (#5883)
e3cb07d32 [Rust] idl_gen_rust.cpp: (Option/required-aware codegen for unions) (#5850)
712866d57 Propagate use_string_pooling in CopyTable (#5879)
44c919a9e Not using reexports with --gen-all (#5873)
99aa1ef21 Added INCLUDE_PREFIX option for flatbuffers_generate_headers (#5866)
40ba170c9 Fixed text in internals doc that implied structs can be root
cb4d0f72e [Swift] Object API support  (#5826)
003e16405 [TS] Add Obj API (#5788)
21cf300f4 fix cpp usage markdown error (#5845)
9655e12d6 Upgraded swift implementation for grpc (#5843)
fb96fadc2 [C#] Fix nested structs and arrays in Object API (#5765)
408f11fbd [ts] Fix empty source/dest namespaces when reexporting. (#5841)
a83caf591 Improves performance for the swift library by using structs + a storage class (#5835)
925fab6b1 [Java][FlexBuffers] Optimize Map access (#5735)
d9fecc332 [CMake] : Add precompiled header support with FLATBUFFERS_ENABLE_PCH (#5827)
e9d453240 Added flatbuffers_generate_headers and flatbuffers_generate_binary_files cmake functions. (#5830)
c37c989ed Correct calculation of vector element size (#5831)
6b271b7ec Fix Clang-trunk warnings about special members deprecated in C++20. (#5829)
90f3b8e8c Fix `float_constant` definition in './doc/Grammar.md` (#5828)
3af735934 [csharp] flatc should generate a 'Create…' method for tables with struct field… (#5818)
c4231c3cb Updated doxyfile - added missing files (#5824)
9657df184 Update Grammar.md (#5820)
97ffc590e Include CPack only when explictly packaging (#5817)
8b52af65b [C++] Add max_depth and max_tables parameters to reflection::Verify (#5815)
9b034eee1 Fix interpretation of 'nan(number)' by the idl_parser (#5810)
3e9ac3cff [Scripts] Adds swift to generated code (#5806)
697147a2e updated maven build files
6df40a247 pre-tag version bump for 1.12
0dba63909 Removes the inner loop in the endtable check written tables (#5803)
0e3fdd0ee Escape characters in jsonschema descriptions (#5644)
45a2b07cb Remove `noexcept` qualifier copy-ctor of `union` type (#5800) (#5802)
d10c16314 Replace 'assert' by 'FLATBUFFERS_ASSERT' inside idl_parser.cpp (#5799)
35abb7f89 Add non-nullable modifier to return type of functions never returning null (#5797)
9954e09ab [C++] Generate code for vector force_align attribute. (#5796)
95a21327f rust: pub export the VectorIter type (#5736)
89b6183ee Fix Python min alignment
5a98d65e8 [Rust] Add gen-name-strings for Rust (#5757)
f73d205bc Removed assert that wasn't backwards compatible.
7c37abe92 [C#] add ObjectAPI Serialization Utility (#5785)
4749e77b0 Fixed docs on how to obtain parser error.
6ff189841 Added --filename-suffix and --filename-ext to flatc (#5778)
c9a30c9ca Fixed refractoring issue in reflection/generate_code.sh. Also, mv deletes the original file, so I don't need to clean it up manually in that case. (#5777)
8c02d17be Skip writing reflection_generated.h if not changed (#5776)
34305c4ce [Swift] Adds GRPC to Swift (#5758)
cd88e6b2a [Java][FlexBuffers] Abstract buffer access from ByteBuffer (#5743)
3ec7a53c6 Adds cocoapods and a readme of how to get the package (#5771)
6d44cede7 [snap] Fix versioning (#5727)
cc08c0835 [Python] Fixed potential allignment issue (#5768)
54f8b787c Fix memory leak on cpp object api (#5761)
17557f913 [Python] Fixed issue #5499 (#5764)
d54af8cd4 [C++] Use strong enum type for vectors when scoped-enums is on. (#5750)
173e10fdf [C#] support Json Serialization (#5752)
8f56990f6 FlexBuffers: C++: scalar-only typed vectors were not aligned.
6400c9b05 Bump Rust port to 0.6.1 (#5747)
7418d8587 [C#] support Object API (#5710)
c580fa284 Adds min and max, comments, and all of swift's keywords + fix docs (#5737)
f2a127230 Use VS 2017 and 2019 on CI, fix cast issue in dart_idl (#5740)
316d7c208 Creates a flatbuffers validation function + small fix (#5725)
47026ea6b Added the code to embed the binary schema to the source (--bfbs-gen-embed). (#5701)
3f677f241 [Java][FlexBuffers] Deprecate typed vector strings due to design flaw (#5722)
a593a11e5 [Go] Implements a SharedStrings function (#5733)
7cdfc8475 [Swift] Fix padding function overflow when bufSize is 0 (#5721)
bab2b0db4 Add vcpkg installation instructions (#5732)
89418eb84 [Dart] Fix deprecated field support, inf/nan (#5724)
9cadf05d8 [typescript] Size-prefixed root accessors not taking into account size prefix (#5717)
6da1cf79d [rust] Add use declarations to Rust-generated bindings for imported FB definitions (#5645)
bee1df96d [Go] Replace references to hardcoded ”Monster" etc with idiomatic go wherever possible (#5716)
01189d7ed [C++] Fix for printing of enum in case output_enum_identifiers=1. (#5706)
c4b2b0a25 [Swift] Support create long string (#5709)
a4b2884e4 Added create function for swift (#5707)
04d80f255 [Swift] Swift implementation 🎉🎉 (#5603)
55686100a Changed direct calls to strtod to use StringToNumber
718351831 Document JSON compatibility guarantees. (#5704)
d1b34f0f2 Add CMake 'generated_code' target to simplify resolution of build dependencies (#5697)
21b706196 (Optionally) add an additional suffix namespace to generated fbs files. (#5698)
35daaf83d [Java] Replace Table.UTF8_CHARSET with StandardCharsets.UTF_8 (#5696)
3b458f7a1 Rust: Temporarily disable 2 endianness unit tests (#5695)
a5d9d0f7d [C++17] Add Traits class for Tables and Factory function within it. (#5678)
3cd9b6434 Removed code_generators.cpp from library targets
355dfd48d [rust] Make enum names public (#5690)
bcd58a159 Correct inverted logic around include prefixes. (#5689)
a2c12900a Optimize Pack method using numpy (#5662)
901b89e73 [C++] Add Builder and Table typedefs (#5685)
31f879908 Minor doc updates: FlexBuffers C#, Discord, CppUsage.
8023d99e2 Upgrade rules_go (#5684)
b4154405d Fix --incompatible_load_cc_rules_from_bzl (#5683)
04c17c7a7 Add support for absl::string_view when available (#5682)
62ec7d52c [Bazel] Add support for compatible_with and restricted_to (#5681)
7de668053 CI: New Docker tests for Python with numpy (#5677)
3a70e0b30 Fixed struct initialization error on older versions of C#
9b1320135 Fixed warnings in FlexBuffers.java
5e3916050 Fixed out of date licenses on gRPC Python files.
c95755051 Removed test proto output.
44bf71988 Add flatc '--cpp_std' switch (#5656)
3e8f15df9 Fix for FlexBuffers FBT_VECTOR_STRING size bit-width.
602721a73 Added Check to VerifyAlignment (#5675)
13c05f4da Improve import handling for proto conversion (#5673)
ce3a1c43a [Dart] Fix prepare space for writeListInt64 and writeListUint64 (#5654)
aa75e5734 Make Rust constants public (#5659)
2790fee25 Add namespace qualification to union types (#5666)
eddebec1b Bugfix for Rust generation of union fields named with language keywords (#5592)
030fee36a wrap multiple statements in do {} while(!IsConstTrue(true)) (#5655)
f9724d1bd [gRPC] Uncomment MessageBuilder (#5658)
b20801ca4 Supress unsigned-integer-overflow for PaddingBytes (#5647)
a8e800bd7 Add --force-empty-vectors option (#5653)
d7530ae96 Fixed enum min/max values not properly escaped.
99d11e279 Split Bazel targets into multiple packages (#5640)
4fd8eb214 Remove a static_assert (#5643)
65f870357 Flatbuffers Python Object API (#5616)
75823cc27 [Clang 10]: definition of implicit copy constructor for 'TableKeyComparatoris deprecated #5649 (#5650)
58e279244 [docs]: add missing semicolon (#5648)
3c964e10a [GO] Fix support for enums with underscores and Unions with imported members (#5600)
c3c32ec94 Fix ambiguity of a type deduction in TEST_EQ macro if arguments have `enum class` type. (#5630)
075e8d676 Simplify declarations of x-macro FLATBUFFERS_TD (#5638)
bcf1bd5c9 read vtable size through ReadScalar() (#5636)
136d75fa6 Changed null checks in test. Removed verifier pointer usage (#5634)
091fa1fd1 Add testing of C++ with sanitizers (CI-Docker) (#5631)
ff3781dc2 add namespace prefix in FLATBUFFERS_MAX_BUFFER_SIZE (#5629)
6beb9f49c Support for python grpc - continuing the work from the pull request #4270 #4705 (#5613)
80988ea86 Removed idl_gen_general.cpp and move contents to code_generators.cpp (#5625)
0f2ff7eaa Lua cleanup (#5624)
dda095023 [C++] Adds basic schema evolution tests (#5611)
adbcbba5d [C++, C#, Java] Separated C# and Java generators into their own classes (#5618)
cbbd6aca0 add check for root_type specified for json schema generation (#5622)
405c64e07 [Rust] Bump smallvec version to 1.0 (#5621)
42c08cbca Ran src/clang-format-all.sh (#5617)
33d5dd9bd Improved pull request & clang-format instructions.
105dd528e Change monster_extra generation to use flatbuffers::unique_ptr (#5612)
f0f0efe7b [C++] Refactor to conform to Google C++ style guide (#5608)
e837d5a29 Fixed deprecated method in GRPC Java test.
9834ee978 Fixed Apache license not using canonical version.
44b2ab087 include/flatbuffers/base.h: fix no_sanitize issue with old clang (#5610)
46ae3f80a [C++, Java, C#, TypeScript, JavaScript] Skip generation of mutable union types (#5599)
7b38aa71e flatbuffers.h: fix documentation warning (#5607)
661bedd83 Add Lua FlatbufferBuilder Clean() method to enable reuseable builders (#5606)
8526e12d7 [Kotlin] Fix union vector accessor after change in Java API (#5605)
3c7b660d6 [flatc] Remove an always true condition for flexbuffers (#5604)
964365ba6 [Go] Add UnPackTo functions (#5598)
32254b7ac [Go] Object API support (#5339)
521e255ad Rust: Add idiomatic iterator for Vector type (#5579)
1b85292fd Fix typos in comments (#5590)
480815447 C++ verifier for evolved union fields should return true (#5586)
8d5e424c6 Add ByteBuffer copy for vector of bytes in Java (#5587)
b4774d235 Rust: Fix Copy and Clone impls for a few generic types (#5577)
26f238c24 Add `--clean-first` to the cmake-build command (travis) (#5574)
e93c8c46e Fix Follow implementation for bool (#5554)
e21516b9d Fix issue #5557 (#5573)
fbc11e8ae Avoid intentional unsigned integer overflow getting caught by sanitizers (#5572)
e9d29c21a Python: Add forceDefaults opt to python Builder (#5564)
8bfafc76d Java: Don't annotate vector-of-tables item getters with @nullable. (#5562)
df3e8bf4a Fixed warnings generated by recent JSON sorting feature.
5665cfe49 [Java] byte buffer factory returned buffer capcity is used instead of the requested size (#5558)
5797540ed #5544 Fix of Array of table is not sorted if Create<type>Direct() is used (#5546)
7f1af7cb0 Fix build with gcc version 7.4.0 (#5570)
32f47ad24 Fixed JSON parser not sorting vectors of tables/structs with key.
842f672ba [FlexBuffers][Java] Cache size of Sized objects in FlexBuffers (#5551)
d4cae0a62 Fix issue #5542 (#5543)
f1147f65b Fixed Android STLPort related error.
69d3fec48 Fix namespaced struct/field name collision detection (#5540) (#5545)
cfb4ecf6f [flac] Add FlexBuffers option for generating data (#5519)
a92039687 Update Rust versions under test from 1.30.1 to 1.37.0 (#5538)
625338d09 Adds XOPEN_SOURCE for PATH_MAX and POSIX 1993 for stat (#5529)
3f8ce99c5 [FlexBuffers][Java] Add override Key::toString (#5533)
0798b7b69 [FlexBuffers][Java] Fix wrong access to a string using Reference::asString(). (#5532)
cbdf82e2f Fix Mutate() methods of Array<scalar/struct> (override 5508) (#5526)
e365c502f Java: Added access object for vector of struct and vector of tables. (#5233)
97f3aa917 Fixed DetachedBuffer self move assignment (#5521)
2f5bb2eec Fix buildifier warnings found in new bazel (#5517)
917687c7a Fixed Reflection Verifier not handling vectors of unions.
f9277e691 Fixed GenerateText not handling vectors of unions.
2706381ee Add element size parameter to __vector_as_arraysegment [c#] (#5512)
b5560fcd5 [Java][FlexBuffers] Improve documentation for FlexBuffers in Java. (#5506)
782b865c5 Annotate getters with @Pure when --java-checkerframework is specified. (#5510)
3bfc86eaf [Dart]fix: segment fault with empty namespace when generating dart file (#5507)
c0282873f Rust: Fixed cargo clippy on non-generated code (#5485)
4b870aca9 [Javascript] Fix syntax error for signed enum (#5503)
d0e3870c0 [C#] Fix retrieving enumeration vectors as arrays (#5457)
fb25eb87f Doc typo fixes (#5505)
cb35d3a0e Use all of the available space in the buffer returned by ByteBufferFactory to allow the factory to keep a pool of larger than initialsize sized buffers. (#5500)
8e6cabb31 [FlexBuffers][Java] Implementation of FlexBuffers API (#5476)
bd31dd242 Clarified value reuse in FlexBuffers
65b67d213 Fixed test build invocation of arrays_test.fbs
1fbb71132 FlexBuffers: allow any values to be shared.
cd75a3658 Android: remove app_dummy() calls
ec6b0bf29 Fixed STLPort Android compile error
c11b5d744 [bugfix]flexbuffers isvector bugfix (#5488)
4525c91be Fix incorrect padding in arrays of structs (Issue #5484) (#5491)
b97b342f5 Fixed missing generated code.
c1058a903 C++ IDL generation adds superfluous semicolon in GenTablePost, causing (#5483)
303044934 [go]add Name() for ForceCodec  interface (#5486)
a2485d4ec reflection: check for valid union enum value during object verification (#5475)
a20e71ac9 has_method support for primitive fields in java runtime. Changed: idl.h, FlatBufferBuilder.java ,  idl_gen_general.cpp, idl_parser.cpp, flatc.cpp (#5468)

Change-Id: I836f4b43e6818bb16425a87899e6234ac86242aa
git-subtree-dir: third_party/flatbuffers
git-subtree-split: d6a8dbd26ff08a8868e0d0c1b4b67d31b40e4a7f
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index 31b315c..a87fbce 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -15,12 +15,11 @@
  */
 
 #include <algorithm>
+#include <cmath>
 #include <list>
 #include <string>
 #include <utility>
 
-#include <cmath>
-
 #include "flatbuffers/idl.h"
 #include "flatbuffers/util.h"
 
@@ -38,26 +37,22 @@
 
 const double kPi = 3.14159265358979323846;
 
-const char *const kTypeNames[] = {
 // clang-format off
-  #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
-    CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+const char *const kTypeNames[] = {
+  #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
     IDLTYPE,
     FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
   #undef FLATBUFFERS_TD
-  // clang-format on
   nullptr
 };
 
 const char kTypeSizes[] = {
-// clang-format off
-  #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
-      CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
-      sizeof(CTYPE),
+  #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+    sizeof(CTYPE),
     FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
   #undef FLATBUFFERS_TD
-  // clang-format on
 };
+// clang-format on
 
 // The enums in the reflection schema should match the ones we use internally.
 // Compare the last element to check if these go out of sync.
@@ -87,23 +82,45 @@
   return true;
 }
 
+static bool IsLowerSnakeCase(const std::string &str) {
+  for (size_t i = 0; i < str.length(); i++) {
+    char c = str[i];
+    if (!check_ascii_range(c, 'a', 'z') && !is_digit(c) && c != '_') {
+      return false;
+    }
+  }
+  return true;
+}
+
 // Convert an underscore_based_indentifier in to camelCase.
 // Also uppercases the first character if first is true.
 std::string MakeCamel(const std::string &in, bool first) {
   std::string s;
   for (size_t i = 0; i < in.length(); i++) {
     if (!i && first)
-      s += static_cast<char>(toupper(in[0]));
+      s += CharToUpper(in[0]);
     else if (in[i] == '_' && i + 1 < in.length())
-      s += static_cast<char>(toupper(in[++i]));
+      s += CharToUpper(in[++i]);
     else
       s += in[i];
   }
   return s;
 }
 
-void DeserializeDoc( std::vector<std::string> &doc,
-                     const Vector<Offset<String>> *documentation) {
+// Convert an underscore_based_identifier in to screaming snake case.
+std::string MakeScreamingCamel(const std::string &in) {
+  std::string s;
+  for (size_t i = 0; i < in.length(); i++) {
+    if (in[i] != '_')
+      s += CharToUpper(in[i]);
+    else
+      s += in[i];
+  }
+  return s;
+}
+
+void DeserializeDoc(std::vector<std::string> &doc,
+                    const Vector<Offset<String>> *documentation) {
   if (documentation == nullptr) return;
   for (uoffset_t index = 0; index < documentation->size(); index++)
     doc.push_back(documentation->Get(index)->str());
@@ -211,8 +228,7 @@
     #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING,
       FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN)
     #undef FLATBUFFERS_TOKEN
-    #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
-      CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+    #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
       IDLTYPE,
       FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
     #undef FLATBUFFERS_TD
@@ -387,7 +403,8 @@
                   "illegal Unicode sequence (unpaired high surrogate)");
             }
             // reset if non-printable
-            attr_is_trivial_ascii_string_ &= check_ascii_range(*cursor_, ' ', '~');
+            attr_is_trivial_ascii_string_ &=
+                check_ascii_range(*cursor_, ' ', '~');
 
             attribute_ += *cursor_++;
           }
@@ -425,11 +442,11 @@
           cursor_ += 2;
           break;
         }
-        FLATBUFFERS_FALLTHROUGH(); // else fall thru
+        FLATBUFFERS_FALLTHROUGH();  // else fall thru
       default:
         const auto has_sign = (c == '+') || (c == '-');
         // '-'/'+' and following identifier - can be a predefined constant like:
-        // NAN, INF, PI, etc.
+        // NAN, INF, PI, etc or it can be a function name like cos/sin/deg.
         if (IsIdentifierStart(c) || (has_sign && IsIdentifierStart(*cursor_))) {
           // Collect all chars of an identifier:
           const char *start = cursor_ - 1;
@@ -439,14 +456,15 @@
           return NoError();
         }
 
-        auto dot_lvl = (c == '.') ? 0 : 1;  // dot_lvl==0 <=> exactly one '.' seen
-        if (!dot_lvl && !is_digit(*cursor_)) return NoError(); // enum?
+        auto dot_lvl =
+            (c == '.') ? 0 : 1;  // dot_lvl==0 <=> exactly one '.' seen
+        if (!dot_lvl && !is_digit(*cursor_)) return NoError();  // enum?
         // Parser accepts hexadecimal-floating-literal (see C++ 5.13.4).
         if (is_digit(c) || has_sign || !dot_lvl) {
           const auto start = cursor_ - 1;
           auto start_digits = !is_digit(c) ? cursor_ : cursor_ - 1;
-          if (!is_digit(c) && is_digit(*cursor_)){
-            start_digits = cursor_; // see digit in cursor_ position
+          if (!is_digit(c) && is_digit(*cursor_)) {
+            start_digits = cursor_;  // see digit in cursor_ position
             c = *cursor_++;
           }
           // hex-float can't begind with '.'
@@ -489,7 +507,8 @@
         }
         std::string ch;
         ch = c;
-        if (false == check_ascii_range(c, ' ', '~')) ch = "code: " + NumToString(c);
+        if (false == check_ascii_range(c, ' ', '~'))
+          ch = "code: " + NumToString(c);
         return Error("illegal character: " + ch);
     }
   }
@@ -618,12 +637,6 @@
             "length of fixed-length array must be positive and fit to "
             "uint16_t type");
       }
-      // Check if enum arrays are used in C++ without specifying --scoped-enums
-      if ((opts.lang_to_generate & IDLOptions::kCpp) && !opts.scoped_enums &&
-          IsEnum(subtype)) {
-        return Error(
-            "--scoped-enums must be enabled to use enum arrays in C++\n");
-      }
       type = Type(BASE_TYPE_ARRAY, subtype.struct_def, subtype.enum_def,
                   fixed_length);
       NEXT();
@@ -665,18 +678,28 @@
 CheckedError Parser::ParseField(StructDef &struct_def) {
   std::string name = attribute_;
 
-  if (LookupStruct(name))
+  if (LookupCreateStruct(name, false, false))
     return Error("field name can not be the same as table/struct name");
 
+  if (!IsLowerSnakeCase(name)) {
+    Warning("field names should be lowercase snake_case, got: " + name);
+  }
+
   std::vector<std::string> dc = doc_comment_;
   EXPECT(kTokenIdentifier);
   EXPECT(':');
   Type type;
   ECHECK(ParseType(type));
 
-  if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type) &&
-      !IsArray(type))
-    return Error("structs_ may contain only scalar or struct fields");
+  if (struct_def.fixed) {
+    auto valid = IsScalar(type.base_type) || IsStruct(type);
+    if (!valid && IsArray(type)) {
+      const auto &elem_type = type.VectorType();
+      valid |= IsScalar(elem_type.base_type) || IsStruct(elem_type);
+    }
+    if (!valid)
+      return Error("structs may contain only scalar or struct fields");
+  }
 
   if (!struct_def.fixed && IsArray(type))
     return Error("fixed-length array in table must be wrapped in struct");
@@ -693,12 +716,11 @@
     // with a special suffix.
     ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
                     type.enum_def->underlying_type, &typefield));
-  } else if (type.base_type == BASE_TYPE_VECTOR &&
-             type.element == BASE_TYPE_UNION) {
+  } else if (IsVector(type) && type.element == BASE_TYPE_UNION) {
     // Only cpp, js and ts supports the union vector feature so far.
     if (!SupportsAdvancedUnionFeatures()) {
       return Error(
-          "Vectors of unions are not yet supported in all "
+          "Vectors of unions are not yet supported in at least one of "
           "the specified programming languages.");
     }
     // For vector of union fields, add a second auto-generated vector field to
@@ -718,15 +740,44 @@
     if (!IsScalar(type.base_type) ||
         (struct_def.fixed && field->value.constant != "0"))
       return Error(
-            "default values currently only supported for scalars in tables");
+          "default values currently only supported for scalars in tables");
   }
+
+  // Mark the optional scalars. Note that a side effect of ParseSingleValue is
+  // fixing field->value.constant to null.
+  if (IsScalar(type.base_type)) {
+    field->optional = (field->value.constant == "null");
+    if (field->optional) {
+      if (type.enum_def && type.enum_def->Lookup("null")) {
+        FLATBUFFERS_ASSERT(IsInteger(type.base_type));
+        return Error(
+            "the default 'null' is reserved for declaring optional scalar "
+            "fields, it conflicts with declaration of enum '" +
+            type.enum_def->name + "'.");
+      }
+      if (field->attributes.Lookup("key")) {
+        return Error(
+            "only a non-optional scalar field can be used as a 'key' field");
+      }
+      if (!SupportsOptionalScalars()) {
+        return Error(
+            "Optional scalars are not yet supported in at least one the of "
+            "the specified programming languages.");
+      }
+    }
+  } else {
+    // For nonscalars, only required fields are non-optional.
+    // At least until https://github.com/google/flatbuffers/issues/6053
+    field->optional = !field->required;
+  }
+
   // Append .0 if the value has not it (skip hex and scientific floats).
   // This suffix needed for generated C++ code.
   if (IsFloat(type.base_type)) {
     auto &text = field->value.constant;
     FLATBUFFERS_ASSERT(false == text.empty());
     auto s = text.c_str();
-    while(*s == ' ') s++;
+    while (*s == ' ') s++;
     if (*s == '-' || *s == '+') s++;
     // 1) A float constants (nan, inf, pi, etc) is a kind of identifier.
     // 2) A float number needn't ".0" at the end if it has exponent.
@@ -740,15 +791,15 @@
     // Table, struct or string can't have enum_def.
     // Default value of union and vector in NONE, NULL translated to "0".
     FLATBUFFERS_ASSERT(IsInteger(type.base_type) ||
-                       (type.base_type == BASE_TYPE_UNION) ||
-                       (type.base_type == BASE_TYPE_VECTOR) ||
-                       (type.base_type == BASE_TYPE_ARRAY));
-    if (type.base_type == BASE_TYPE_VECTOR) {
+                       (type.base_type == BASE_TYPE_UNION) || IsVector(type) ||
+                       IsArray(type));
+    if (IsVector(type)) {
       // Vector can't use initialization list.
       FLATBUFFERS_ASSERT(field->value.constant == "0");
     } else {
       // All unions should have the NONE ("0") enum value.
       auto in_enum = type.enum_def->attributes.Lookup("bit_flags") ||
+                     field->IsScalarOptional() ||
                      type.enum_def->FindByValue(field->value.constant);
       if (false == in_enum)
         return Error("default value of " + field->value.constant +
@@ -762,7 +813,7 @@
   field->deprecated = field->attributes.Lookup("deprecated") != nullptr;
   auto hash_name = field->attributes.Lookup("hash");
   if (hash_name) {
-    switch ((type.base_type == BASE_TYPE_VECTOR) ? type.element : type.base_type) {
+    switch ((IsVector(type)) ? type.element : type.base_type) {
       case BASE_TYPE_SHORT:
       case BASE_TYPE_USHORT: {
         if (FindHashFunction16(hash_name->constant.c_str()) == nullptr)
@@ -786,7 +837,8 @@
       }
       default:
         return Error(
-            "only short, ushort, int, uint, long and ulong data types support hashing.");
+            "only short, ushort, int, uint, long and ulong data types support "
+            "hashing.");
     }
   }
   auto cpp_type = field->attributes.Lookup("cpp_type");
@@ -805,9 +857,15 @@
   if (field->deprecated && struct_def.fixed)
     return Error("can't deprecate fields in a struct");
   field->required = field->attributes.Lookup("required") != nullptr;
-  if (field->required &&
-      (struct_def.fixed || IsScalar(type.base_type)))
+  if (field->required && (struct_def.fixed || IsScalar(type.base_type)))
     return Error("only non-scalar fields in tables may be 'required'");
+
+  if (!IsScalar(type.base_type)) {
+    // For nonscalars, only required fields are non-optional.
+    // At least until https://github.com/google/flatbuffers/issues/6053
+    field->optional = !field->required;
+  }
+
   field->key = field->attributes.Lookup("key") != nullptr;
   if (field->key) {
     if (struct_def.has_key) return Error("only one field may be set as 'key'");
@@ -849,8 +907,7 @@
   if (field->attributes.Lookup("flexbuffer")) {
     field->flexbuffer = true;
     uses_flexbuffers_ = true;
-    if (type.base_type != BASE_TYPE_VECTOR ||
-        type.element != BASE_TYPE_UCHAR)
+    if (type.base_type != BASE_TYPE_VECTOR || type.element != BASE_TYPE_UCHAR)
       return Error("flexbuffer attribute may only apply to a vector of ubyte");
   }
 
@@ -869,16 +926,23 @@
       val->constant = NumToString(id - 1);
       typefield->attributes.Add("id", val);
     }
+    // if this field is a union that is deprecated,
+    // the automatically added type field should be deprecated as well
+    if (field->deprecated) { typefield->deprecated = true; }
   }
 
   EXPECT(';');
   return NoError();
 }
 
-CheckedError Parser::ParseString(Value &val) {
+CheckedError Parser::ParseString(Value &val, bool use_string_pooling) {
   auto s = attribute_;
   EXPECT(kTokenStringConstant);
-  val.constant = NumToString(builder_.CreateString(s).o);
+  if (use_string_pooling) {
+    val.constant = NumToString(builder_.CreateSharedString(s).o);
+  } else {
+    val.constant = NumToString(builder_.CreateString(s).o);
+  }
   return NoError();
 }
 
@@ -890,8 +954,7 @@
 CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
                                    size_t parent_fieldn,
                                    const StructDef *parent_struct_def,
-                                   uoffset_t count,
-                                   bool inside_vector) {
+                                   uoffset_t count, bool inside_vector) {
   switch (val.type.base_type) {
     case BASE_TYPE_UNION: {
       FLATBUFFERS_ASSERT(field);
@@ -903,14 +966,13 @@
         auto &type = elem->second->value.type;
         if (type.enum_def == val.type.enum_def) {
           if (inside_vector) {
-            if (type.base_type == BASE_TYPE_VECTOR &&
-                type.element == BASE_TYPE_UTYPE) {
+            if (IsVector(type) && 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);
+                  builder_.GetCurrentBufferPointer() + builder_.GetSize() -
+                  offset);
               break;
             }
           } else {
@@ -952,8 +1014,7 @@
         }
       }
       if (constant.empty() && !vector_of_union_types) {
-        return Error("missing type field for this union value: " +
-                     field->name);
+        return Error("missing type field for this union value: " + field->name);
       }
       uint8_t enum_idx;
       if (vector_of_union_types) {
@@ -972,8 +1033,8 @@
           builder_.ClearOffsets();
           val.constant = NumToString(builder_.GetSize());
         }
-      } else if (enum_val->union_type.base_type == BASE_TYPE_STRING) {
-        ECHECK(ParseString(val));
+      } else if (IsString(enum_val->union_type)) {
+        ECHECK(ParseString(val, field->shared));
       } else {
         FLATBUFFERS_ASSERT(false);
       }
@@ -983,7 +1044,7 @@
       ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr));
       break;
     case BASE_TYPE_STRING: {
-      ECHECK(ParseString(val));
+      ECHECK(ParseString(val, field->shared));
       break;
     }
     case BASE_TYPE_VECTOR: {
@@ -1028,10 +1089,9 @@
   builder.AddStructOffset(val.offset, builder.GetSize());
 }
 
-template <typename F>
+template<typename F>
 CheckedError Parser::ParseTableDelimiters(size_t &fieldn,
-                                          const StructDef *struct_def,
-                                          F body) {
+                                          const StructDef *struct_def, F body) {
   // We allow tables both as JSON object{ .. } with field names
   // or vector[..] with all fields in order
   char terminator = '}';
@@ -1167,9 +1227,8 @@
       if (!struct_def.sortbysize ||
           size == SizeOf(field_value.type.base_type)) {
         switch (field_value.type.base_type) {
-          // clang-format off
-          #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
-            CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+// clang-format off
+          #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
             case BASE_TYPE_ ## ENUM: \
               builder_.Pad(field->padding); \
               if (struct_def.fixed) { \
@@ -1183,10 +1242,9 @@
                 builder_.AddElement(field_value.offset, val, valdef); \
               } \
               break;
-            FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD);
+            FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
           #undef FLATBUFFERS_TD
-          #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
-            CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+          #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
             case BASE_TYPE_ ## ENUM: \
               builder_.Pad(field->padding); \
               if (IsStruct(field->value.type)) { \
@@ -1197,7 +1255,7 @@
                 builder_.AddOffset(field_value.offset, val); \
               } \
               break;
-            FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD);
+            FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
           #undef FLATBUFFERS_TD
             case BASE_TYPE_ARRAY:
               builder_.Pad(field->padding);
@@ -1205,7 +1263,7 @@
                 reinterpret_cast<const uint8_t*>(field_value.constant.c_str()),
                 InlineSize(field_value.type));
               break;
-              // clang-format on
+            // clang-format on
         }
       }
     }
@@ -1231,7 +1289,7 @@
   return NoError();
 }
 
-template <typename F>
+template<typename F>
 CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) {
   EXPECT('[');
   for (;;) {
@@ -1245,6 +1303,42 @@
   return NoError();
 }
 
+static bool CompareType(const uint8_t *a, const uint8_t *b, BaseType ftype) {
+  switch (ftype) {
+#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+  case BASE_TYPE_##ENUM: return ReadScalar<CTYPE>(a) < ReadScalar<CTYPE>(b);
+    FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
+#undef FLATBUFFERS_TD
+    case BASE_TYPE_STRING:
+      // Indirect offset pointer to string pointer.
+      a += ReadScalar<uoffset_t>(a);
+      b += ReadScalar<uoffset_t>(b);
+      return *reinterpret_cast<const String *>(a) <
+             *reinterpret_cast<const String *>(b);
+    default: return false;
+  }
+}
+
+// See below for why we need our own sort :(
+template<typename T, typename F, typename S>
+void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) {
+  if (end - begin <= static_cast<ptrdiff_t>(width)) return;
+  auto l = begin + width;
+  auto r = end;
+  while (l < r) {
+    if (comparator(begin, l)) {
+      r -= width;
+      swapper(l, r);
+    } else {
+      l += width;
+    }
+  }
+  l -= width;
+  swapper(begin, l);
+  SimpleQsort(begin, l, width, comparator, swapper);
+  SimpleQsort(r, end, width, comparator, swapper);
+}
+
 CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
                                  FieldDef *field, size_t fieldn) {
   uoffset_t count = 0;
@@ -1259,15 +1353,21 @@
   });
   ECHECK(err);
 
-  builder_.StartVector(count * InlineSize(type) / InlineAlignment(type),
-                       InlineAlignment(type));
+  const auto *force_align = field->attributes.Lookup("force_align");
+  const size_t align =
+      force_align ? static_cast<size_t>(atoi(force_align->constant.c_str()))
+                  : 1;
+  const size_t len = count * InlineSize(type) / InlineAlignment(type);
+  const size_t elemsize = InlineAlignment(type);
+  if (align > 1) { builder_.ForceVectorAlignment(len, elemsize, align); }
+
+  builder_.StartVector(len, elemsize);
   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) {
-      // clang-format off
-      #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
-        CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+// clang-format off
+      #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE,...) \
         case BASE_TYPE_ ## ENUM: \
           if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \
           else { \
@@ -1285,6 +1385,75 @@
 
   builder_.ClearOffsets();
   *ovalue = builder_.EndVector(count);
+
+  if (type.base_type == BASE_TYPE_STRUCT && type.struct_def->has_key) {
+    // We should sort this vector. Find the key first.
+    const FieldDef *key = nullptr;
+    for (auto it = type.struct_def->fields.vec.begin();
+         it != type.struct_def->fields.vec.end(); ++it) {
+      if ((*it)->key) {
+        key = (*it);
+        break;
+      }
+    }
+    FLATBUFFERS_ASSERT(key);
+    // Now sort it.
+    // We can't use std::sort because for structs the size is not known at
+    // compile time, and for tables our iterators dereference offsets, so can't
+    // be used to swap elements.
+    // And we can't use C qsort either, since that would force use to use
+    // globals, making parsing thread-unsafe.
+    // So for now, we use SimpleQsort above.
+    // TODO: replace with something better, preferably not recursive.
+    voffset_t offset = key->value.offset;
+    BaseType ftype = key->value.type.base_type;
+
+    if (type.struct_def->fixed) {
+      auto v =
+          reinterpret_cast<VectorOfAny *>(builder_.GetCurrentBufferPointer());
+      SimpleQsort<uint8_t>(
+          v->Data(), v->Data() + v->size() * type.struct_def->bytesize,
+          type.struct_def->bytesize,
+          [&](const uint8_t *a, const uint8_t *b) -> bool {
+            return CompareType(a + offset, b + offset, ftype);
+          },
+          [&](uint8_t *a, uint8_t *b) {
+            // FIXME: faster?
+            for (size_t i = 0; i < type.struct_def->bytesize; i++) {
+              std::swap(a[i], b[i]);
+            }
+          });
+    } else {
+      auto v = reinterpret_cast<Vector<Offset<Table>> *>(
+          builder_.GetCurrentBufferPointer());
+      // Here also can't use std::sort. We do have an iterator type for it,
+      // but it is non-standard as it will dereference the offsets, and thus
+      // can't be used to swap elements.
+      SimpleQsort<Offset<Table>>(
+          v->data(), v->data() + v->size(), 1,
+          [&](const Offset<Table> *_a, const Offset<Table> *_b) -> bool {
+            // Indirect offset pointer to table pointer.
+            auto a = reinterpret_cast<const uint8_t *>(_a) +
+                     ReadScalar<uoffset_t>(_a);
+            auto b = reinterpret_cast<const uint8_t *>(_b) +
+                     ReadScalar<uoffset_t>(_b);
+            // Fetch field address from table.
+            a = reinterpret_cast<const Table *>(a)->GetAddressOf(offset);
+            b = reinterpret_cast<const Table *>(b)->GetAddressOf(offset);
+            return CompareType(a, b, ftype);
+          },
+          [&](Offset<Table> *a, Offset<Table> *b) {
+            // These are serialized offsets, so are relative where they are
+            // stored in memory, so compute the distance between these pointers:
+            ptrdiff_t diff = (b - a) * sizeof(Offset<Table>);
+            FLATBUFFERS_ASSERT(diff >= 0);  // Guaranteed by SimpleQsort.
+            auto udiff = static_cast<uoffset_t>(diff);
+            a->o = EndianScalar(ReadScalar<uoffset_t>(a) - udiff);
+            b->o = EndianScalar(ReadScalar<uoffset_t>(b) + udiff);
+            std::swap(*a, *b);
+          });
+    }
+  }
   return NoError();
 }
 
@@ -1312,8 +1481,7 @@
     auto &val = *it;
     // clang-format off
     switch (val.type.base_type) {
-      #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
-        CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+      #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
         case BASE_TYPE_ ## ENUM: \
           if (IsStruct(val.type)) { \
             SerializeStruct(builder, *val.type.struct_def, val); \
@@ -1362,12 +1530,11 @@
     nested_parser.enums_.dict.clear();
     nested_parser.enums_.vec.clear();
 
-    if (!ok) {
-      ECHECK(Error(nested_parser.error_));
-    }
+    if (!ok) { ECHECK(Error(nested_parser.error_)); }
     // Force alignment for nested flatbuffer
-    builder_.ForceVectorAlignment(nested_parser.builder_.GetSize(), sizeof(uint8_t),
-                                  nested_parser.builder_.GetBufferMinAlignment());
+    builder_.ForceVectorAlignment(
+        nested_parser.builder_.GetSize(), sizeof(uint8_t),
+        nested_parser.builder_.GetBufferMinAlignment());
 
     auto off = builder_.CreateVector(nested_parser.builder_.GetBufferPointer(),
                                      nested_parser.builder_.GetSize());
@@ -1383,13 +1550,13 @@
       auto name = attribute_;
       if (false == (Is(kTokenIdentifier) || Is(kTokenStringConstant)))
         return Error("attribute name must be either identifier or string: " +
-          name);
+                     name);
       if (known_attributes_.find(name) == known_attributes_.end())
         return Error("user define attributes must be declared before use: " +
                      name);
       NEXT();
       auto e = new Value();
-      attributes->Add(name, e);
+      if (attributes->Add(name, e)) Warning("attribute already found: " + name);
       if (Is(':')) {
         NEXT();
         ECHECK(ParseSingleValue(&name, *e, true));
@@ -1404,45 +1571,6 @@
   return NoError();
 }
 
-CheckedError Parser::TryTypedValue(const std::string *name, int dtoken,
-                                   bool check, Value &e, BaseType req,
-                                   bool *destmatch) {
-  bool match = dtoken == token_;
-  if (match) {
-    FLATBUFFERS_ASSERT(*destmatch == false);
-    *destmatch = true;
-    e.constant = attribute_;
-    // Check token match
-    if (!check) {
-      if (e.type.base_type == BASE_TYPE_NONE) {
-        e.type.base_type = req;
-      } else {
-        return Error(
-            std::string("type mismatch: expecting: ") +
-            kTypeNames[e.type.base_type] + ", found: " + kTypeNames[req] +
-            ", name: " + (name ? *name : "") + ", value: " + e.constant);
-      }
-    }
-    // The exponent suffix of hexadecimal float-point number is mandatory.
-    // A hex-integer constant is forbidden as an initializer of float number.
-    if ((kTokenFloatConstant != dtoken) && IsFloat(e.type.base_type)) {
-      const auto &s = e.constant;
-      const auto k = s.find_first_of("0123456789.");
-      if ((std::string::npos != k) && (s.length() > (k + 1)) &&
-          (s[k] == '0' && is_alpha_char(s[k + 1], 'X')) &&
-          (std::string::npos == s.find_first_of("pP", k + 2))) {
-        return Error(
-            "invalid number, the exponent suffix of hexadecimal "
-            "floating-point literals is mandatory: \"" +
-            s + "\"");
-      }
-    }
-
-    NEXT();
-  }
-  return NoError();
-}
-
 CheckedError Parser::ParseEnumFromString(const Type &type,
                                          std::string *result) {
   const auto base_type =
@@ -1531,61 +1659,106 @@
   if (IsInteger(e.type.base_type)) { e.constant = NumToString(val); }
 }
 #if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
-// Normilaze defaults NaN to unsigned quiet-NaN(0).
-static inline void SingleValueRepack(Value& e, float val) {
+// Normalize defaults NaN to unsigned quiet-NaN(0) if value was parsed from
+// hex-float literal.
+static inline void SingleValueRepack(Value &e, float val) {
   if (val != val) e.constant = "nan";
 }
-static inline void SingleValueRepack(Value& e, double val) {
+static inline void SingleValueRepack(Value &e, double val) {
   if (val != val) e.constant = "nan";
 }
 #endif
 
-CheckedError Parser::ParseSingleValue(const std::string *name, Value &e,
-                                      bool check_now) {
-  // First see if this could be a conversion function:
-  if (token_ == kTokenIdentifier && *cursor_ == '(') {
-    // todo: Extract processing of conversion functions to ParseFunction.
-    const auto functionname = attribute_;
-    if (!IsFloat(e.type.base_type)) {
-      return Error(functionname + ": type of argument mismatch, expecting: " +
-                   kTypeNames[BASE_TYPE_DOUBLE] +
-                   ", found: " + kTypeNames[e.type.base_type] +
-                   ", name: " + (name ? *name : "") + ", value: " + e.constant);
+CheckedError Parser::ParseFunction(const std::string *name, Value &e) {
+  // Copy name, attribute will be changed on NEXT().
+  const auto functionname = attribute_;
+  if (!IsFloat(e.type.base_type)) {
+    return Error(functionname + ": type of argument mismatch, expecting: " +
+                 kTypeNames[BASE_TYPE_DOUBLE] +
+                 ", found: " + kTypeNames[e.type.base_type] +
+                 ", name: " + (name ? *name : "") + ", value: " + e.constant);
+  }
+  NEXT();
+  EXPECT('(');
+  ECHECK(Recurse([&]() { return ParseSingleValue(name, e, false); }));
+  EXPECT(')');
+  // calculate with double precision
+  double x, y = 0.0;
+  ECHECK(atot(e.constant.c_str(), *this, &x));
+  // clang-format off
+  auto func_match = false;
+  #define FLATBUFFERS_FN_DOUBLE(name, op) \
+    if (!func_match && functionname == name) { y = op; func_match = true; }
+  FLATBUFFERS_FN_DOUBLE("deg", x / kPi * 180);
+  FLATBUFFERS_FN_DOUBLE("rad", x * kPi / 180);
+  FLATBUFFERS_FN_DOUBLE("sin", sin(x));
+  FLATBUFFERS_FN_DOUBLE("cos", cos(x));
+  FLATBUFFERS_FN_DOUBLE("tan", tan(x));
+  FLATBUFFERS_FN_DOUBLE("asin", asin(x));
+  FLATBUFFERS_FN_DOUBLE("acos", acos(x));
+  FLATBUFFERS_FN_DOUBLE("atan", atan(x));
+  // TODO(wvo): add more useful conversion functions here.
+  #undef FLATBUFFERS_FN_DOUBLE
+  // clang-format on
+  if (true != func_match) {
+    return Error(std::string("Unknown conversion function: ") + functionname +
+                 ", field name: " + (name ? *name : "") +
+                 ", value: " + e.constant);
+  }
+  e.constant = NumToString(y);
+  return NoError();
+}
+
+CheckedError Parser::TryTypedValue(const std::string *name, int dtoken,
+                                   bool check, Value &e, BaseType req,
+                                   bool *destmatch) {
+  bool match = dtoken == token_;
+  if (match) {
+    FLATBUFFERS_ASSERT(*destmatch == false);
+    *destmatch = true;
+    e.constant = attribute_;
+    // Check token match
+    if (!check) {
+      if (e.type.base_type == BASE_TYPE_NONE) {
+        e.type.base_type = req;
+      } else {
+        return Error(
+            std::string("type mismatch: expecting: ") +
+            kTypeNames[e.type.base_type] + ", found: " + kTypeNames[req] +
+            ", name: " + (name ? *name : "") + ", value: " + e.constant);
+      }
+    }
+    // The exponent suffix of hexadecimal float-point number is mandatory.
+    // A hex-integer constant is forbidden as an initializer of float number.
+    if ((kTokenFloatConstant != dtoken) && IsFloat(e.type.base_type)) {
+      const auto &s = e.constant;
+      const auto k = s.find_first_of("0123456789.");
+      if ((std::string::npos != k) && (s.length() > (k + 1)) &&
+          (s[k] == '0' && is_alpha_char(s[k + 1], 'X')) &&
+          (std::string::npos == s.find_first_of("pP", k + 2))) {
+        return Error(
+            "invalid number, the exponent suffix of hexadecimal "
+            "floating-point literals is mandatory: \"" +
+            s + "\"");
+      }
     }
     NEXT();
-    EXPECT('(');
-    ECHECK(Recurse([&]() { return ParseSingleValue(name, e, false); }));
-    EXPECT(')');
-    // calculate with double precision
-    double x, y = 0.0;
-    ECHECK(atot(e.constant.c_str(), *this, &x));
-    auto func_match = false;
-    // clang-format off
-    #define FLATBUFFERS_FN_DOUBLE(name, op) \
-      if (!func_match && functionname == name) { y = op; func_match = true; }
-    FLATBUFFERS_FN_DOUBLE("deg", x / kPi * 180);
-    FLATBUFFERS_FN_DOUBLE("rad", x * kPi / 180);
-    FLATBUFFERS_FN_DOUBLE("sin", sin(x));
-    FLATBUFFERS_FN_DOUBLE("cos", cos(x));
-    FLATBUFFERS_FN_DOUBLE("tan", tan(x));
-    FLATBUFFERS_FN_DOUBLE("asin", asin(x));
-    FLATBUFFERS_FN_DOUBLE("acos", acos(x));
-    FLATBUFFERS_FN_DOUBLE("atan", atan(x));
-    // TODO(wvo): add more useful conversion functions here.
-    #undef FLATBUFFERS_FN_DOUBLE
-    // clang-format on
-    if (true != func_match) {
-      return Error(std::string("Unknown conversion function: ") + functionname +
-                   ", field name: " + (name ? *name : "") +
-                   ", value: " + e.constant);
-    }
-    e.constant = NumToString(y);
-    return NoError();
   }
+  return NoError();
+}
 
-  auto match = false;
+CheckedError Parser::ParseSingleValue(const std::string *name, Value &e,
+                                      bool check_now) {
   const auto in_type = e.type.base_type;
+  const auto is_tok_ident = (token_ == kTokenIdentifier);
+  const auto is_tok_string = (token_ == kTokenStringConstant);
+
+  // First see if this could be a conversion function:
+  if (is_tok_ident && *cursor_ == '(') { return ParseFunction(name, e); }
+
   // clang-format off
+  auto match = false;
+
   #define IF_ECHECK_(force, dtoken, check, req)    \
     if (!match && ((check) || IsConstTrue(force))) \
     ECHECK(TryTypedValue(name, dtoken, check, e, req, &match))
@@ -1593,14 +1766,14 @@
   #define FORCE_ECHECK(dtoken, check, req) IF_ECHECK_(true, dtoken, check, req)
   // clang-format on
 
-  if (token_ == kTokenStringConstant || token_ == kTokenIdentifier) {
+  if (is_tok_ident || is_tok_string) {
     const auto kTokenStringOrIdent = token_;
     // The string type is a most probable type, check it first.
     TRY_ECHECK(kTokenStringConstant, in_type == BASE_TYPE_STRING,
                BASE_TYPE_STRING);
 
     // avoid escaped and non-ascii in the string
-    if (!match && (token_ == kTokenStringConstant) && IsScalar(in_type) &&
+    if (!match && is_tok_string && IsScalar(in_type) &&
         !attr_is_trivial_ascii_string_) {
       return Error(
           std::string("type mismatch or invalid value, an initializer of "
@@ -1618,6 +1791,12 @@
         TRY_ECHECK(kTokenStringOrIdent, IsBool(in_type), BASE_TYPE_BOOL);
       }
     }
+    // Check for optional scalars.
+    if (!match && IsScalar(in_type) && attribute_ == "null") {
+      e.constant = "null";
+      NEXT();
+      match = true;
+    }
     // Check if this could be a string/identifier enum value.
     // Enum can have only true integer base type.
     if (!match && IsInteger(in_type) && !IsBool(in_type) &&
@@ -1628,11 +1807,19 @@
     }
     // Parse a float/integer number from the string.
     if (!match) check_now = true;  // Re-pack if parsed from string literal.
-    if (!match && (token_ == kTokenStringConstant) && IsScalar(in_type)) {
-      // remove trailing whitespaces from attribute_
-      auto last = attribute_.find_last_not_of(' ');
-      if (std::string::npos != last)  // has non-whitespace
-        attribute_.resize(last + 1);
+    // A "scalar-in-string" value needs extra checks.
+    if (!match && is_tok_string && IsScalar(in_type)) {
+      // Strip trailing whitespaces from attribute_.
+      auto last_non_ws = attribute_.find_last_not_of(' ');
+      if (std::string::npos != last_non_ws) attribute_.resize(last_non_ws + 1);
+      if (IsFloat(e.type.base_type)) {
+        // The functions strtod() and strtof() accept both 'nan' and
+        // 'nan(number)' literals. While 'nan(number)' is rejected by the parser
+        // as an unsupported function if is_tok_ident is true.
+        if (attribute_.find_last_of(')') != std::string::npos) {
+          return Error("invalid number: " + attribute_);
+        }
+      }
     }
     // Float numbers or nan, inf, pi, etc.
     TRY_ECHECK(kTokenStringOrIdent, IsFloat(in_type), BASE_TYPE_FLOAT);
@@ -1658,22 +1845,22 @@
            "' to value of <" + std::string(kTypeNames[in_type]) + "> type.";
     return Error(msg);
   }
-  const auto match_type = e.type.base_type; // may differ from in_type
+  const auto match_type = e.type.base_type;  // may differ from in_type
   // The check_now flag must be true when parse a fbs-schema.
   // This flag forces to check default scalar values or metadata of field.
   // For JSON parser the flag should be false.
   // If it is set for JSON each value will be checked twice (see ParseTable).
-  if (check_now && IsScalar(match_type)) {
+  // Special case 'null' since atot can't handle that.
+  if (check_now && IsScalar(match_type) && e.constant != "null") {
     // clang-format off
     switch (match_type) {
-    #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
-            CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
-            case BASE_TYPE_ ## ENUM: {\
-                CTYPE val; \
-                ECHECK(atot(e.constant.c_str(), *this, &val)); \
-                SingleValueRepack(e, val); \
-              break; }
-    FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD);
+    #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+      case BASE_TYPE_ ## ENUM: {\
+          CTYPE val; \
+          ECHECK(atot(e.constant.c_str(), *this, &val)); \
+          SingleValueRepack(e, val); \
+        break; }
+    FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
     #undef FLATBUFFERS_TD
     default: break;
     }
@@ -1865,21 +2052,16 @@
   FLATBUFFERS_CHECKED_ERROR AssignEnumeratorValue(const std::string &value) {
     user_value = true;
     auto fit = false;
-    auto ascending = false;
     if (enum_def.IsUInt64()) {
       uint64_t u64;
       fit = StringToNumber(value.c_str(), &u64);
-      ascending = u64 > temp->GetAsUInt64();
       temp->value = static_cast<int64_t>(u64);  // well-defined since C++20.
     } else {
       int64_t i64;
       fit = StringToNumber(value.c_str(), &i64);
-      ascending = i64 > temp->GetAsInt64();
       temp->value = i64;
     }
     if (!fit) return parser.Error("enum value does not fit, \"" + value + "\"");
-    if (!ascending && strict_ascending && !enum_def.vals.vec.empty())
-      return parser.Error("enum values must be specified in ascending order");
     return NoError();
   }
 
@@ -1902,13 +2084,12 @@
   FLATBUFFERS_CHECKED_ERROR ValidateValue(int64_t *ev, bool next) {
     // clang-format off
     switch (enum_def.underlying_type.base_type) {
-    #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE,   \
-                           PTYPE, RTYPE, KTYPE)                         \
+    #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...)                   \
       case BASE_TYPE_##ENUM: {                                          \
         if (!IsInteger(BASE_TYPE_##ENUM)) break;                        \
         return ValidateImpl<BASE_TYPE_##ENUM, CTYPE>(ev, next ? 1 : 0); \
       }
-      FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD);
+      FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
     #undef FLATBUFFERS_TD
     default: break;
     }
@@ -1916,11 +2097,10 @@
     return parser.Error("fatal: invalid enum underlying type");
   }
 
-  EnumValBuilder(Parser &_parser, EnumDef &_enum_def, bool strict_order = true)
+  EnumValBuilder(Parser &_parser, EnumDef &_enum_def)
       : parser(_parser),
         enum_def(_enum_def),
         temp(nullptr),
-        strict_ascending(strict_order),
         user_value(false) {}
 
   ~EnumValBuilder() { delete temp; }
@@ -1928,7 +2108,6 @@
   Parser &parser;
   EnumDef &enum_def;
   EnumVal *temp;
-  const bool strict_ascending;
   bool user_value;
 };
 
@@ -1965,9 +2144,7 @@
     // todo: Convert to the Error in the future?
     Warning("underlying type of bit_flags enum must be unsigned");
   }
-  // Protobuf allows them to be specified in any order, so sort afterwards.
-  const auto strict_ascending = (false == opts.proto_mode);
-  EnumValBuilder evb(*this, *enum_def, strict_ascending);
+  EnumValBuilder evb(*this, *enum_def);
   EXPECT('{');
   // A lot of code generatos expect that an enum is not-empty.
   if ((is_union || Is('}')) && !opts.proto_mode) {
@@ -2011,9 +2188,6 @@
         NEXT();
         ECHECK(evb.AssignEnumeratorValue(attribute_));
         EXPECT(kTokenIntegerConstant);
-      } else if (false == strict_ascending) {
-        // The opts.proto_mode flag is active.
-        return Error("Protobuf mode doesn't allow implicit enum values.");
       }
 
       ECHECK(evb.AcceptEnumerator());
@@ -2049,8 +2223,18 @@
     }
   }
 
-  if (false == strict_ascending)
-    enum_def->SortByValue();  // Must be sorted to use MinValue/MaxValue.
+  enum_def->SortByValue();  // Must be sorted to use MinValue/MaxValue.
+
+  // Ensure enum value uniqueness.
+  auto prev_it = enum_def->Vals().begin();
+  for (auto it = prev_it + 1; it != enum_def->Vals().end(); ++it) {
+    auto prev_ev = *prev_it;
+    auto ev = *it;
+    if (prev_ev->GetAsUInt64() == ev->GetAsUInt64())
+      return Error("all enum values must be unique: " + prev_ev->name +
+                   " and " + ev->name + " are both " +
+                   NumToString(ev->GetAsInt64()));
+  }
 
   if (dest) *dest = enum_def;
   types_.Add(current_namespace_->GetFullyQualifiedName(enum_def->name),
@@ -2092,13 +2276,28 @@
   return NoError();
 }
 
+bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts) {
+  static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
+      IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster |
+      IDLOptions::kKotlin | IDLOptions::kCpp | IDLOptions::kJava |
+      IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kJs |
+      IDLOptions::kBinary;
+  unsigned long langs = opts.lang_to_generate;
+  return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs);
+}
+
+bool Parser::SupportsOptionalScalars() const {
+  // Check in general if a language isn't specified.
+  return opts.lang_to_generate == 0 || SupportsOptionalScalars(opts);
+}
+
 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 |
-                                    IDLOptions::kKotlin |
-                                    IDLOptions::kBinary)) == 0;
+         (opts.lang_to_generate &
+          ~(IDLOptions::kCpp | IDLOptions::kJs | IDLOptions::kTs |
+            IDLOptions::kPhp | IDLOptions::kJava | IDLOptions::kCSharp |
+            IDLOptions::kKotlin | IDLOptions::kBinary | IDLOptions::kSwift)) ==
+             0;
 }
 
 bool Parser::SupportsAdvancedArrayFeatures() const {
@@ -2370,8 +2569,8 @@
   if (enums_.Add(current_namespace_->GetFullyQualifiedName(enum_name),
                  &enum_def))
     return Error("enum already exists: " + enum_name);
-  enum_def.underlying_type.base_type = is_union ? BASE_TYPE_UTYPE
-                                                : BASE_TYPE_INT;
+  enum_def.underlying_type.base_type =
+      is_union ? BASE_TYPE_UTYPE : BASE_TYPE_INT;
   enum_def.underlying_type.enum_def = &enum_def;
   if (dest) *dest = &enum_def;
   return NoError();
@@ -2479,10 +2678,13 @@
           auto val = attribute_;
           ECHECK(ParseProtoCurliesOrIdent());
           if (key == "default") {
-            // Temp: skip non-numeric defaults (enums).
+            // Temp: skip non-numeric and non-boolean defaults (enums).
             auto numeric = strpbrk(val.c_str(), "0123456789-+.");
-            if (IsScalar(type.base_type) && numeric == val.c_str())
+            if (IsScalar(type.base_type) && numeric == val.c_str()) {
               field->value.constant = val;
+            } else if (val == "true") {
+              field->value.constant = val;
+            }  // "false" is default, no need to handle explicitly.
           } else if (key == "deprecated") {
             field->deprecated = val == "true";
           }
@@ -2507,8 +2709,8 @@
           if (oneof_type.base_type != BASE_TYPE_STRUCT ||
               !oneof_type.struct_def || oneof_type.struct_def->fixed)
             return Error("oneof '" + name +
-                "' cannot be mapped to a union because member '" +
-                oneof_field.name + "' is not a table type.");
+                         "' cannot be mapped to a union because member '" +
+                         oneof_field.name + "' is not a table type.");
           EnumValBuilder evb(*this, *oneof_union);
           auto ev = evb.CreateEnumerator(oneof_type.struct_def->name);
           ev->union_type = oneof_type;
@@ -2667,10 +2869,13 @@
       builder->Int(StringToInt(attribute_.c_str()));
       EXPECT(kTokenIntegerConstant);
       break;
-    case kTokenFloatConstant:
-      builder->Double(strtod(attribute_.c_str(), nullptr));
+    case kTokenFloatConstant: {
+      double d;
+      StringToNumber(attribute_.c_str(), &d);
+      builder->Double(d);
       EXPECT(kTokenFloatConstant);
       break;
+    }
     default:
       if (IsIdent("true")) {
         builder->Bool(true);
@@ -2698,7 +2903,13 @@
 bool Parser::Parse(const char *source, const char **include_paths,
                    const char *source_filename) {
   FLATBUFFERS_ASSERT(0 == recurse_protection_counter);
-  auto r = !ParseRoot(source, include_paths, source_filename).Check();
+  bool r;
+
+  if (opts.use_flexbuffers) {
+    r = ParseFlexBuffer(source, source_filename, &flex_builder_);
+  } else {
+    r = !ParseRoot(source, include_paths, source_filename).Check();
+  }
   FLATBUFFERS_ASSERT(0 == recurse_protection_counter);
   return r;
 }
@@ -2747,7 +2958,7 @@
               if (field.value.type.struct_def == &struct_def) {
                 field.value.type.struct_def = nullptr;
                 field.value.type.enum_def = enum_def;
-                auto &bt = field.value.type.base_type == BASE_TYPE_VECTOR
+                auto &bt = IsVector(field.value.type)
                                ? field.value.type.element
                                : field.value.type.base_type;
                 FLATBUFFERS_ASSERT(bt == BASE_TYPE_STRUCT);
@@ -2785,8 +2996,8 @@
       for (auto val_it = enum_def.Vals().begin();
            val_it != enum_def.Vals().end(); ++val_it) {
         auto &val = **val_it;
-        if (!SupportsAdvancedUnionFeatures() && val.union_type.struct_def &&
-            val.union_type.struct_def->fixed)
+        if (!SupportsAdvancedUnionFeatures() &&
+            (IsStruct(val.union_type) || IsString(val.union_type)))
           return Error(
               "only tables can be union elements in the generated language: " +
               val.name);
@@ -2867,9 +3078,7 @@
         // entered into included_files_.
         // This is recursive, but only go as deep as the number of include
         // statements.
-        if (source_filename) {
-          included_files_.erase(source_filename);
-        }
+        if (source_filename) { included_files_.erase(source_filename); }
         return DoParse(source, include_paths, source_filename,
                        include_filename);
       }
@@ -2893,9 +3102,9 @@
       uoffset_t toff;
       ECHECK(ParseTable(*root_struct_def_, nullptr, &toff));
       if (opts.size_prefixed) {
-        builder_.FinishSizePrefixed(Offset<Table>(toff), file_identifier_.length()
-                                                             ? file_identifier_.c_str()
-                                                             : nullptr);
+        builder_.FinishSizePrefixed(
+            Offset<Table>(toff),
+            file_identifier_.length() ? file_identifier_.c_str() : nullptr);
       } else {
         builder_.Finish(Offset<Table>(toff), file_identifier_.length()
                                                  ? file_identifier_.c_str()
@@ -2916,8 +3125,7 @@
       if (opts.root_type.empty()) {
         if (!SetRootType(root_type.c_str()))
           return Error("unknown root type: " + root_type);
-        if (root_struct_def_->fixed)
-          return Error("root type must be a table");
+        if (root_struct_def_->fixed) return Error("root type must be a table");
       }
       EXPECT(';');
     } else if (IsIdent("file_identifier")) {
@@ -3022,10 +3230,9 @@
   auto fiid__ = builder_.CreateString(file_identifier_);
   auto fext__ = builder_.CreateString(file_extension_);
   auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets);
-  auto schema_offset =
-      reflection::CreateSchema(builder_, objs__, enum__, fiid__, fext__,
-        (root_struct_def_ ? root_struct_def_->serialized_location : 0),
-        serv__);
+  auto schema_offset = reflection::CreateSchema(
+      builder_, objs__, enum__, fiid__, fext__,
+      (root_struct_def_ ? root_struct_def_->serialized_location : 0), serv__);
   if (opts.size_prefixed) {
     builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier());
   } else {
@@ -3071,22 +3278,20 @@
   auto flds__ = builder->CreateVectorOfSortedTables(&field_offsets);
   auto attr__ = SerializeAttributes(builder, parser);
   auto docs__ = parser.opts.binary_schema_comments
-                ? builder->CreateVectorOfStrings(doc_comment)
-                : 0;
+                    ? builder->CreateVectorOfStrings(doc_comment)
+                    : 0;
   return reflection::CreateObject(*builder, name__, flds__, fixed,
                                   static_cast<int>(minalign),
-                                  static_cast<int>(bytesize),
-                                  attr__, docs__);
+                                  static_cast<int>(bytesize), attr__, docs__);
 }
 
 bool StructDef::Deserialize(Parser &parser, const reflection::Object *object) {
-  if (!DeserializeAttributes(parser, object->attributes()))
-    return false;
+  if (!DeserializeAttributes(parser, object->attributes())) return false;
   DeserializeDoc(doc_comment, object->documentation());
   name = parser.UnqualifiedName(object->name()->str());
   predecl = false;
   sortbysize = attributes.Lookup("original_order") == nullptr && !fixed;
-  const auto& of = *(object->fields());
+  const auto &of = *(object->fields());
   auto indexes = std::vector<uoffset_t>(of.size());
   for (uoffset_t i = 0; i < of.size(); i++) indexes[of.Get(i)->id()] = i;
   size_t tmp_struct_size = 0;
@@ -3102,9 +3307,7 @@
       // Recompute padding since that's currently not serialized.
       auto size = InlineSize(field_def->value.type);
       auto next_field =
-          i + 1 < indexes.size()
-          ? of.Get(indexes[i+1])
-          : nullptr;
+          i + 1 < indexes.size() ? of.Get(indexes[i + 1]) : nullptr;
       tmp_struct_size += size;
       field_def->padding =
           next_field ? (next_field->offset() - field_def->value.offset) - size
@@ -3123,15 +3326,17 @@
   auto type__ = value.type.Serialize(builder);
   auto attr__ = SerializeAttributes(builder, parser);
   auto docs__ = parser.opts.binary_schema_comments
-                ? builder->CreateVectorOfStrings(doc_comment)
-                : 0;
-  return reflection::CreateField(*builder, name__, type__, id, value.offset,
+                    ? builder->CreateVectorOfStrings(doc_comment)
+                    : 0;
+  double d;
+  StringToNumber(value.constant.c_str(), &d);
+  return reflection::CreateField(
+      *builder, name__, type__, id, value.offset,
       // Is uint64>max(int64) tested?
       IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0,
       // result may be platform-dependent if underlying is float (not double)
-      IsFloat(value.type.base_type) ? strtod(value.constant.c_str(), nullptr)
-                                    : 0.0,
-      deprecated, required, key, attr__, docs__);
+      IsFloat(value.type.base_type) ? d : 0.0, deprecated, required, key,
+      attr__, docs__, optional);
   // TODO: value.constant is almost always "0", we could save quite a bit of
   // space by sharing it. Same for common values of value.type.
 }
@@ -3139,23 +3344,17 @@
 bool FieldDef::Deserialize(Parser &parser, const reflection::Field *field) {
   name = field->name()->str();
   defined_namespace = parser.current_namespace_;
-  if (!value.type.Deserialize(parser, field->type()))
-    return false;
+  if (!value.type.Deserialize(parser, field->type())) return false;
   value.offset = field->offset();
   if (IsInteger(value.type.base_type)) {
     value.constant = NumToString(field->default_integer());
   } else if (IsFloat(value.type.base_type)) {
     value.constant = FloatToString(field->default_real(), 16);
-    size_t last_zero = value.constant.find_last_not_of('0');
-    if (last_zero != std::string::npos && last_zero != 0) {
-      value.constant.erase(last_zero, std::string::npos);
-    }
   }
   deprecated = field->deprecated();
   required = field->required();
   key = field->key();
-  if (!DeserializeAttributes(parser, field->attributes()))
-    return false;
+  if (!DeserializeAttributes(parser, field->attributes())) return false;
   // TODO: this should probably be handled by a separate attribute
   if (attributes.Lookup("flexbuffer")) {
     flexbuffer = true;
@@ -3170,6 +3369,7 @@
     nested_flatbuffer = parser.LookupStruct(nested_qualified_name);
     if (!nested_flatbuffer) return false;
   }
+  shared = attributes.Lookup("shared") != nullptr;
   DeserializeDoc(doc_comment, field->documentation());
   return true;
 }
@@ -3179,18 +3379,16 @@
   auto name__ = builder->CreateString(name);
   auto attr__ = SerializeAttributes(builder, parser);
   auto docs__ = parser.opts.binary_schema_comments
-                ? builder->CreateVectorOfStrings(doc_comment)
-                : 0;
-  return reflection::CreateRPCCall(*builder, name__,
-                                   request->serialized_location,
-                                   response->serialized_location,
-                                   attr__, docs__);
+                    ? builder->CreateVectorOfStrings(doc_comment)
+                    : 0;
+  return reflection::CreateRPCCall(
+      *builder, name__, request->serialized_location,
+      response->serialized_location, attr__, docs__);
 }
 
 bool RPCCall::Deserialize(Parser &parser, const reflection::RPCCall *call) {
   name = call->name()->str();
-  if (!DeserializeAttributes(parser, call->attributes()))
-    return false;
+  if (!DeserializeAttributes(parser, call->attributes())) return false;
   DeserializeDoc(doc_comment, call->documentation());
   request = parser.structs_.Lookup(call->request()->name()->str());
   response = parser.structs_.Lookup(call->response()->name()->str());
@@ -3209,8 +3407,8 @@
   auto call__ = builder->CreateVector(servicecall_offsets);
   auto attr__ = SerializeAttributes(builder, parser);
   auto docs__ = parser.opts.binary_schema_comments
-                ? builder->CreateVectorOfStrings(doc_comment)
-                : 0;
+                    ? builder->CreateVectorOfStrings(doc_comment)
+                    : 0;
   return reflection::CreateService(*builder, name__, call__, attr__, docs__);
 }
 
@@ -3227,8 +3425,7 @@
       }
     }
   }
-  if (!DeserializeAttributes(parser, service->attributes()))
-    return false;
+  if (!DeserializeAttributes(parser, service->attributes())) return false;
   DeserializeDoc(doc_comment, service->documentation());
   return true;
 }
@@ -3245,8 +3442,8 @@
   auto type__ = underlying_type.Serialize(builder);
   auto attr__ = SerializeAttributes(builder, parser);
   auto docs__ = parser.opts.binary_schema_comments
-                ? builder->CreateVectorOfStrings(doc_comment)
-                : 0;
+                    ? builder->CreateVectorOfStrings(doc_comment)
+                    : 0;
   return reflection::CreateEnum(*builder, name__, vals__, is_union, type__,
                                 attr__, docs__);
 }
@@ -3265,8 +3462,7 @@
   if (!underlying_type.Deserialize(parser, _enum->underlying_type())) {
     return false;
   }
-  if (!DeserializeAttributes(parser, _enum->attributes()))
-    return false;
+  if (!DeserializeAttributes(parser, _enum->attributes())) return false;
   DeserializeDoc(doc_comment, _enum->documentation());
   return true;
 }
@@ -3276,9 +3472,10 @@
   auto name__ = builder->CreateString(name);
   auto type__ = union_type.Serialize(builder);
   auto docs__ = parser.opts.binary_schema_comments
-                ? builder->CreateVectorOfStrings(doc_comment)
-                : 0;
-  return reflection::CreateEnumVal(*builder, name__, value,
+                    ? builder->CreateVectorOfStrings(doc_comment)
+                    : 0;
+  return reflection::CreateEnumVal(
+      *builder, name__, value,
       union_type.struct_def ? union_type.struct_def->serialized_location : 0,
       type__, docs__);
 }
@@ -3287,8 +3484,7 @@
                           const reflection::EnumVal *val) {
   name = val->name()->str();
   value = val->value();
-  if (!union_type.Deserialize(parser, val->union_type()))
-    return false;
+  if (!union_type.Deserialize(parser, val->union_type())) return false;
   DeserializeDoc(doc_comment, val->documentation());
   return true;
 }
@@ -3310,8 +3506,7 @@
     bool is_series = type->base_type() == reflection::Vector ||
                      type->base_type() == reflection::Array;
     if (type->base_type() == reflection::Obj ||
-        (is_series &&
-         type->element() == reflection::Obj)) {
+        (is_series && type->element() == reflection::Obj)) {
       if (static_cast<size_t>(type->index()) < parser.structs_.vec.size()) {
         struct_def = parser.structs_.vec[type->index()];
         struct_def->refcount++;
@@ -3352,8 +3547,7 @@
 
 bool Definition::DeserializeAttributes(
     Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs) {
-  if (attrs == nullptr)
-    return true;
+  if (attrs == nullptr) return true;
   for (uoffset_t i = 0; i < attrs->size(); ++i) {
     auto kv = attrs->Get(i);
     auto value = new Value();
@@ -3373,7 +3567,7 @@
 bool Parser::Deserialize(const uint8_t *buf, const size_t size) {
   flatbuffers::Verifier verifier(reinterpret_cast<const uint8_t *>(buf), size);
   bool size_prefixed = false;
-  if(!reflection::SchemaBufferHasIdentifier(buf)) {
+  if (!reflection::SchemaBufferHasIdentifier(buf)) {
     if (!flatbuffers::BufferHasIdentifier(buf, reflection::SchemaIdentifier(),
                                           true))
       return false;
@@ -3382,9 +3576,7 @@
   }
   auto verify_fn = size_prefixed ? &reflection::VerifySizePrefixedSchemaBuffer
                                  : &reflection::VerifySchemaBuffer;
-  if (!verify_fn(verifier)) {
-    return false;
-  }
+  if (!verify_fn(verifier)) { return false; }
   auto schema = size_prefixed ? reflection::GetSizePrefixedSchema(buf)
                               : reflection::GetSchema(buf);
   return Deserialize(schema);
@@ -3433,7 +3625,7 @@
     auto struct_def = structs_.Lookup(qualified_name);
     struct_def->defined_namespace =
         GetNamespace(qualified_name, namespaces_, namespaces_index);
-    if (!struct_def->Deserialize(*this, * it)) { return false; }
+    if (!struct_def->Deserialize(*this, *it)) { return false; }
     if (schema->root_table() == *it) { root_struct_def_ = struct_def; }
   }
   for (auto it = schema->enums()->begin(); it != schema->enums()->end(); ++it) {