Squashed 'third_party/flatbuffers/' changes from d6a8dbd26..338393f85

338393f85 Documentation updates for Optional Scalars (#6014) (#6270)
c27bc2d76 [C++] Add ParseJson(), Parser(Parser&&), update fuzzers (#6284)
bc518a512 Fixed FlexBufferBuilder asserting on duplicate keys
100c59054 Added a few more paths for auto labeler (#6281)
e58c18244 Add --require-explicit-ids to require explicit ids (#6277)
69a8b2a57 idl_gen_json_schema.cpp: Changed generation of array element types (#6253)
25eba6f35 fix typo (#6280)
e1f0f75ba Updated Ms build Action to fix build issue (#6279)
faeb04fbe Add type annotation to unspecified array (#6264)
537212afe [Swift] Adds a format file and reformats the swift project (#6250)
6764f25d9 Adds a fix for enum generation (#6263)

Change-Id: I716bd4d2521fb0a673e50a699cef761e042052b2
git-subtree-dir: third_party/flatbuffers
git-subtree-split: 338393f854eb5ba24761a22cd9316ff5cee4eab0
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index a87fbce..6d916e5 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -2379,11 +2379,18 @@
       if ((*it)->attributes.Lookup("id")) num_id_fields++;
     }
     // If any fields have ids..
-    if (num_id_fields) {
+    if (num_id_fields || opts.require_explicit_ids) {
       // Then all fields must have them.
-      if (num_id_fields != fields.size())
-        return Error(
-            "either all fields or no fields must have an 'id' attribute");
+      if (num_id_fields != fields.size()) {
+        if (opts.require_explicit_ids) {
+          return Error(
+              "all fields must have an 'id' attribute when "
+              "--require-explicit-ids is used");
+        } else {
+          return Error(
+              "either all fields or no fields must have an 'id' attribute");
+        }
+      }
       // Simply sort by id, then the fields are the same as if no ids had
       // been specified.
       std::sort(fields.begin(), fields.end(), compareFieldDefs);
@@ -2850,6 +2857,8 @@
                                });
       ECHECK(err);
       builder->EndMap(start);
+      if (builder->HasDuplicateKeys())
+        return Error("FlexBuffers map has duplicate keys");
       break;
     }
     case '[': {
@@ -2914,6 +2923,15 @@
   return r;
 }
 
+bool Parser::ParseJson(const char *json, const char *json_filename) {
+  FLATBUFFERS_ASSERT(0 == recurse_protection_counter);
+  builder_.Clear();
+  const auto done =
+      !StartParseFile(json, json_filename).Check() && !DoParseJson().Check();
+  FLATBUFFERS_ASSERT(0 == recurse_protection_counter);
+  return done;
+}
+
 CheckedError Parser::StartParseFile(const char *source,
                                     const char *source_filename) {
   file_being_parsed_ = source_filename ? source_filename : "";
@@ -3094,25 +3112,7 @@
     } else if (IsIdent("namespace")) {
       ECHECK(ParseNamespace());
     } else if (token_ == '{') {
-      if (!root_struct_def_)
-        return Error("no root type set to parse json with");
-      if (builder_.GetSize()) {
-        return Error("cannot have more than one json object in a file");
-      }
-      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);
-      } else {
-        builder_.Finish(Offset<Table>(toff), file_identifier_.length()
-                                                 ? file_identifier_.c_str()
-                                                 : nullptr);
-      }
-      // Check that JSON file doesn't contain more objects or IDL directives.
-      // Comments after JSON are allowed.
-      EXPECT(kTokenEof);
+      ECHECK(DoParseJson());
     } else if (IsIdent("enum")) {
       ECHECK(ParseEnum(false, nullptr));
     } else if (IsIdent("union")) {
@@ -3163,6 +3163,34 @@
   return NoError();
 }
 
+CheckedError Parser::DoParseJson()
+{
+  if (token_ != '{') {
+    EXPECT('{');
+  } else {
+    if (!root_struct_def_)
+      return Error("no root type set to parse json with");
+    if (builder_.GetSize()) {
+      return Error("cannot have more than one json object in a file");
+    }
+    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);
+    } else {
+      builder_.Finish(Offset<Table>(toff), file_identifier_.length()
+                                                ? file_identifier_.c_str()
+                                                : nullptr);
+    }
+  }
+  // Check that JSON file doesn't contain more objects or IDL directives.
+  // Comments after JSON are allowed.
+  EXPECT(kTokenEof);
+  return NoError();
+}
+
 std::set<std::string> Parser::GetIncludedFilesRecursive(
     const std::string &file_name) const {
   std::set<std::string> included_files;