Merge commit '6dccd64de51ea960cb6f0d975768c874814b4c75' into HEAD
Update flatbuffers. Relevant merge tasks:
* A field got added to reflection.fbs; this had fallout in
reflection_generated.h and the logger_test shas.
* Resolved merge conflict in rust/flatbuffers/src/lib.rs
* Reverted upstream change that made Table rust struct members private.
* FlatBufferBuilder Create*Vector calls now include alignment.
* nim codegen got added; needed to update to use scoped enums.
Main fix that motivated this update is
https://github.com/google/flatbuffers/pull/7588
Change-Id: I6bbe5d56846f426fa5f2a82c4f2bc77be2b93bb0
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
diff --git a/third_party/flatbuffers/src/BUILD.bazel b/third_party/flatbuffers/src/BUILD.bazel
index 8110be4..e8c3ffb 100644
--- a/third_party/flatbuffers/src/BUILD.bazel
+++ b/third_party/flatbuffers/src/BUILD.bazel
@@ -39,6 +39,8 @@
"bfbs_gen.h",
"bfbs_gen_lua.cpp",
"bfbs_gen_lua.h",
+ "bfbs_gen_nim.cpp",
+ "bfbs_gen_nim.h",
"bfbs_namer.h",
"binary_annotator.cpp",
"binary_annotator.h",
@@ -62,6 +64,8 @@
"bfbs_gen.h",
"bfbs_gen_lua.cpp",
"bfbs_gen_lua.h",
+ "bfbs_gen_nim.cpp",
+ "bfbs_gen_nim.h",
"bfbs_namer.h",
"flatc_main.cpp",
"idl_gen_cpp.cpp",
diff --git a/third_party/flatbuffers/src/annotated_binary_text_gen.cpp b/third_party/flatbuffers/src/annotated_binary_text_gen.cpp
index ec30b1d..1c7a4dd 100644
--- a/third_party/flatbuffers/src/annotated_binary_text_gen.cpp
+++ b/third_party/flatbuffers/src/annotated_binary_text_gen.cpp
@@ -1,5 +1,6 @@
#include "annotated_binary_text_gen.h"
+#include <algorithm>
#include <sstream>
#include <string>
diff --git a/third_party/flatbuffers/src/bfbs_gen.h b/third_party/flatbuffers/src/bfbs_gen.h
index 63220e8..8e3c6f3 100644
--- a/third_party/flatbuffers/src/bfbs_gen.h
+++ b/third_party/flatbuffers/src/bfbs_gen.h
@@ -38,8 +38,9 @@
for (auto it = objects->cbegin(); it != objects->cend(); ++it) { func(*it); }
}
-static void ForAllEnumValues(const reflection::Enum *enum_def,
- std::function<void(const reflection::EnumVal *)> func) {
+static void ForAllEnumValues(
+ const reflection::Enum *enum_def,
+ std::function<void(const reflection::EnumVal *)> func) {
for (auto it = enum_def->values()->cbegin(); it != enum_def->values()->cend();
++it) {
func(*it);
@@ -91,7 +92,7 @@
return base_type == reflection::BaseType::Vector;
}
-} // namespace
+} // namespace
// A concrete base Flatbuffer Generator that specific language generators can
// derive from.
@@ -130,17 +131,29 @@
}
protected:
- const reflection::Object *GetObject(const reflection::Type *type) const {
- if (type->index() >= 0 && IsStructOrTable(type->base_type())) {
+ // GetObject returns the underlying object struct of the given type
+ // if element_type is true and GetObject is a list of objects then
+ // GetObject will correctly return the object struct of the vector's elements
+ const reflection::Object *GetObject(const reflection::Type *type,
+ bool element_type = false) const {
+ const reflection::BaseType base_type =
+ element_type ? type->element() : type->base_type();
+ if (type->index() >= 0 && IsStructOrTable(base_type)) {
return GetObjectByIndex(type->index());
}
return nullptr;
}
- const reflection::Enum *GetEnum(const reflection::Type *type) const {
+ // GetEnum returns the underlying enum struct of the given type
+ // if element_type is true and GetEnum is a list of enums then
+ // GetEnum will correctly return the enum struct of the vector's elements
+ const reflection::Enum *GetEnum(const reflection::Type *type,
+ bool element_type = false) const {
+ const reflection::BaseType base_type =
+ element_type ? type->element() : type->base_type();
// TODO(derekbailey): it would be better to have a explicit list of allowed
// base types, instead of negating Obj types.
- if (type->index() >= 0 && !IsStructOrTable(type->base_type())) {
+ if (type->index() >= 0 && !IsStructOrTable(base_type)) {
return GetEnumByIndex(type->index());
}
return nullptr;
diff --git a/third_party/flatbuffers/src/bfbs_gen_lua.cpp b/third_party/flatbuffers/src/bfbs_gen_lua.cpp
index e9623d4..1bfe8b2 100644
--- a/third_party/flatbuffers/src/bfbs_gen_lua.cpp
+++ b/third_party/flatbuffers/src/bfbs_gen_lua.cpp
@@ -175,7 +175,7 @@
// Skip writing deprecated fields altogether.
if (field->deprecated()) { return; }
- const std::string field_name = namer_.Field(field->name()->str());
+ const std::string field_name = namer_.Field(*field);
const r::BaseType base_type = field->type()->base_type();
// Generate some fixed strings so we don't repeat outselves later.
@@ -367,9 +367,8 @@
ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
if (field->deprecated()) { return; }
- const std::string field_name = namer_.Field(field->name()->str());
- const std::string variable_name =
- namer_.Variable(field->name()->str());
+ const std::string field_name = namer_.Field(*field);
+ const std::string variable_name = namer_.Variable(*field);
code += "function " + object_name + ".Add" + field_name +
"(builder, " + variable_name + ")\n";
@@ -428,9 +427,9 @@
if (IsStructOrTable(field->type()->base_type())) {
const r::Object *field_object = GetObject(field->type());
signature += GenerateStructBuilderArgs(
- field_object, prefix + namer_.Variable(field->name()->str()) + "_");
+ field_object, prefix + namer_.Variable(*field) + "_");
} else {
- signature += ", " + prefix + namer_.Variable(field->name()->str());
+ signature += ", " + prefix + namer_.Variable(*field);
}
});
return signature;
@@ -451,11 +450,11 @@
}
if (IsStructOrTable(field->type()->base_type())) {
const r::Object *field_object = GetObject(field->type());
- code += AppendStructBuilderBody(
- field_object, prefix + namer_.Variable(field->name()->str()) + "_");
+ code += AppendStructBuilderBody(field_object,
+ prefix + namer_.Variable(*field) + "_");
} else {
code += " builder:Prepend" + GenerateMethod(field) + "(" + prefix +
- namer_.Variable(field->name()->str()) + ")\n";
+ namer_.Variable(*field) + ")\n";
}
});
diff --git a/third_party/flatbuffers/src/bfbs_gen_nim.cpp b/third_party/flatbuffers/src/bfbs_gen_nim.cpp
new file mode 100644
index 0000000..dcd4cde
--- /dev/null
+++ b/third_party/flatbuffers/src/bfbs_gen_nim.cpp
@@ -0,0 +1,651 @@
+/*
+ * Copyright 2021 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "bfbs_gen_nim.h"
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+// Ensure no includes to flatc internals. bfbs_gen.h and generator.h are OK.
+#include "bfbs_gen.h"
+#include "bfbs_namer.h"
+#include "flatbuffers/bfbs_generator.h"
+
+// The intermediate representation schema.
+#include "flatbuffers/reflection.h"
+#include "flatbuffers/reflection_generated.h"
+
+namespace flatbuffers {
+namespace {
+
+// To reduce typing
+namespace r = ::reflection;
+
+std::set<std::string> NimKeywords() {
+ return {
+ "addr", "and", "as", "asm", "bind", "block",
+ "break", "case", "cast", "concept", "const", "continue",
+ "converter", "defer", "discard", "distinct", "div", "do",
+ "elif", "else", "end", "enum", "except", "export",
+ "finally", "for", "from", "func", "if", "import",
+ "in", "include", "interface", "is", "isnot", "iterator",
+ "let", "macro", "method", "mixin", "mod", "nil",
+ "not", "notin", "object", "of", "or", "out",
+ "proc", "ptr", "raise", "ref", "return", "shl",
+ "shr", "static", "template", "try", "tuple", "type",
+ "using", "var", "when", "while", "xor", "yield",
+ };
+}
+
+Namer::Config NimDefaultConfig() {
+ return { /*types=*/Case::kUpperCamel,
+ /*constants=*/Case::kUpperCamel,
+ /*methods=*/Case::kLowerCamel,
+ /*functions=*/Case::kUpperCamel,
+ /*fields=*/Case::kLowerCamel,
+ /*variable=*/Case::kLowerCamel,
+ /*variants=*/Case::kUpperCamel,
+ /*enum_variant_seperator=*/".",
+ /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
+ /*namespaces=*/Case::kKeep,
+ /*namespace_seperator=*/"/",
+ /*object_prefix=*/"",
+ /*object_suffix=*/"T",
+ /*keyword_prefix=*/"",
+ /*keyword_suffix=*/"_",
+ /*filenames=*/Case::kKeep,
+ /*directories=*/Case::kKeep,
+ /*output_path=*/"",
+ /*filename_suffix=*/"",
+ /*filename_extension=*/".nim" };
+}
+
+const std::string Indent = " ";
+const std::string Export = "*";
+const std::set<std::string> builtin_types = {
+ "uint8", "uint8", "bool", "int8", "uint8", "int16",
+ "uint16", "int32", "uint32", "int64", "uint64", "float32",
+ "float64", "string", "int", "uint", "uoffset", "Builder"
+};
+
+class NimBfbsGenerator : public BaseBfbsGenerator {
+ public:
+ explicit NimBfbsGenerator(const std::string &flatc_version)
+ : BaseBfbsGenerator(),
+ keywords_(),
+ imports_(),
+ current_obj_(nullptr),
+ current_enum_(nullptr),
+ flatc_version_(flatc_version),
+ namer_(NimDefaultConfig(), NimKeywords()) {}
+
+ GeneratorStatus GenerateFromSchema(const r::Schema *schema)
+ FLATBUFFERS_OVERRIDE {
+ ForAllEnums(schema->enums(), [&](const r::Enum *enum_def) {
+ StartCodeBlock(enum_def);
+ GenerateEnum(enum_def);
+ });
+ ForAllObjects(schema->objects(), [&](const r::Object *object) {
+ StartCodeBlock(object);
+ GenerateObject(object);
+ });
+ return OK;
+ }
+
+ uint64_t SupportedAdvancedFeatures() const FLATBUFFERS_OVERRIDE {
+ return static_cast<uint64_t>(r::AdvancedFeatures::AdvancedArrayFeatures) |
+ static_cast<uint64_t>(r::AdvancedFeatures::AdvancedUnionFeatures) |
+ static_cast<uint64_t>(r::AdvancedFeatures::OptionalScalars) |
+ static_cast<uint64_t>(r::AdvancedFeatures::DefaultVectorsAndStrings);
+ }
+
+ protected:
+ void GenerateEnum(const r::Enum *enum_def) {
+ std::string code;
+
+ std::string ns;
+ const std::string enum_name = namer_.Type(namer_.Denamespace(enum_def, ns));
+ const std::string enum_type =
+ GenerateTypeBasic(enum_def->underlying_type());
+
+ GenerateDocumentation(enum_def->documentation(), "", code);
+ code += "type " + enum_name + Export + "{.pure.} = enum\n";
+
+ ForAllEnumValues(enum_def, [&](const reflection::EnumVal *enum_val) {
+ GenerateDocumentation(enum_val->documentation(), " ", code);
+ code += " " + namer_.Variant(enum_val->name()->str()) + " = " +
+ NumToString(enum_val->value()) + "." + enum_type + ",\n";
+ });
+
+ EmitCodeBlock(code, enum_name, ns, enum_def->declaration_file()->str());
+ }
+
+ void GenerateObject(const r::Object *object) {
+ // Register the main flatbuffers module.
+ RegisterImports("flatbuffers", "");
+ std::string code;
+
+ std::string ns;
+ const std::string object_name = namer_.Type(namer_.Denamespace(object, ns));
+
+ GenerateDocumentation(object->documentation(), "", code);
+ code += "type " + object_name + "* = object of FlatObj\n";
+
+ // Create all the field accessors.
+ ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
+ // Skip writing deprecated fields altogether.
+ if (field->deprecated()) { return; }
+
+ const std::string field_name = namer_.Field(*field);
+ const r::BaseType base_type = field->type()->base_type();
+ std::string field_type = GenerateType(field->type());
+
+ if (field->optional() && !object->is_struct()) {
+ RegisterImports("std/options", "");
+ field_type = "Option[" + field_type + "]";
+ }
+
+ const std::string offset_prefix =
+ "let o = self.tab.Offset(" + NumToString(field->offset()) + ")\n";
+ const std::string offset_prefix_2 = "if o != 0:\n";
+
+ if (IsScalar(base_type) || base_type == r::BaseType::String ||
+ base_type == r::BaseType::Obj || base_type == r::BaseType::Union) {
+ GenerateDocumentation(field->documentation(), "", code);
+
+ std::string getter_signature = "func " + namer_.Method(field_name) +
+ "*(self: " + object_name +
+ "): " + field_type + " =\n";
+ std::string getter_code;
+ std::string setter_signature =
+ "func `" + namer_.Method(field_name + "=") + "`*(self: var " +
+ object_name + ", n: " + field_type + "): bool =\n";
+ std::string setter_code;
+
+ if (base_type == r::BaseType::Obj || base_type == r::BaseType::Union ||
+ field->type()->index() >= 0) {
+ RegisterImports(object, field);
+ }
+
+ if (object->is_struct()) {
+ std::string field_getter =
+ GenerateGetter(field->type(), NumToString(field->offset()));
+ getter_code += " return " + field_getter + "\n";
+
+ if (IsScalar(base_type)) {
+ setter_code += " return self.tab.Mutate(self.tab.Pos + " +
+ NumToString(field->offset()) + ", n)\n";
+ }
+ } else {
+ // Table accessors
+ getter_code += " " + offset_prefix;
+ getter_code += " " + offset_prefix_2;
+ std::string field_getter = GenerateGetter(field->type(), "o");
+ if (field->optional()) {
+ field_getter = "some(" + field_getter + ")";
+ }
+ getter_code += " return " + field_getter + "\n";
+ if (!field->optional()) {
+ getter_code += " return " + DefaultValue(field) + "\n";
+ }
+
+ if (IsScalar(base_type)) {
+ setter_code += " return self.tab.MutateSlot(" +
+ NumToString(field->offset()) + ", n)\n";
+ }
+ }
+ code += getter_signature + getter_code;
+ if (IsScalar(base_type)) { code += setter_signature + setter_code; }
+ } else if (base_type == r::BaseType::Array ||
+ base_type == r::BaseType::Vector) {
+ const r::BaseType vector_base_type = field->type()->element();
+ uint32_t element_size = field->type()->element_size();
+
+ if (vector_base_type == r::BaseType::Obj ||
+ vector_base_type == r::BaseType::Union ||
+ field->type()->index() >= 0) {
+ RegisterImports(object, field, true);
+ }
+
+ // Get vector length:
+ code += "func " + namer_.Method(field_name + "Length") +
+ "*(self: " + object_name + "): int = \n";
+ code += " " + offset_prefix;
+ code += " " + offset_prefix_2;
+ code += " return self.tab.VectorLen(o)\n";
+
+ // Get single vector field:
+ code += "func " + namer_.Method(field_name) + "*(self: " + object_name +
+ ", j: int): " + GenerateType(field->type(), true) + " = \n";
+ code += " " + offset_prefix;
+ code += " " + offset_prefix_2;
+ code += " var x = self.tab.Vector(o)\n";
+ code +=
+ " x += j.uoffset * " + NumToString(element_size) + ".uoffset\n";
+ code += " return " + GenerateGetter(field->type(), "x", true) + "\n";
+
+ // Get entire vector:
+ code += "func " + namer_.Method(field_name) + "*(self: " + object_name +
+ "): " + GenerateType(field->type()) + " = \n";
+ code += " let len = self." + field_name + "Length\n";
+ code += " for i in countup(0, len - 1):\n";
+ code += " result.add(self." + field_name + "(i))\n";
+
+ (void)IsSingleByte(vector_base_type); // unnused function warning
+ }
+ });
+
+ // Create all the builders
+ if (object->is_struct()) {
+ code += "proc " + namer_.Function(object_name + "Create") +
+ "*(self: var Builder";
+ code += GenerateStructBuilderArgs(object);
+ code += "): uoffset =\n";
+ code += AppendStructBuilderBody(object);
+ code += " return self.Offset()\n";
+ } else {
+ // Table builders
+ code += "proc " + namer_.Function(object_name + "Start") +
+ "*(builder: var Builder) =\n";
+ code += " builder.StartObject(" + NumToString(object->fields()->size()) +
+ ")\n";
+
+ ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
+ if (field->deprecated()) { return; }
+
+ const std::string field_name = namer_.Field(*field);
+ const std::string variable_name = namer_.Variable(*field);
+ const std::string variable_type = GenerateTypeBasic(field->type());
+
+ code += "proc " + namer_.Function(object_name + "Add" + field_name) +
+ "*(builder: var Builder, " + variable_name + ": " +
+ variable_type + ") =\n";
+ code += " builder.Prepend" + GenerateMethod(field) + "Slot(" +
+ NumToString(field->id()) + ", " + variable_name + ", default(" +
+ variable_type + "))\n";
+
+ if (IsVector(field->type()->base_type())) {
+ code += "proc " +
+ namer_.Function(object_name + "Start" + field_name) +
+ "Vector*(builder: var Builder, numElems: uoffset) =\n";
+
+ const int32_t element_size = field->type()->element_size();
+ int32_t alignment = element_size;
+ if (IsStruct(field->type(), /*use_element=*/true)) {
+ alignment = GetObjectByIndex(field->type()->index())->minalign();
+ }
+
+ code += " builder.StartVector(" + NumToString(element_size) +
+ ", numElems, " + NumToString(alignment) + ")\n";
+ }
+ });
+
+ code += "proc " + namer_.Function(object_name + "End") +
+ "*(builder: var Builder): uoffset =\n";
+ code += " return builder.EndObject()\n";
+ }
+ EmitCodeBlock(code, object_name, ns, object->declaration_file()->str());
+ }
+
+ private:
+ void GenerateDocumentation(
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>
+ *documentation,
+ std::string indent, std::string &code) const {
+ flatbuffers::ForAllDocumentation(
+ documentation, [&](const flatbuffers::String *str) {
+ code += indent + "# " + str->str() + "\n";
+ });
+ }
+
+ std::string GenerateStructBuilderArgs(const r::Object *object,
+ std::string prefix = "") const {
+ std::string signature;
+ ForAllFields(object, /*reverse=*/false, [&](const r::Field *field) {
+ if (IsStructOrTable(field->type()->base_type())) {
+ const r::Object *field_object = GetObject(field->type());
+ signature += GenerateStructBuilderArgs(
+ field_object, prefix + namer_.Variable(*field) + "_");
+ } else {
+ signature += ", " + prefix + namer_.Variable(*field) + ": " +
+ GenerateType(field->type());
+ }
+ });
+ return signature;
+ }
+
+ std::string AppendStructBuilderBody(const r::Object *object,
+ std::string prefix = "") const {
+ std::string code;
+ code += " self.Prep(" + NumToString(object->minalign()) + ", " +
+ NumToString(object->bytesize()) + ")\n";
+
+ // We need to reverse the order we iterate over, since we build the
+ // buffer backwards.
+ ForAllFields(object, /*reverse=*/true, [&](const r::Field *field) {
+ const int32_t num_padding_bytes = field->padding();
+ if (num_padding_bytes) {
+ code += " self.Pad(" + NumToString(num_padding_bytes) + ")\n";
+ }
+ if (IsStructOrTable(field->type()->base_type())) {
+ const r::Object *field_object = GetObject(field->type());
+ code += AppendStructBuilderBody(field_object,
+ prefix + namer_.Variable(*field) + "_");
+ } else {
+ code += " self.Prepend(" + prefix + namer_.Variable(*field) + ")\n";
+ }
+ });
+
+ return code;
+ }
+
+ std::string GenerateMethod(const r::Field *field) const {
+ const r::BaseType base_type = field->type()->base_type();
+ if (IsStructOrTable(base_type)) { return "Struct"; }
+ return "";
+ }
+
+ std::string GenerateGetter(const r::Type *type, const std::string &offsetval,
+ bool element_type = false) const {
+ const r::BaseType base_type =
+ element_type ? type->element() : type->base_type();
+ std::string offset = offsetval;
+ if (!element_type) { offset = "self.tab.Pos + " + offset; }
+ switch (base_type) {
+ case r::BaseType::String: return "self.tab.String(" + offset + ")";
+ case r::BaseType::Union: return "self.tab.Union(" + offsetval + ")";
+ case r::BaseType::Obj: {
+ return GenerateType(type, element_type) +
+ "(tab: Vtable(Bytes: self.tab.Bytes, Pos: " + offset + "))";
+ }
+ case r::BaseType::Vector: return GenerateGetter(type, offsetval, true);
+ default:
+ const r::Enum *type_enum = GetEnum(type, element_type);
+ if (type_enum != nullptr) {
+ return GenerateType(type, element_type) + "(" + "Get[" +
+ GenerateType(base_type) + "](self.tab, " + offset + ")" + ")";
+ } else {
+ return "Get[" + GenerateType(base_type) + "](self.tab, " + offset +
+ ")";
+ }
+ }
+ }
+
+ std::string Denamespace(const std::string &s, std::string &importns,
+ std::string &ns) const {
+ if (builtin_types.find(s) != builtin_types.end()) { return s; }
+ std::string type = namer_.Type(namer_.Denamespace(s, ns));
+ importns = ns.empty() ? type : ns + "." + type;
+ std::replace(importns.begin(), importns.end(), '.', '_');
+ return type;
+ }
+
+ std::string Denamespace(const std::string &s, std::string &importns) const {
+ std::string ns;
+ return Denamespace(s, importns, ns);
+ }
+
+ std::string Denamespace(const std::string &s) const {
+ std::string importns;
+ return Denamespace(s, importns);
+ }
+
+ std::string GenerateType(const r::Type *type, bool element_type = false,
+ bool enum_inner = false) const {
+ const r::BaseType base_type =
+ element_type ? type->element() : type->base_type();
+ if (IsScalar(base_type) && !enum_inner) {
+ const r::Enum *type_enum = GetEnum(type, element_type);
+ if (type_enum != nullptr) {
+ std::string importns;
+ std::string type_name = Denamespace(type_enum->name()->str(), importns);
+ return importns + "." + type_name;
+ }
+ }
+ if (IsScalar(base_type)) { return Denamespace(GenerateType(base_type)); }
+ switch (base_type) {
+ case r::BaseType::String: return "string";
+ case r::BaseType::Vector: {
+ return "seq[" + GenerateType(type, true) + "]";
+ }
+ case r::BaseType::Union: return "Vtable";
+ case r::BaseType::Obj: {
+ const r::Object *type_obj = GetObject(type, element_type);
+ std::string importns;
+ std::string type_name = Denamespace(type_obj->name()->str(), importns);
+ if (type_obj == current_obj_) {
+ return type_name;
+ } else {
+ return importns + "." + type_name;
+ }
+ }
+ default: return "uoffset";
+ }
+ }
+
+ std::string GenerateTypeBasic(const r::Type *type,
+ bool element_type = false) const {
+ const r::BaseType base_type =
+ element_type ? type->element() : type->base_type();
+ if (IsScalar(base_type)) {
+ return GenerateType(base_type);
+ } else {
+ return "uoffset";
+ }
+ }
+
+ std::string GenerateType(const r::BaseType base_type) const {
+ switch (base_type) {
+ case r::BaseType::None: return "uint8";
+ case r::BaseType::UType: return "uint8";
+ case r::BaseType::Bool: return "bool";
+ case r::BaseType::Byte: return "int8";
+ case r::BaseType::UByte: return "uint8";
+ case r::BaseType::Short: return "int16";
+ case r::BaseType::UShort: return "uint16";
+ case r::BaseType::Int: return "int32";
+ case r::BaseType::UInt: return "uint32";
+ case r::BaseType::Long: return "int64";
+ case r::BaseType::ULong: return "uint64";
+ case r::BaseType::Float: return "float32";
+ case r::BaseType::Double: return "float64";
+ case r::BaseType::String: return "string";
+ default: return r::EnumNameBaseType(base_type);
+ }
+ }
+
+ std::string DefaultValue(const r::Field *field) const {
+ const r::BaseType base_type = field->type()->base_type();
+ if (IsFloatingPoint(base_type)) {
+ if (field->default_real() != field->default_real()) {
+ return "NaN";
+ } else if (field->default_real() == std::numeric_limits<double>::infinity()) {
+ return "Inf";
+ } else if (field->default_real() == -std::numeric_limits<double>::infinity()) {
+ return "-Inf";
+ }
+ return NumToString(field->default_real());
+ }
+ if (IsBool(base_type)) {
+ return field->default_integer() ? "true" : "false";
+ }
+ if (IsScalar(base_type)) {
+ const r::Enum *type_enum = GetEnum(field->type());
+ if (type_enum != nullptr) {
+ return "type(result)(" + NumToString((field->default_integer())) + ")";
+ }
+ return NumToString((field->default_integer()));
+ }
+ if (base_type == r::BaseType::String) { return "\"\""; }
+ // represents offsets
+ return "0";
+ }
+
+ void StartCodeBlock(const reflection::Enum *enum_def) {
+ current_enum_ = enum_def;
+ current_obj_ = nullptr;
+ imports_.clear();
+ }
+
+ void StartCodeBlock(const reflection::Object *object) {
+ current_enum_ = nullptr;
+ current_obj_ = object;
+ imports_.clear();
+ }
+
+ std::vector<std::string> StringSplit(const std::string orig_str,
+ const std::string token) {
+ std::vector<std::string> result;
+ std::string str = orig_str;
+ while (str.size()) {
+ size_t index = str.find(token);
+ if (index != std::string::npos) {
+ result.push_back(str.substr(0, index));
+ str = str.substr(index + token.size());
+ if (str.size() == 0) result.push_back(str);
+ } else {
+ result.push_back(str);
+ str = "";
+ }
+ }
+ return result;
+ }
+
+ std::string GetRelativePathFromNamespace(const std::string &relative_to,
+ const std::string &str2) {
+ std::vector<std::string> relative_to_vec = StringSplit(relative_to, ".");
+ std::vector<std::string> str2_vec = StringSplit(str2, ".");
+ while (relative_to_vec.size() > 0 && str2_vec.size() > 0) {
+ if (relative_to_vec[0] == str2_vec[0]) {
+ relative_to_vec.erase(relative_to_vec.begin());
+ str2_vec.erase(str2_vec.begin());
+ } else {
+ break;
+ }
+ }
+ relative_to_vec.pop_back();
+ for (size_t i = 0; i < relative_to_vec.size(); ++i) {
+ str2_vec.insert(str2_vec.begin(), std::string(".."));
+ }
+
+ std::string new_path;
+ for (size_t i = 0; i < str2_vec.size(); ++i) {
+ new_path += str2_vec[i];
+ if (i != str2_vec.size() - 1) { new_path += "/"; }
+ }
+ return new_path;
+ }
+
+ void RegisterImports(const r::Object *object, const r::Field *field,
+ bool use_element = false) {
+ std::string importns;
+ std::string type_name;
+
+ const r::BaseType type =
+ use_element ? field->type()->element() : field->type()->base_type();
+
+ if (IsStructOrTable(type)) {
+ const r::Object *object_def = GetObjectByIndex(field->type()->index());
+ if (object_def == current_obj_) { return; }
+ std::string ns;
+ type_name = Denamespace(object_def->name()->str(), importns, ns);
+ type_name = ns.empty() ? type_name : ns + "." + type_name;
+ } else {
+ const r::Enum *enum_def = GetEnumByIndex(field->type()->index());
+ if (enum_def == current_enum_) { return; }
+ std::string ns;
+ type_name = Denamespace(enum_def->name()->str(), importns, ns);
+ type_name = ns.empty() ? type_name : ns + "." + type_name;
+ }
+
+ std::string import_path =
+ GetRelativePathFromNamespace(object->name()->str(), type_name);
+ std::replace(type_name.begin(), type_name.end(), '.', '_');
+ RegisterImports(import_path, importns);
+ }
+
+ void RegisterImports(const std::string &local_name,
+ const std::string &imports_name) {
+ imports_[local_name] = imports_name;
+ }
+
+ void EmitCodeBlock(const std::string &code_block, const std::string &name,
+ const std::string &ns, const std::string &declaring_file) {
+ const std::string full_qualified_name = ns.empty() ? name : ns + "." + name;
+
+ std::string code = "#[ " + full_qualified_name + "\n";
+ code +=
+ " Automatically generated by the FlatBuffers compiler, do not "
+ "modify.\n";
+ code += " Or modify. I'm a message, not a cop.\n";
+ code += "\n";
+ code += " flatc version: " + flatc_version_ + "\n";
+ code += "\n";
+ code += " Declared by : " + declaring_file + "\n";
+ if (schema_->root_table() != nullptr) {
+ const std::string root_type = schema_->root_table()->name()->str();
+ const std::string root_file =
+ schema_->root_table()->declaration_file()->str();
+ code += " Rooting type : " + root_type + " (" + root_file + ")\n";
+ }
+ code += "]#\n\n";
+
+ if (!imports_.empty()) {
+ for (auto it = imports_.cbegin(); it != imports_.cend(); ++it) {
+ if (it->second.empty()) {
+ code += "import " + it->first + "\n";
+ } else {
+ code += "import " + it->first + " as " + it->second + "\n";
+ }
+ }
+ code += "\n";
+ }
+ code += code_block;
+
+ // Namespaces are '.' deliminted, so replace it with the path separator.
+ std::string path = ns;
+
+ if (ns.empty()) {
+ path = ".";
+ } else {
+ std::replace(path.begin(), path.end(), '.', '/');
+ }
+
+ // TODO(derekbailey): figure out a save file without depending on util.h
+ EnsureDirExists(path);
+ const std::string file_name = path + "/" + namer_.File(name);
+ SaveFile(file_name.c_str(), code, false);
+ }
+
+ std::unordered_set<std::string> keywords_;
+ std::map<std::string, std::string> imports_;
+ const r::Object *current_obj_;
+ const r::Enum *current_enum_;
+ const std::string flatc_version_;
+ const BfbsNamer namer_;
+};
+} // namespace
+
+std::unique_ptr<BfbsGenerator> NewNimBfbsGenerator(
+ const std::string &flatc_version) {
+ return std::unique_ptr<NimBfbsGenerator>(new NimBfbsGenerator(flatc_version));
+}
+
+} // namespace flatbuffers
diff --git a/third_party/flatbuffers/src/bfbs_gen_nim.h b/third_party/flatbuffers/src/bfbs_gen_nim.h
new file mode 100644
index 0000000..80be16d
--- /dev/null
+++ b/third_party/flatbuffers/src/bfbs_gen_nim.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FLATBUFFERS_BFBS_GEN_NIM_H_
+#define FLATBUFFERS_BFBS_GEN_NIM_H_
+
+#include <memory>
+#include <string>
+
+#include "flatbuffers/bfbs_generator.h"
+
+namespace flatbuffers {
+
+// Constructs a new Nim Code generator.
+std::unique_ptr<BfbsGenerator> NewNimBfbsGenerator(
+ const std::string &flatc_version);
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_BFBS_GEN_NIM_H_
diff --git a/third_party/flatbuffers/src/bfbs_namer.h b/third_party/flatbuffers/src/bfbs_namer.h
index 2c6e724..ef6c6c5 100644
--- a/third_party/flatbuffers/src/bfbs_namer.h
+++ b/third_party/flatbuffers/src/bfbs_namer.h
@@ -36,6 +36,14 @@
std::string Denamespace(T t, const char delimiter = '.') const {
return Namer::Denamespace(t->name()->c_str(), delimiter);
}
+
+ virtual std::string Field(const ::reflection::Field &f) const {
+ return Field(f.name()->str());
+ }
+
+ virtual std::string Variable(const ::reflection::Field &f) const {
+ return Variable(f.name()->str());
+ }
};
} // namespace flatbuffers
diff --git a/third_party/flatbuffers/src/binary_annotator.cpp b/third_party/flatbuffers/src/binary_annotator.cpp
index 2a94abc..92d4391 100644
--- a/third_party/flatbuffers/src/binary_annotator.cpp
+++ b/third_party/flatbuffers/src/binary_annotator.cpp
@@ -1,5 +1,6 @@
#include "binary_annotator.h"
+#include <algorithm>
#include <limits>
#include <string>
#include <vector>
@@ -1451,4 +1452,4 @@
it->second.regions.back().length;
}
-} // namespace flatbuffers
\ No newline at end of file
+} // namespace flatbuffers
diff --git a/third_party/flatbuffers/src/flatc.cpp b/third_party/flatbuffers/src/flatc.cpp
index 1d12a17..40a538f 100644
--- a/third_party/flatbuffers/src/flatc.cpp
+++ b/third_party/flatbuffers/src/flatc.cpp
@@ -16,6 +16,8 @@
#include "flatbuffers/flatc.h"
+#include <algorithm>
+#include <limits>
#include <list>
#include <sstream>
@@ -88,7 +90,7 @@
"--no-prefix." },
{ "", "swift-implementation-only", "",
"Adds a @_implementationOnly to swift imports" },
- { "", "gen-inclues", "",
+ { "", "gen-includes", "",
"(deprecated), this is the default behavior. If the original behavior is "
"required (no include statements) use --no-includes." },
{ "", "no-includes", "",
@@ -215,14 +217,14 @@
"Allows (de)serialization of JSON text in the Object API. (requires "
"--gen-object-api)." },
{ "", "json-nested-bytes", "",
- "Allow a nested_flatbuffer field to be parsed as a vector of bytes"
+ "Allow a nested_flatbuffer field to be parsed as a vector of bytes "
"in JSON, which is unsafe unless checked by a verifier afterwards." },
{ "", "ts-flat-files", "",
"Only generated one typescript file per .fbs file." },
{ "", "annotate", "SCHEMA",
"Annotate the provided BINARY_FILE with the specified SCHEMA file." },
{ "", "no-leak-private-annotation", "",
- "Prevents multiple type of annotations within a Fbs SCHEMA file."
+ "Prevents multiple type of annotations within a Fbs SCHEMA file. "
"Currently this is required to generate private types in Rust" },
};
diff --git a/third_party/flatbuffers/src/flatc_main.cpp b/third_party/flatbuffers/src/flatc_main.cpp
index b4c4251..f2aa781 100644
--- a/third_party/flatbuffers/src/flatc_main.cpp
+++ b/third_party/flatbuffers/src/flatc_main.cpp
@@ -18,6 +18,7 @@
#include <memory>
#include "bfbs_gen_lua.h"
+#include "bfbs_gen_nim.h"
#include "flatbuffers/base.h"
#include "flatbuffers/flatc.h"
#include "flatbuffers/util.h"
@@ -56,6 +57,8 @@
std::unique_ptr<flatbuffers::BfbsGenerator> bfbs_gen_lua =
flatbuffers::NewLuaBfbsGenerator(flatbuffers_version);
+ std::unique_ptr<flatbuffers::BfbsGenerator> bfbs_gen_nim =
+ flatbuffers::NewNimBfbsGenerator(flatbuffers_version);
g_program_name = argv[0];
@@ -142,6 +145,10 @@
flatbuffers::FlatCOption{ "", "swift", "",
"Generate Swift files for tables/structs" },
nullptr, nullptr, nullptr },
+ { nullptr, "Nim", true, nullptr, flatbuffers::IDLOptions::kNim,
+ flatbuffers::FlatCOption{ "", "nim", "",
+ "Generate Nim files for tables/structs" },
+ nullptr, bfbs_gen_nim.get(), nullptr },
};
flatbuffers::FlatCompiler::InitParams params;
diff --git a/third_party/flatbuffers/src/idl_gen_cpp.cpp b/third_party/flatbuffers/src/idl_gen_cpp.cpp
index c1a0198..aeb16fd 100644
--- a/third_party/flatbuffers/src/idl_gen_cpp.cpp
+++ b/third_party/flatbuffers/src/idl_gen_cpp.cpp
@@ -16,6 +16,7 @@
// independent from idl_parser, since this code is not needed for most clients
+#include <limits>
#include <string>
#include <unordered_set>
diff --git a/third_party/flatbuffers/src/idl_gen_csharp.cpp b/third_party/flatbuffers/src/idl_gen_csharp.cpp
index fa67eaf..ab36bd9 100644
--- a/third_party/flatbuffers/src/idl_gen_csharp.cpp
+++ b/third_party/flatbuffers/src/idl_gen_csharp.cpp
@@ -655,7 +655,7 @@
// Force compile time error if not using the same version runtime.
code += " public static void ValidateVersion() {";
code += " FlatBufferConstants.";
- code += "FLATBUFFERS_2_0_8(); ";
+ code += "FLATBUFFERS_22_10_26(); ";
code += "}\n";
// Generate a special accessor for the table that when used as the root
diff --git a/third_party/flatbuffers/src/idl_gen_dart.cpp b/third_party/flatbuffers/src/idl_gen_dart.cpp
index 0bf230d..ada5956 100644
--- a/third_party/flatbuffers/src/idl_gen_dart.cpp
+++ b/third_party/flatbuffers/src/idl_gen_dart.cpp
@@ -16,6 +16,7 @@
// independent from idl_parser, since this code is not needed for most clients
#include <cassert>
+#include <cmath>
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
@@ -721,16 +722,17 @@
if (!value.constant.empty() && value.constant != "0") {
if (IsBool(value.type.base_type)) {
return "true";
- } else if (value.constant == "nan" || value.constant == "+nan" ||
- value.constant == "-nan") {
- return "double.nan";
- } else if (value.constant == "inf" || value.constant == "+inf") {
- return "double.infinity";
- } else if (value.constant == "-inf") {
- return "double.negativeInfinity";
- } else {
- return value.constant;
}
+ if (IsScalar(value.type.base_type)) {
+ if (StringIsFlatbufferNan(value.constant)) {
+ return "double.nan";
+ } else if (StringIsFlatbufferPositiveInfinity(value.constant)) {
+ return "double.infinity";
+ } else if (StringIsFlatbufferNegativeInfinity(value.constant)) {
+ return "double.negativeInfinity";
+ }
+ }
+ return value.constant;
} else if (IsBool(value.type.base_type)) {
return "false";
} else if (IsScalar(value.type.base_type) && !IsUnion(value.type)) {
diff --git a/third_party/flatbuffers/src/idl_gen_fbs.cpp b/third_party/flatbuffers/src/idl_gen_fbs.cpp
index 782557f..9c58dc4 100644
--- a/third_party/flatbuffers/src/idl_gen_fbs.cpp
+++ b/third_party/flatbuffers/src/idl_gen_fbs.cpp
@@ -137,6 +137,7 @@
schema += " " + field.name + ":" + GenType(field.value.type);
if (field.value.constant != "0") schema += " = " + field.value.constant;
if (field.IsRequired()) schema += " (required)";
+ if (field.key) schema += " (key)";
schema += ";\n";
}
}
diff --git a/third_party/flatbuffers/src/idl_gen_go.cpp b/third_party/flatbuffers/src/idl_gen_go.cpp
index 51e018a..33917ff 100644
--- a/third_party/flatbuffers/src/idl_gen_go.cpp
+++ b/third_party/flatbuffers/src/idl_gen_go.cpp
@@ -16,6 +16,8 @@
// independent from idl_parser, since this code is not needed for most clients
+#include <algorithm>
+#include <cmath>
#include <sstream>
#include <string>
@@ -101,6 +103,7 @@
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
tracked_imported_namespaces_.clear();
+ needs_math_import_ = false;
needs_imports = false;
std::string enumcode;
GenEnum(**it, &enumcode);
@@ -120,6 +123,7 @@
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
tracked_imported_namespaces_.clear();
+ needs_math_import_ = false;
std::string declcode;
GenStruct(**it, &declcode);
if (parser_.opts.one_file) {
@@ -153,6 +157,7 @@
}
};
std::set<const Namespace *, NamespacePtrLess> tracked_imported_namespaces_;
+ bool needs_math_import_ = false;
// Most field accessors need to retrieve and test the field offset first,
// this is the prefix code for that.
@@ -1276,6 +1281,23 @@
switch (field.value.type.base_type) {
case BASE_TYPE_BOOL:
return field.value.constant == "0" ? "false" : "true";
+ case BASE_TYPE_FLOAT:
+ case BASE_TYPE_DOUBLE: {
+ const std::string float_type =
+ field.value.type.base_type == BASE_TYPE_FLOAT ? "float32"
+ : "float64";
+ if (StringIsFlatbufferNan(field.value.constant)) {
+ needs_math_import_ = true;
+ return float_type + "(math.NaN())";
+ } else if (StringIsFlatbufferPositiveInfinity(field.value.constant)) {
+ needs_math_import_ = true;
+ return float_type + "(math.Inf(1))";
+ } else if (StringIsFlatbufferNegativeInfinity(field.value.constant)) {
+ needs_math_import_ = true;
+ return float_type + "(math.Inf(-1))";
+ }
+ return field.value.constant;
+ }
default: return field.value.constant;
}
}
@@ -1329,6 +1351,8 @@
if (needs_imports) {
code += "import (\n";
if (is_enum) { code += "\t\"strconv\"\n\n"; }
+ // math is needed to support non-finite scalar default values.
+ if (needs_math_import_) { code += "\t\"math\"\n\n"; }
if (!parser_.opts.go_import.empty()) {
code += "\tflatbuffers \"" + parser_.opts.go_import + "\"\n";
} else {
@@ -1345,6 +1369,10 @@
code += ")\n\n";
} else {
if (is_enum) { code += "import \"strconv\"\n\n"; }
+ if (needs_math_import_) {
+ // math is needed to support non-finite scalar default values.
+ code += "import \"math\"\n\n";
+ }
}
}
diff --git a/third_party/flatbuffers/src/idl_gen_java.cpp b/third_party/flatbuffers/src/idl_gen_java.cpp
index 6ee97aa..a35950f 100644
--- a/third_party/flatbuffers/src/idl_gen_java.cpp
+++ b/third_party/flatbuffers/src/idl_gen_java.cpp
@@ -397,6 +397,10 @@
code += " ";
code += namer_.Variant(ev) + " = ";
code += enum_def.ToString(ev);
+ if (enum_def.underlying_type.base_type == BASE_TYPE_LONG ||
+ enum_def.underlying_type.base_type == BASE_TYPE_ULONG) {
+ code += "L";
+ }
code += ";\n";
}
@@ -665,7 +669,7 @@
// Force compile time error if not using the same version runtime.
code += " public static void ValidateVersion() {";
code += " Constants.";
- code += "FLATBUFFERS_2_0_8(); ";
+ code += "FLATBUFFERS_22_10_26(); ";
code += "}\n";
// Generate a special accessor for the table that when used as the root
@@ -1889,6 +1893,7 @@
}
} else {
code += " " + name + " = ";
+ code += SourceCast(field_type);
code += "_o";
for (size_t i = 0; i < array_lengths.size(); ++i) {
code += "." + namer_.Method("get", array_lengths[i].name) + "()";
diff --git a/third_party/flatbuffers/src/idl_gen_json_schema.cpp b/third_party/flatbuffers/src/idl_gen_json_schema.cpp
index 5cb6a9d..796d1e2 100644
--- a/third_party/flatbuffers/src/idl_gen_json_schema.cpp
+++ b/third_party/flatbuffers/src/idl_gen_json_schema.cpp
@@ -14,7 +14,9 @@
* limitations under the License.
*/
+#include <algorithm>
#include <iostream>
+#include <limits>
#include "flatbuffers/code_generators.h"
#include "flatbuffers/idl.h"
diff --git a/third_party/flatbuffers/src/idl_gen_kotlin.cpp b/third_party/flatbuffers/src/idl_gen_kotlin.cpp
index 102e24d..57ec7b7 100644
--- a/third_party/flatbuffers/src/idl_gen_kotlin.cpp
+++ b/third_party/flatbuffers/src/idl_gen_kotlin.cpp
@@ -505,7 +505,7 @@
// runtime.
GenerateFunOneLine(
writer, "validateVersion", "", "",
- [&]() { writer += "Constants.FLATBUFFERS_2_0_8()"; },
+ [&]() { writer += "Constants.FLATBUFFERS_22_10_26()"; },
options.gen_jvmstatic);
GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options);
diff --git a/third_party/flatbuffers/src/idl_gen_python.cpp b/third_party/flatbuffers/src/idl_gen_python.cpp
index 0b8ffa8..38a5bc1 100644
--- a/third_party/flatbuffers/src/idl_gen_python.cpp
+++ b/third_party/flatbuffers/src/idl_gen_python.cpp
@@ -83,11 +83,11 @@
// Most field accessors need to retrieve and test the field offset first,
// this is the prefix code for that.
- std::string OffsetPrefix(const FieldDef &field) const {
+ std::string OffsetPrefix(const FieldDef &field, bool new_line = true) const {
return "\n" + Indent + Indent +
"o = flatbuffers.number_types.UOffsetTFlags.py_type" +
"(self._tab.Offset(" + NumToString(field.value.offset) + "))\n" +
- Indent + Indent + "if o != 0:\n";
+ Indent + Indent + "if o != 0:" + (new_line ? "\n" : "");
}
// Begin a class declaration.
@@ -164,9 +164,14 @@
GenReceiver(struct_def, code_ptr);
code += namer_.Method(field) + "Length(self";
- code += "):" + OffsetPrefix(field);
- code += Indent + Indent + Indent + "return self._tab.VectorLen(o)\n";
- code += Indent + Indent + "return 0\n\n";
+ code += "):";
+ if(!IsArray(field.value.type)){
+ code += OffsetPrefix(field,false);
+ code += GenIndents(3) + "return self._tab.VectorLen(o)";
+ code += GenIndents(2) + "return 0\n\n";
+ }else{
+ code += GenIndents(2) + "return "+NumToString(field.value.type.fixed_length)+"\n\n";
+ }
}
// Determines whether a vector is none or not.
@@ -177,10 +182,15 @@
GenReceiver(struct_def, code_ptr);
code += namer_.Method(field) + "IsNone(self";
code += "):";
- code += GenIndents(2) +
- "o = flatbuffers.number_types.UOffsetTFlags.py_type" +
- "(self._tab.Offset(" + NumToString(field.value.offset) + "))";
- code += GenIndents(2) + "return o == 0";
+ if(!IsArray(field.value.type)){
+ code += GenIndents(2) +
+ "o = flatbuffers.number_types.UOffsetTFlags.py_type" +
+ "(self._tab.Offset(" + NumToString(field.value.offset) + "))";
+ code += GenIndents(2) + "return o == 0";
+ } else {
+ //assume that we always have an array as memory is preassigned
+ code += GenIndents(2) + "return False";
+ }
code += "\n\n";
}
@@ -244,21 +254,42 @@
const auto vec_type = field.value.type.VectorType();
GenReceiver(struct_def, code_ptr);
code += namer_.Method(field);
- if (IsStruct(vec_type)) {
- code += "(self, obj, i):\n";
- code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
- code += NumToString(field.value.offset) + " + i * ";
- code += NumToString(InlineSize(vec_type));
- code += ")\n" + Indent + Indent + "return obj\n\n";
- } else {
- auto getter = GenGetter(vec_type);
- code += "(self): return [" + getter;
- code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
- code += NumToString(field.value.offset) + " + i * ";
- code += NumToString(InlineSize(vec_type));
- code += ")) for i in range(";
- code += NumToString(field.value.type.fixed_length) + ")]\n";
+ code += "(self, i: int):";
+ if (parser_.opts.include_dependence_headers) {
+ code += GenIndents(2);
+ code += "from " + GenPackageReference(field.value.type) + " import " +
+ TypeName(field);
}
+ code += GenIndents(2) + "obj = " + TypeName(field) + "()";
+ code += GenIndents(2) + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
+ code += NumToString(field.value.offset) + " + i * ";
+ code += NumToString(InlineSize(vec_type));
+ code += ")" + GenIndents(2) + "return obj\n\n";
+ }
+
+ // Get the value of a vector's non-struct member. Uses a named return
+ // argument to conveniently set the zero value for the result.
+ void GetArrayOfNonStruct(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) const {
+ auto &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += namer_.Method(field);
+ code += "(self, j = None):";
+ code += GenIndents(2) + "if j is None:";
+ code += GenIndents(3) + "return [" + GenGetter(field.value.type);
+ code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
+ code += NumToString(field.value.offset) + " + i * ";
+ code += NumToString(InlineSize(field.value.type.VectorType()));
+ code += ")) for i in range(";
+ code += "self."+namer_.Method(field)+"Length()" + ")]";
+ code += GenIndents(2) +"elif j >= 0 and j < self."+namer_.Method(field)+"Length():";
+ code += GenIndents(3) + "return " + GenGetter(field.value.type);
+ code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
+ code += NumToString(field.value.offset) + " + j * ";
+ code += NumToString(InlineSize(field.value.type.VectorType()));
+ code += "))";
+ code += GenIndents(2) + "else:";
+ code += GenIndents(3) + "return None\n\n";
}
// Get a struct by initializing an existing struct.
@@ -403,18 +434,25 @@
GenReceiver(struct_def, code_ptr);
code += namer_.Method(field) + "AsNumpy(self):";
- code += OffsetPrefix(field);
+ if(!IsArray(field.value.type)){
+ code += OffsetPrefix(field, false);
- code += Indent + Indent + Indent;
- code += "return ";
- code += "self._tab.GetVectorAsNumpy(flatbuffers.number_types.";
- code += namer_.Method(GenTypeGet(field.value.type));
- code += "Flags, o)\n";
+ code += GenIndents(3);
+ code += "return ";
+ code += "self._tab.GetVectorAsNumpy(flatbuffers.number_types.";
+ code += namer_.Method(GenTypeGet(field.value.type));
+ code += "Flags, o)";
- if (IsString(vectortype)) {
- code += Indent + Indent + "return \"\"\n";
- } else {
- code += Indent + Indent + "return 0\n";
+ if (IsString(vectortype)) {
+ code += GenIndents(2) + "return \"\"\n";
+ } else {
+ code += GenIndents(2) + "return 0\n";
+ }
+ }else{
+ code += GenIndents(2) + "return ";
+ code += "self._tab.GetArrayAsNumpy(flatbuffers.number_types.";
+ code += namer_.Method(GenTypeGet(field.value.type.VectorType()));
+ code += "Flags, self._tab.Pos + "+NumToString(field.value.offset)+", "+NumToString("self."+namer_.Method(field)+"Length()")+")\n";
}
code += "\n";
}
@@ -714,8 +752,6 @@
} else {
GetScalarFieldOfTable(struct_def, field, code_ptr);
}
- } else if (IsArray(field.value.type)) {
- GetArrayOfStruct(struct_def, field, code_ptr);
} else {
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT:
@@ -739,6 +775,17 @@
}
break;
}
+ case BASE_TYPE_ARRAY: {
+ auto vectortype = field.value.type.VectorType();
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ GetArrayOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetArrayOfNonStruct(struct_def, field, code_ptr);
+ GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
+ GetVectorAsNestedFlatbuffer(struct_def, field, code_ptr);
+ }
+ break;
+ }
case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
default: FLATBUFFERS_ASSERT(0);
}
@@ -1067,6 +1114,19 @@
code += "\n";
}
+ void InitializeFromPackedBuf(const StructDef &struct_def,
+ std::string *code_ptr) const {
+ auto &code = *code_ptr;
+ const auto struct_var = namer_.Variable(struct_def);
+ const auto struct_type = namer_.Type(struct_def);
+
+ code += GenIndents(1) + "@classmethod";
+ code += GenIndents(1) + "def InitFromPackedBuf(cls, buf, pos=0):";
+ code += GenIndents(2) + "n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)";
+ code += GenIndents(2) + "return cls.InitFromBuf(buf, pos+n)";
+ code += "\n";
+ }
+
void InitializeFromObjForObject(const StructDef &struct_def,
std::string *code_ptr) const {
auto &code = *code_ptr;
@@ -1100,8 +1160,8 @@
code += field_type + "()";
}
code += ") is not None:";
- code += GenIndents(3) + "self." + field_field + " = " + field_type +
- "T.InitFromObj(" + struct_var + "." + field_method + "(";
+ code += GenIndents(3) + "self." + field_field + " = " + namer_.ObjectType(field_type) +
+ + ".InitFromObj(" + struct_var + "." + field_method + "(";
// A struct's accessor requires a struct buf instance.
if (struct_def.fixed && field.value.type.base_type == BASE_TYPE_STRUCT) {
code += field_type + "()";
@@ -1143,18 +1203,47 @@
auto field_type = TypeName(field);
auto one_instance = field_type + "_";
one_instance[0] = CharToLower(one_instance[0]);
-
if (parser_.opts.include_dependence_headers) {
auto package_reference = GenPackageReference(field.value.type);
field_type = package_reference + "." + TypeName(field);
}
-
code += GenIndents(4) + "if " + struct_var + "." + field_method +
"(i) is None:";
code += GenIndents(5) + "self." + field_field + ".append(None)";
code += GenIndents(4) + "else:";
- code += GenIndents(5) + one_instance + " = " + field_type +
- "T.InitFromObj(" + struct_var + "." + field_method + "(i))";
+ code += GenIndents(5) + one_instance + " = " + namer_.ObjectType(field_type) +
+ ".InitFromObj(" + struct_var + "." + field_method + "(i))";
+ code +=
+ GenIndents(5) + "self." + field_field + ".append(" + one_instance + ")";
+ }
+
+ void GenUnpackForTableVector(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) const {
+ auto &code = *code_ptr;
+ const auto field_field = namer_.Field(field);
+ const auto field_method = namer_.Method(field);
+ const auto struct_var = namer_.Variable(struct_def);
+
+ code += GenIndents(2) + "if not " + struct_var + "." + field_method +
+ "IsNone():";
+ code += GenIndents(3) + "self." + field_field + " = []";
+ code += GenIndents(3) + "for i in range(" + struct_var + "." +
+ field_method + "Length()):";
+
+ auto field_type = TypeName(field);
+ auto one_instance = field_type + "_";
+ one_instance[0] = CharToLower(one_instance[0]);
+ if (parser_.opts.include_dependence_headers) {
+ auto package_reference = GenPackageReference(field.value.type);
+ field_type = package_reference + "." + TypeName(field);
+ }
+ code += GenIndents(4) + "if " + struct_var + "." + field_method +
+ "(i) is None:";
+ code += GenIndents(5) + "self." + field_field + ".append(None)";
+ code += GenIndents(4) + "else:";
+ code += GenIndents(5) + one_instance + " = " + namer_.ObjectType(field_type) +
+ ".InitFromObj(" + struct_var + "." + field_method + "(i))";
code +=
GenIndents(5) + "self." + field_field + ".append(" + one_instance + ")";
}
@@ -1233,6 +1322,7 @@
GenUnPackForUnion(struct_def, field, &code);
break;
}
+ case BASE_TYPE_ARRAY:
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_STRUCT) {
@@ -1242,10 +1332,6 @@
}
break;
}
- case BASE_TYPE_ARRAY: {
- GenUnPackForScalarVector(struct_def, field, &code);
- break;
- }
default: GenUnPackForScalar(struct_def, field, &code);
}
}
@@ -1482,6 +1568,7 @@
GenPackForUnionField(struct_def, field, &code_prefix, &code);
break;
}
+ case BASE_TYPE_ARRAY:
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
if (vectortype.base_type == BASE_TYPE_STRUCT) {
@@ -1491,10 +1578,6 @@
}
break;
}
- case BASE_TYPE_ARRAY: {
- GenPackForScalarVectorField(struct_def, field, &code_prefix, &code);
- break;
- }
case BASE_TYPE_STRING: {
code_prefix +=
GenIndents(2) + "if self." + field_field + " is not None:";
@@ -1536,6 +1619,8 @@
InitializeFromBuf(struct_def, &code);
+ InitializeFromPackedBuf(struct_def, &code);
+
InitializeFromObjForObject(struct_def, &code);
GenUnPack(struct_def, &code);
@@ -1666,7 +1751,9 @@
std::string GenTypePointer(const Type &type) const {
switch (type.base_type) {
case BASE_TYPE_STRING: return "string";
- case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
+ case BASE_TYPE_VECTOR:
+ // fall through
+ case BASE_TYPE_ARRAY: return GenTypeGet(type.VectorType());
case BASE_TYPE_STRUCT: return type.struct_def->name;
case BASE_TYPE_UNION:
// fall through
diff --git a/third_party/flatbuffers/src/idl_gen_rust.cpp b/third_party/flatbuffers/src/idl_gen_rust.cpp
index 64391d0..43237b2 100644
--- a/third_party/flatbuffers/src/idl_gen_rust.cpp
+++ b/third_party/flatbuffers/src/idl_gen_rust.cpp
@@ -16,6 +16,8 @@
// independent from idl_parser, since this code is not needed for most clients
+#include <cmath>
+
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
@@ -738,7 +740,6 @@
code_ += "pub use self::bitflags_{{ENUM_NAMESPACE}}::{{ENUM_TY}};";
code_ += "";
- code_.SetValue("FROM_BASE", "unsafe { Self::from_bits_unchecked(b) }");
code_.SetValue("INTO_BASE", "self.bits()");
} else {
// Normal, c-modelled enums.
@@ -811,7 +812,6 @@
code_ += " }";
code_ += "}";
- code_.SetValue("FROM_BASE", "Self(b)");
code_.SetValue("INTO_BASE", "self.0");
}
@@ -840,35 +840,55 @@
code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_TY}} {";
code_ += " type Inner = Self;";
code_ += " #[inline]";
- code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
- code_ += " let b = unsafe {";
- code_ += " flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc)";
- code_ += " };";
- code_ += " {{FROM_BASE}}";
+ code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " let b = flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc);";
+ if (IsBitFlagsEnum(enum_def)) {
+ // Safety:
+ // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.
+ // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0
+ // https://github.com/bitflags/bitflags/issues/262
+ code_ += " // Safety:";
+ code_ += " // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.";
+ code_ += " // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0";
+ code_ += " // https://github.com/bitflags/bitflags/issues/262";
+ code_ += " Self::from_bits_unchecked(b)";
+ } else {
+ code_ += " Self(b)";
+ }
code_ += " }";
code_ += "}";
code_ += "";
code_ += "impl flatbuffers::Push for {{ENUM_TY}} {";
code_ += " type Output = {{ENUM_TY}};";
code_ += " #[inline]";
- code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
- code_ +=
- " unsafe { flatbuffers::emplace_scalar::<{{BASE_TYPE}}>"
- "(dst, {{INTO_BASE}}); }";
+ code_ += " unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {";
+ code_ += " flatbuffers::emplace_scalar::<{{BASE_TYPE}}>(dst, {{INTO_BASE}});";
code_ += " }";
code_ += "}";
code_ += "";
code_ += "impl flatbuffers::EndianScalar for {{ENUM_TY}} {";
+ code_ += " type Scalar = {{BASE_TYPE}};";
code_ += " #[inline]";
- code_ += " fn to_little_endian(self) -> Self {";
- code_ += " let b = {{BASE_TYPE}}::to_le({{INTO_BASE}});";
- code_ += " {{FROM_BASE}}";
+ code_ += " fn to_little_endian(self) -> {{BASE_TYPE}} {";
+ code_ += " {{INTO_BASE}}.to_le()";
code_ += " }";
code_ += " #[inline]";
code_ += " #[allow(clippy::wrong_self_convention)]";
- code_ += " fn from_little_endian(self) -> Self {";
- code_ += " let b = {{BASE_TYPE}}::from_le({{INTO_BASE}});";
- code_ += " {{FROM_BASE}}";
+ code_ += " fn from_little_endian(v: {{BASE_TYPE}}) -> Self {";
+ code_ += " let b = {{BASE_TYPE}}::from_le(v);";
+ if (IsBitFlagsEnum(enum_def)) {
+ // Safety:
+ // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.
+ // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0
+ // https://github.com/bitflags/bitflags/issues/262
+ code_ += " // Safety:";
+ code_ += " // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size.";
+ code_ += " // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0";
+ code_ += " // https://github.com/bitflags/bitflags/issues/262";
+ code_ += " unsafe { Self::from_bits_unchecked(b) }";
+ } else {
+ code_ += " Self(b)";
+ }
code_ += " }";
code_ += "}";
code_ += "";
@@ -1029,8 +1049,19 @@
if (field.IsOptional() && !IsUnion(field.value.type)) { return "None"; }
}
switch (GetFullType(field.value.type)) {
- case ftInteger:
+ case ftInteger: {
+ return field.value.constant;
+ }
case ftFloat: {
+ const std::string float_prefix =
+ (field.value.type.base_type == BASE_TYPE_FLOAT) ? "f32::" : "f64::";
+ if (StringIsFlatbufferNan(field.value.constant)) {
+ return float_prefix + "NAN";
+ } else if (StringIsFlatbufferPositiveInfinity(field.value.constant)) {
+ return float_prefix + "INFINITY";
+ } else if (StringIsFlatbufferNegativeInfinity(field.value.constant)) {
+ return float_prefix + "NEG_INFINITY";
+ }
return field.value.constant;
}
case ftBool: {
@@ -1426,11 +1457,7 @@
case ftVectorOfBool:
case ftVectorOfFloat: {
const auto typname = GetTypeBasic(type.VectorType());
- const auto vector_type =
- IsOneByte(type.VectorType().base_type)
- ? "&" + lifetime + " [" + typname + "]"
- : "flatbuffers::Vector<" + lifetime + ", " + typname + ">";
- return WrapOption(vector_type);
+ return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname + ">");
}
case ftVectorOfEnumKey: {
const auto typname = WrapInNameSpace(*type.enum_def);
@@ -1439,7 +1466,7 @@
}
case ftVectorOfStruct: {
const auto typname = WrapInNameSpace(*type.struct_def);
- return WrapOption("&" + lifetime + " [" + typname + "]");
+ return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname + ">");
}
case ftVectorOfTable: {
const auto typname = WrapInNameSpace(*type.struct_def);
@@ -1557,19 +1584,8 @@
: "None";
const std::string unwrap = field.IsOptional() ? "" : ".unwrap()";
- const auto t = GetFullType(field.value.type);
-
- // TODO(caspern): Shouldn't 1byte VectorOfEnumKey be slice too?
- const std::string safe_slice =
- (t == ftVectorOfStruct ||
- ((t == ftVectorOfBool || t == ftVectorOfFloat ||
- t == ftVectorOfInteger) &&
- IsOneByte(field.value.type.VectorType().base_type)))
- ? ".map(|v| v.safe_slice())"
- : "";
-
- return "self._tab.get::<" + typname + ">({{STRUCT_TY}}::" + vt_offset +
- ", " + default_value + ")" + safe_slice + unwrap;
+ return "unsafe { self._tab.get::<" + typname + ">({{STRUCT_TY}}::" + vt_offset +
+ ", " + default_value + ")" + unwrap + "}";
}
// Generates a fully-qualified name getter for use with --gen-name-strings
@@ -1655,8 +1671,8 @@
code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}}<'a> {";
code_ += " type Inner = {{STRUCT_TY}}<'a>;";
code_ += " #[inline]";
- code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
- code_ += " Self { _tab: flatbuffers::Table { buf, loc } }";
+ code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " Self { _tab: flatbuffers::Table::new(buf, loc) }";
code_ += " }";
code_ += "}";
code_ += "";
@@ -1677,7 +1693,7 @@
code_ += " #[inline]";
code_ +=
- " pub fn init_from_table(table: flatbuffers::Table<'a>) -> "
+ " pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> "
"Self {";
code_ += " {{STRUCT_TY}} { _tab: table }";
code_ += " }";
@@ -1769,16 +1785,7 @@
break;
}
case ftVectorOfInteger:
- case ftVectorOfBool: {
- if (IsOneByte(type.VectorType().base_type)) {
- // 1 byte stuff is viewed w/ slice instead of flatbuffer::Vector
- // and thus needs to be cloned out of the slice.
- code_.SetValue("EXPR", "x.to_vec()");
- break;
- }
- code_.SetValue("EXPR", "x.into_iter().collect()");
- break;
- }
+ case ftVectorOfBool:
case ftVectorOfFloat:
case ftVectorOfEnumKey: {
code_.SetValue("EXPR", "x.into_iter().collect()");
@@ -1845,6 +1852,9 @@
this->GenComment(field.doc_comment);
code_ += "#[inline]";
code_ += "pub fn {{FIELD}}(&self) -> {{RETURN_TYPE}} {";
+ code_ += " // Safety:";
+ code_ += " // Created from valid Table for this object";
+ code_ += " // which contains a valid value in this slot";
code_ += " " + GenTableAccessorFuncBody(field, "'a");
code_ += "}";
@@ -1869,16 +1879,22 @@
code_ += "{{NESTED}}<'a> {";
code_ += " let data = self.{{FIELD}}();";
code_ += " use flatbuffers::Follow;";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid flatbuffer in this slot";
code_ +=
- " <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
- "::follow(data, 0)";
+ " unsafe { <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
+ "::follow(data.bytes(), 0) }";
} else {
code_ += "Option<{{NESTED}}<'a>> {";
code_ += " self.{{FIELD}}().map(|data| {";
code_ += " use flatbuffers::Follow;";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid flatbuffer in this slot";
code_ +=
- " <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
- "::follow(data, 0)";
+ " unsafe { <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
+ "::follow(data.bytes(), 0) }";
code_ += " })";
}
code_ += "}";
@@ -1914,11 +1930,17 @@
// as of April 10, 2020
if (field.IsRequired()) {
code_ += " let u = self.{{FIELD}}();";
- code_ += " Some({{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid union in this slot";
+ code_ += " Some(unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(u) })";
} else {
- code_ +=
- " self.{{FIELD}}().map("
- "{{U_ELEMENT_TABLE_TYPE}}::init_from_table)";
+ code_ +=" self.{{FIELD}}().map(|t| {";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid union in this slot";
+ code_ += " unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(t) }";
+ code_ += " })";
}
code_ += " } else {";
code_ += " None";
@@ -2291,8 +2313,8 @@
MapNativeTableField(
field,
- "let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();"
- "_fbb.create_vector_of_strings(&w)");
+ "let w: Vec<_> = x.iter().map(|s| _fbb.create_string(s)).collect();"
+ "_fbb.create_vector(&w)");
return;
}
case ftVectorOfTable: {
@@ -2383,32 +2405,6 @@
code_.SetValue("STRUCT_FN", namer_.Function(struct_def));
code_.SetValue("STRUCT_CONST", namer_.Constant(struct_def.name));
- // The root datatype accessors:
- code_ += "#[inline]";
- code_ +=
- "#[deprecated(since=\"2.0.0\", "
- "note=\"Deprecated in favor of `root_as...` methods.\")]";
- code_ +=
- "pub fn get_root_as_{{STRUCT_FN}}<'a>(buf: &'a [u8])"
- " -> {{STRUCT_TY}}<'a> {";
- code_ +=
- " unsafe { flatbuffers::root_unchecked::<{{STRUCT_TY}}"
- "<'a>>(buf) }";
- code_ += "}";
- code_ += "";
-
- code_ += "#[inline]";
- code_ +=
- "#[deprecated(since=\"2.0.0\", "
- "note=\"Deprecated in favor of `root_as...` methods.\")]";
- code_ +=
- "pub fn get_size_prefixed_root_as_{{STRUCT_FN}}"
- "<'a>(buf: &'a [u8]) -> {{STRUCT_TY}}<'a> {";
- code_ +=
- " unsafe { flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_TY}}"
- "<'a>>(buf) }";
- code_ += "}";
- code_ += "";
// Default verifier root fns.
code_ += "#[inline]";
code_ += "/// Verifies that a buffer of bytes contains a `{{STRUCT_TY}}`";
@@ -2650,43 +2646,25 @@
// Follow for the value type, Follow for the reference type, Push for the
// value type, and Push for the reference type.
code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{STRUCT_TY}} {}";
- code_ += "impl flatbuffers::SafeSliceAccess for {{STRUCT_TY}} {}";
code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}} {";
code_ += " type Inner = &'a {{STRUCT_TY}};";
code_ += " #[inline]";
- code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
code_ += " <&'a {{STRUCT_TY}}>::follow(buf, loc)";
code_ += " }";
code_ += "}";
code_ += "impl<'a> flatbuffers::Follow<'a> for &'a {{STRUCT_TY}} {";
code_ += " type Inner = &'a {{STRUCT_TY}};";
code_ += " #[inline]";
- code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
code_ += " flatbuffers::follow_cast_ref::<{{STRUCT_TY}}>(buf, loc)";
code_ += " }";
code_ += "}";
code_ += "impl<'b> flatbuffers::Push for {{STRUCT_TY}} {";
code_ += " type Output = {{STRUCT_TY}};";
code_ += " #[inline]";
- code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
- code_ += " let src = unsafe {";
- code_ +=
- " ::core::slice::from_raw_parts("
- "self as *const {{STRUCT_TY}} as *const u8, Self::size())";
- code_ += " };";
- code_ += " dst.copy_from_slice(src);";
- code_ += " }";
- code_ += "}";
- code_ += "impl<'b> flatbuffers::Push for &'b {{STRUCT_TY}} {";
- code_ += " type Output = {{STRUCT_TY}};";
- code_ += "";
- code_ += " #[inline]";
- code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
- code_ += " let src = unsafe {";
- code_ +=
- " ::core::slice::from_raw_parts("
- "*self as *const {{STRUCT_TY}} as *const u8, Self::size())";
- code_ += " };";
+ code_ += " unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {";
+ code_ += " let src = ::core::slice::from_raw_parts(self as *const {{STRUCT_TY}} as *const u8, Self::size());";
code_ += " dst.copy_from_slice(src);";
code_ += " }";
code_ += "}";
@@ -2759,6 +2737,9 @@
// Getter.
if (IsStruct(field.value.type)) {
code_ += "pub fn {{FIELD}}(&self) -> &{{FIELD_TYPE}} {";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid struct in this slot";
code_ +=
" unsafe {"
" &*(self.0[{{FIELD_OFFSET}}..].as_ptr() as *const"
@@ -2770,20 +2751,26 @@
code_ +=
"pub fn {{FIELD}}(&'a self) -> "
"flatbuffers::Array<'a, {{ARRAY_ITEM}}, {{ARRAY_SIZE}}> {";
- code_ += " flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}})";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid array in this slot";
+ code_ += " unsafe { flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}}) }";
} else {
code_ += "pub fn {{FIELD}}(&self) -> {{FIELD_TYPE}} {";
code_ +=
" let mut mem = core::mem::MaybeUninit::"
- "<{{FIELD_TYPE}}>::uninit();";
- code_ += " unsafe {";
+ "<<{{FIELD_TYPE}} as EndianScalar>::Scalar>::uninit();";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid value in this slot";
+ code_ += " EndianScalar::from_little_endian(unsafe {";
code_ += " core::ptr::copy_nonoverlapping(";
code_ += " self.0[{{FIELD_OFFSET}}..].as_ptr(),";
code_ += " mem.as_mut_ptr() as *mut u8,";
- code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),";
+ code_ += " core::mem::size_of::<<{{FIELD_TYPE}} as EndianScalar>::Scalar>(),";
code_ += " );";
code_ += " mem.assume_init()";
- code_ += " }.from_little_endian()";
+ code_ += " })";
}
code_ += "}\n";
// Setter.
@@ -2804,13 +2791,19 @@
code_ +=
"pub fn set_{{FIELD}}(&mut self, items: &{{FIELD_TYPE}}) "
"{";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid array in this slot";
code_ +=
- " flatbuffers::emplace_scalar_array(&mut self.0, "
- "{{FIELD_OFFSET}}, items);";
+ " unsafe { flatbuffers::emplace_scalar_array(&mut self.0, "
+ "{{FIELD_OFFSET}}, items) };";
} else {
code_.SetValue("FIELD_SIZE",
NumToString(InlineSize(field.value.type)));
code_ += "pub fn set_{{FIELD}}(&mut self, x: &{{FIELD_TYPE}}) {";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid array in this slot";
code_ += " unsafe {";
code_ += " core::ptr::copy(";
code_ += " x.as_ptr() as *const u8,";
@@ -2822,11 +2815,14 @@
} else {
code_ += "pub fn set_{{FIELD}}(&mut self, x: {{FIELD_TYPE}}) {";
code_ += " let x_le = x.to_little_endian();";
+ code_ += " // Safety:";
+ code_ += " // Created from a valid Table for this object";
+ code_ += " // Which contains a valid value in this slot";
code_ += " unsafe {";
code_ += " core::ptr::copy_nonoverlapping(";
- code_ += " &x_le as *const {{FIELD_TYPE}} as *const u8,";
+ code_ += " &x_le as *const _ as *const u8,";
code_ += " self.0[{{FIELD_OFFSET}}..].as_mut_ptr(),";
- code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),";
+ code_ += " core::mem::size_of::<<{{FIELD_TYPE}} as EndianScalar>::Scalar>(),";
code_ += " );";
code_ += " }";
}
diff --git a/third_party/flatbuffers/src/idl_gen_swift.cpp b/third_party/flatbuffers/src/idl_gen_swift.cpp
index b3baa28..c7cf2b5 100644
--- a/third_party/flatbuffers/src/idl_gen_swift.cpp
+++ b/third_party/flatbuffers/src/idl_gen_swift.cpp
@@ -1198,7 +1198,8 @@
void GenEnum(const EnumDef &enum_def) {
if (enum_def.generated) return;
- const auto is_private_access = enum_def.attributes.Lookup("private");
+ const bool is_private_access = parser_.opts.swift_implementation_only ||
+ enum_def.attributes.Lookup("private") != nullptr;
code_.SetValue("ENUM_TYPE",
enum_def.is_union ? "UnionEnum" : "Enum, Verifiable");
code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
@@ -1873,7 +1874,7 @@
}
std::string ValidateFunc() {
- return "static func validateVersion() { FlatBuffersVersion_2_0_8() }";
+ return "static func validateVersion() { FlatBuffersVersion_22_10_26() }";
}
std::string GenType(const Type &type,
diff --git a/third_party/flatbuffers/src/idl_gen_text.cpp b/third_party/flatbuffers/src/idl_gen_text.cpp
index 3b69c95..52f854d 100644
--- a/third_party/flatbuffers/src/idl_gen_text.cpp
+++ b/third_party/flatbuffers/src/idl_gen_text.cpp
@@ -16,6 +16,8 @@
// independent from idl_parser, since this code is not needed for most clients
+#include <algorithm>
+
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/flexbuffers.h"
#include "flatbuffers/idl.h"
diff --git a/third_party/flatbuffers/src/idl_gen_ts.cpp b/third_party/flatbuffers/src/idl_gen_ts.cpp
index 32ab863..9fd1203 100644
--- a/third_party/flatbuffers/src/idl_gen_ts.cpp
+++ b/third_party/flatbuffers/src/idl_gen_ts.cpp
@@ -16,6 +16,7 @@
#include <algorithm>
#include <cassert>
+#include <cmath>
#include <unordered_map>
#include <unordered_set>
@@ -402,12 +403,26 @@
const auto &value = field.value;
if (value.type.enum_def && value.type.base_type != BASE_TYPE_UNION &&
value.type.base_type != BASE_TYPE_VECTOR) {
- // If the value is an enum with a 64-bit base type, we have to just
- // return the bigint value directly since typescript does not support
- // enums with bigint backing types.
switch (value.type.base_type) {
+ case BASE_TYPE_ARRAY: {
+ std::string ret = "[";
+ for (auto i = 0; i < value.type.fixed_length; ++i) {
+ std::string enum_name =
+ AddImport(imports, *value.type.enum_def, *value.type.enum_def)
+ .name;
+ std::string enum_value = namer_.Variant(
+ *value.type.enum_def->FindByValue(value.constant));
+ ret += enum_name + "." + enum_value +
+ (i < value.type.fixed_length - 1 ? ", " : "");
+ }
+ ret += "]";
+ return ret;
+ }
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: {
+ // If the value is an enum with a 64-bit base type, we have to just
+ // return the bigint value directly since typescript does not support
+ // enums with bigint backing types.
return "BigInt('" + value.constant + "')";
}
default: {
@@ -432,6 +447,7 @@
return "null";
}
+ case BASE_TYPE_ARRAY:
case BASE_TYPE_VECTOR: return "[]";
case BASE_TYPE_LONG:
@@ -439,9 +455,16 @@
return "BigInt('" + value.constant + "')";
}
- default:
- if (value.constant == "nan") { return "NaN"; }
+ default: {
+ if (StringIsFlatbufferNan(value.constant)) {
+ return "NaN";
+ } else if (StringIsFlatbufferPositiveInfinity(value.constant)) {
+ return "Infinity";
+ } else if (StringIsFlatbufferNegativeInfinity(value.constant)) {
+ return "-Infinity";
+ }
return value.constant;
+ }
}
}
@@ -464,6 +487,22 @@
case BASE_TYPE_BOOL: return allowNull ? "boolean|null" : "boolean";
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: return allowNull ? "bigint|null" : "bigint";
+ case BASE_TYPE_ARRAY: {
+ std::string name;
+ if (type.element == BASE_TYPE_LONG || type.element == BASE_TYPE_ULONG) {
+ name = "bigint[]";
+ } else if (type.element != BASE_TYPE_STRUCT) {
+ name = "number[]";
+ } else {
+ name = "any[]";
+ if (parser_.opts.generate_object_based_api) {
+ name = "(any|" +
+ GetTypeName(*type.struct_def, /*object_api =*/true) + ")[]";
+ }
+ }
+
+ return name + (allowNull ? "|null" : "");
+ }
default:
if (IsScalar(type.base_type)) {
if (type.enum_def) {
@@ -536,12 +575,91 @@
// Generate arguments for a struct inside a struct. To ensure names
// don't clash, and to make it obvious these arguments are constructing
// a nested struct, prefix the name with the field name.
- GenStructBody(*field.value.type.struct_def, body,
- nameprefix + field.name + "_");
+ GenStructBody(
+ *field.value.type.struct_def, body,
+ nameprefix.length() ? nameprefix + "_" + field.name : field.name);
} else {
- *body += " builder.write" + GenWriteMethod(field.value.type) + "(";
- if (field.value.type.base_type == BASE_TYPE_BOOL) { *body += "+"; }
- *body += nameprefix + field.name + ");\n";
+ auto element_type = field.value.type.element;
+
+ if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ switch (field.value.type.element) {
+ case BASE_TYPE_STRUCT: {
+ std::string str_last_item_idx =
+ NumToString(field.value.type.fixed_length - 1);
+ *body += "\n for (let i = " + str_last_item_idx +
+ "; i >= 0; --i" + ") {\n";
+
+ std::string fname = nameprefix.length()
+ ? nameprefix + "_" + field.name
+ : field.name;
+
+ *body += " const item = " + fname + "?.[i];\n\n";
+
+ if (parser_.opts.generate_object_based_api) {
+ *body += " if (item instanceof " +
+ GetTypeName(*field.value.type.struct_def,
+ /*object_api =*/true) +
+ ") {\n";
+ *body += " item.pack(builder);\n";
+ *body += " continue;\n";
+ *body += " }\n\n";
+ }
+
+ std::string class_name =
+ GetPrefixedName(*field.value.type.struct_def);
+ std::string pack_func_create_call =
+ class_name + ".create" + class_name + "(builder,\n";
+ pack_func_create_call +=
+ " " +
+ GenStructMemberValueTS(*field.value.type.struct_def, "item",
+ ",\n ", false) +
+ "\n ";
+ *body += " " + pack_func_create_call;
+ *body += " );\n }\n\n";
+
+ break;
+ }
+ default: {
+ std::string str_last_item_idx =
+ NumToString(field.value.type.fixed_length - 1);
+ std::string fname = nameprefix.length()
+ ? nameprefix + "_" + field.name
+ : field.name;
+
+ *body += "\n for (let i = " + str_last_item_idx +
+ "; i >= 0; --i) {\n";
+ *body += " builder.write";
+ *body += GenWriteMethod(
+ static_cast<flatbuffers::Type>(field.value.type.element));
+ *body += "(";
+ *body += element_type == BASE_TYPE_BOOL ? "+" : "";
+
+ if (element_type == BASE_TYPE_LONG ||
+ element_type == BASE_TYPE_ULONG) {
+ *body += "BigInt(" + fname + "?.[i] ?? 0));\n";
+ } else {
+ *body += "(" + fname + "?.[i] ?? 0));\n\n";
+ }
+ *body += " }\n\n";
+ break;
+ }
+ }
+ } else {
+ std::string fname =
+ nameprefix.length() ? nameprefix + "_" + field.name : field.name;
+
+ *body += " builder.write" + GenWriteMethod(field.value.type) + "(";
+ if (field.value.type.base_type == BASE_TYPE_BOOL) {
+ *body += "Number(Boolean(" + fname + ")));\n";
+ continue;
+ } else if (field.value.type.base_type == BASE_TYPE_LONG ||
+ field.value.type.base_type == BASE_TYPE_ULONG) {
+ *body += "BigInt(" + fname + " ?? 0));\n";
+ continue;
+ }
+
+ *body += fname + ");\n";
+ }
}
}
}
@@ -759,10 +877,10 @@
import.object_name = object_name;
import.bare_file_path = bare_file_path;
import.rel_file_path = rel_file_path;
- import.import_statement =
- "import { " + symbols_expression + " } from '" + rel_file_path + ".js';";
- import.export_statement =
- "export { " + symbols_expression + " } from '." + bare_file_path + ".js';";
+ import.import_statement = "import { " + symbols_expression + " } from '" +
+ rel_file_path + ".js';";
+ import.export_statement = "export { " + symbols_expression + " } from '." +
+ bare_file_path + ".js';";
import.dependency = &dependency;
import.dependent = &dependent;
@@ -903,7 +1021,7 @@
const auto conversion_function = GenUnionConvFuncName(enum_def);
ret = "(() => {\n";
- ret += " let temp = " + conversion_function + "(this." +
+ ret += " const temp = " + conversion_function + "(this." +
namer_.Method(field_name, "Type") + "(), " +
field_binded_method + ");\n";
ret += " if(temp === null) { return null; }\n";
@@ -916,17 +1034,20 @@
const auto conversion_function = GenUnionListConvFuncName(enum_def);
ret = "(() => {\n";
- ret += " let ret = [];\n";
+ ret += " const ret: (" +
+ GenObjApiUnionTypeTS(imports, *union_type.struct_def,
+ parser_.opts, *union_type.enum_def) +
+ ")[] = [];\n";
ret += " for(let targetEnumIndex = 0; targetEnumIndex < this." +
namer_.Method(field_name, "TypeLength") + "()" +
"; "
"++targetEnumIndex) {\n";
- ret += " let targetEnum = this." +
+ ret += " const targetEnum = this." +
namer_.Method(field_name, "Type") + "(targetEnumIndex);\n";
ret += " if(targetEnum === null || " + enum_type +
"[targetEnum!] === 'NONE') { "
"continue; }\n\n";
- ret += " let temp = " + conversion_function + "(targetEnum, " +
+ ret += " const temp = " + conversion_function + "(targetEnum, " +
field_binded_method + ", targetEnumIndex);\n";
ret += " if(temp === null) { continue; }\n";
ret += union_has_string ? " if(typeof temp === 'string') { "
@@ -973,6 +1094,11 @@
std::string nullValue = "0";
if (field.value.type.base_type == BASE_TYPE_BOOL) {
nullValue = "false";
+ } else if (field.value.type.base_type == BASE_TYPE_LONG ||
+ field.value.type.base_type == BASE_TYPE_ULONG) {
+ nullValue = "BigInt(0)";
+ } else if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ nullValue = "[]";
}
ret += "(" + curr_member_accessor + " ?? " + nullValue + ")";
} else {
@@ -1091,7 +1217,7 @@
break;
}
- case BASE_TYPE_VECTOR: {
+ case BASE_TYPE_ARRAY: {
auto vectortype = field.value.type.VectorType();
auto vectortypename =
GenTypeName(imports, struct_def, vectortype, false);
@@ -1102,13 +1228,15 @@
switch (vectortype.base_type) {
case BASE_TYPE_STRUCT: {
const auto &sd = *field.value.type.struct_def;
- field_type += GetTypeName(sd, /*object_api=*/true);
- ;
+ const auto field_type_name =
+ GetTypeName(sd, /*object_api=*/true);
+ field_type += field_type_name;
field_type += ")[]";
- field_val = GenBBAccess() + ".createObjList(" +
- field_binded_method + ", this." +
- namer_.Method(field, "Length") + "())";
+ field_val = GenBBAccess() + ".createObjList<" + vectortypename +
+ ", " + field_type_name + ">(" +
+ field_binded_method + ", " +
+ NumToString(field.value.type.fixed_length) + ")";
if (sd.fixed) {
field_offset_decl =
@@ -1128,7 +1256,7 @@
case BASE_TYPE_STRING: {
field_type += "string)[]";
- field_val = GenBBAccess() + ".createScalarList(" +
+ field_val = GenBBAccess() + ".createScalarList<string>(" +
field_binded_method + ", this." +
namer_.Field(field, "Length") + "())";
field_offset_decl =
@@ -1162,10 +1290,99 @@
field_type += vectortypename;
}
field_type += ")[]";
- field_val = GenBBAccess() + ".createScalarList(" +
+ field_val = GenBBAccess() + ".createScalarList<" +
+ vectortypename + ">(" + field_binded_method + ", " +
+ NumToString(field.value.type.fixed_length) + ")";
+
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, this." + field_field + ")";
+
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ auto vectortypename =
+ GenTypeName(imports, struct_def, vectortype, false);
+ is_vector = true;
+
+ field_type = "(";
+
+ switch (vectortype.base_type) {
+ case BASE_TYPE_STRUCT: {
+ const auto &sd = *field.value.type.struct_def;
+ const auto field_type_name =
+ GetTypeName(sd, /*object_api=*/true);
+ field_type += field_type_name;
+ field_type += ")[]";
+
+ field_val = GenBBAccess() + ".createObjList<" + vectortypename +
+ ", " + field_type_name + ">(" +
field_binded_method + ", this." +
namer_.Method(field, "Length") + "())";
+ if (sd.fixed) {
+ field_offset_decl =
+ "builder.createStructOffsetList(this." + field_field +
+ ", " + AddImport(imports, struct_def, struct_def).name +
+ "." + namer_.Method("start", field, "Vector") + ")";
+ } else {
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ field_field + "))";
+ }
+
+ break;
+ }
+
+ case BASE_TYPE_STRING: {
+ field_type += "string)[]";
+ field_val = GenBBAccess() + ".createScalarList<string>(" +
+ field_binded_method + ", this." +
+ namer_.Field(field, "Length") + "())";
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
+ break;
+ }
+
+ case BASE_TYPE_UNION: {
+ field_type += GenObjApiUnionTypeTS(
+ imports, struct_def, parser.opts, *(vectortype.enum_def));
+ field_type += ")[]";
+ field_val = GenUnionValTS(imports, struct_def, field_method,
+ vectortype, true);
+
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def).name + "." +
+ namer_.Method("create", field, "Vector") +
+ "(builder, builder.createObjectOffsetList(" + "this." +
+ namer_.Field(field) + "))";
+
+ break;
+ }
+ default: {
+ if (vectortype.enum_def) {
+ field_type += GenTypeName(imports, struct_def, vectortype,
+ false, HasNullDefault(field));
+ } else {
+ field_type += vectortypename;
+ }
+ field_type += ")[]";
+ field_val = GenBBAccess() + ".createScalarList<" +
+ vectortypename + ">(" + field_binded_method +
+ ", this." + namer_.Method(field, "Length") + "())";
+
field_offset_decl =
AddImport(imports, struct_def, struct_def).name + "." +
namer_.Method("create", field, "Vector") +
@@ -1260,7 +1477,7 @@
obj_api_class = "\n";
obj_api_class += "export class ";
obj_api_class += GetTypeName(struct_def, /*object_api=*/true);
- obj_api_class += " {\n";
+ obj_api_class += " implements flatbuffers.IGeneratedObject {\n";
obj_api_class += constructor_func;
obj_api_class += pack_func_prototype + pack_func_offset_decl +
pack_func_create_call + "\n}";
@@ -1298,12 +1515,17 @@
}
const std::string object_name = GetTypeName(struct_def);
+ const std::string object_api_name = GetTypeName(struct_def, true);
// Emit constructor
GenDocComment(struct_def.doc_comment, code_ptr);
code += "export class ";
code += object_name;
- code += " {\n";
+ if (parser.opts.generate_object_based_api)
+ code += " implements flatbuffers.IUnpackableObject<" + object_api_name +
+ "> {\n";
+ else
+ code += " {\n";
code += " bb: flatbuffers.ByteBuffer|null = null;\n";
code += " bb_pos = 0;\n";
@@ -1337,9 +1559,16 @@
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
- auto offset_prefix =
- " const offset = " + GenBBAccess() + ".__offset(this.bb_pos, " +
- NumToString(field.value.offset) + ");\n return offset ? ";
+ std::string offset_prefix = "";
+
+ if (field.value.type.base_type == BASE_TYPE_ARRAY) {
+ offset_prefix = " return ";
+ } else {
+ offset_prefix = " const offset = " + GenBBAccess() +
+ ".__offset(this.bb_pos, " +
+ NumToString(field.value.offset) + ");\n";
+ offset_prefix += " return offset ? ";
+ }
// Emit a scalar field
const auto is_string = IsString(field.value.type);
@@ -1379,9 +1608,11 @@
} else {
std::string index = "this.bb_pos + offset";
if (is_string) { index += ", optionalEncoding"; }
- code += offset_prefix +
- GenGetter(field.value.type, "(" + index + ")") + " : " +
- GenDefaultValue(field, imports);
+ code +=
+ offset_prefix + GenGetter(field.value.type, "(" + index + ")");
+ if (field.value.type.base_type != BASE_TYPE_ARRAY) {
+ code += " : " + GenDefaultValue(field, imports);
+ }
code += ";\n";
}
}
@@ -1414,6 +1645,95 @@
break;
}
+ case BASE_TYPE_ARRAY: {
+ auto vectortype = field.value.type.VectorType();
+ auto vectortypename =
+ GenTypeName(imports, struct_def, vectortype, false);
+ auto inline_size = InlineSize(vectortype);
+ auto index = "this.bb_pos + " + NumToString(field.value.offset) +
+ " + index" + MaybeScale(inline_size);
+ std::string ret_type;
+ bool is_union = false;
+ switch (vectortype.base_type) {
+ case BASE_TYPE_STRUCT: ret_type = vectortypename; break;
+ case BASE_TYPE_STRING: ret_type = vectortypename; break;
+ case BASE_TYPE_UNION:
+ ret_type = "?flatbuffers.Table";
+ is_union = true;
+ break;
+ default: ret_type = vectortypename;
+ }
+ GenDocComment(field.doc_comment, code_ptr);
+ std::string prefix = namer_.Method(field);
+ // TODO: make it work without any
+ // if (is_union) { prefix += "<T extends flatbuffers.Table>"; }
+ if (is_union) { prefix += ""; }
+ prefix += "(index: number";
+ if (is_union) {
+ const auto union_type =
+ GenUnionGenericTypeTS(*(field.value.type.enum_def));
+
+ vectortypename = union_type;
+ code += prefix + ", obj:" + union_type;
+ } else if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ code += prefix + ", obj?:" + vectortypename;
+ } else if (IsString(vectortype)) {
+ code += prefix + "):string\n";
+ code += prefix + ",optionalEncoding:flatbuffers.Encoding" +
+ "):" + vectortypename + "\n";
+ code += prefix + ",optionalEncoding?:any";
+ } else {
+ code += prefix;
+ }
+ code += "):" + vectortypename + "|null {\n";
+
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ code += offset_prefix + "(obj || " +
+ GenerateNewExpression(vectortypename);
+ code += ").__init(";
+ code += vectortype.struct_def->fixed
+ ? index
+ : GenBBAccess() + ".__indirect(" + index + ")";
+ code += ", " + GenBBAccess() + ")";
+ } else {
+ if (is_union) {
+ index = "obj, " + index;
+ } else if (IsString(vectortype)) {
+ index += ", optionalEncoding";
+ }
+ code += offset_prefix + GenGetter(vectortype, "(" + index + ")");
+ }
+
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_ARRAY: {
+ break;
+ }
+ case BASE_TYPE_BOOL: {
+ code += " : false";
+ break;
+ }
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG: {
+ code += " : BigInt(0)";
+ break;
+ }
+ default: {
+ if (IsScalar(field.value.type.element)) {
+ if (field.value.type.enum_def) {
+ code += field.value.constant;
+ } else {
+ code += " : 0";
+ }
+ } else {
+ code += ": null";
+ }
+ break;
+ }
+ }
+ code += ";\n";
+ break;
+ }
+
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
auto vectortypename =
diff --git a/third_party/flatbuffers/src/idl_parser.cpp b/third_party/flatbuffers/src/idl_parser.cpp
index 524c996..48d0f07 100644
--- a/third_party/flatbuffers/src/idl_parser.cpp
+++ b/third_party/flatbuffers/src/idl_parser.cpp
@@ -507,6 +507,8 @@
case ')':
case '[':
case ']':
+ case '<':
+ case '>':
case ',':
case ':':
case ';':
@@ -1584,7 +1586,6 @@
return NoError();
}
-
CheckedError Parser::ParseAlignAttribute(const std::string &align_constant,
size_t min_align, size_t *align) {
// Use uint8_t to avoid problems with size_t==`unsigned long` on LP64.
@@ -1614,6 +1615,7 @@
});
ECHECK(err);
+ const size_t alignment = InlineAlignment(type);
const size_t len = count * InlineSize(type) / InlineAlignment(type);
const size_t elemsize = InlineAlignment(type);
const auto force_align = field->attributes.Lookup("force_align");
@@ -1623,7 +1625,8 @@
if (align > 1) { builder_.ForceVectorAlignment(len, elemsize, align); }
}
- builder_.StartVector(len, elemsize);
+ // TODO Fix using element alignment as size (`elemsize`)!
+ builder_.StartVector(len, elemsize, alignment);
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;
@@ -2448,14 +2451,17 @@
EXPECT(kTokenIntegerConstant);
}
- ECHECK(evb.AcceptEnumerator());
-
if (opts.proto_mode && Is('[')) {
NEXT();
// ignore attributes on enums.
while (token_ != ']') NEXT();
NEXT();
+ } else {
+ // parse attributes in fbs schema
+ ECHECK(ParseMetaData(&ev.attributes));
}
+
+ ECHECK(evb.AcceptEnumerator());
}
if (!Is(opts.proto_mode ? ';' : ',')) break;
NEXT();
@@ -2550,7 +2556,8 @@
IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster |
IDLOptions::kKotlin | IDLOptions::kCpp | IDLOptions::kJava |
IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kBinary |
- IDLOptions::kGo | IDLOptions::kPython | IDLOptions::kJson;
+ IDLOptions::kGo | IDLOptions::kPython | IDLOptions::kJson |
+ IDLOptions::kNim;
unsigned long langs = opts.lang_to_generate;
return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs);
}
@@ -2561,7 +2568,7 @@
bool Parser::SupportsDefaultVectorsAndStrings() const {
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
- IDLOptions::kRust | IDLOptions::kSwift;
+ IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kNim;
return !(opts.lang_to_generate & ~supported_langs);
}
@@ -2569,14 +2576,14 @@
return (opts.lang_to_generate &
~(IDLOptions::kCpp | IDLOptions::kTs | IDLOptions::kPhp |
IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kKotlin |
- IDLOptions::kBinary | IDLOptions::kSwift)) == 0;
+ IDLOptions::kBinary | IDLOptions::kSwift | IDLOptions::kNim)) == 0;
}
bool Parser::SupportsAdvancedArrayFeatures() const {
return (opts.lang_to_generate &
~(IDLOptions::kCpp | IDLOptions::kPython | IDLOptions::kJava |
IDLOptions::kCSharp | IDLOptions::kJsonSchema | IDLOptions::kJson |
- IDLOptions::kBinary | IDLOptions::kRust)) == 0;
+ IDLOptions::kBinary | IDLOptions::kRust | IDLOptions::kTs)) == 0;
}
Namespace *Parser::UniqueNamespace(Namespace *ns) {
@@ -2891,6 +2898,8 @@
NEXT();
while (!Is(';')) { NEXT(); } // A variety of formats, just skip.
NEXT();
+ } else if (IsIdent("map")) {
+ ECHECK(ParseProtoMapField(struct_def));
} else {
std::vector<std::string> field_comment = doc_comment_;
// Parse the qualifier.
@@ -3025,6 +3034,41 @@
return NoError();
}
+CheckedError Parser::ParseProtoMapField(StructDef *struct_def) {
+ NEXT();
+ EXPECT('<');
+ Type key_type;
+ ECHECK(ParseType(key_type));
+ EXPECT(',');
+ Type value_type;
+ ECHECK(ParseType(value_type));
+ EXPECT('>');
+ auto field_name = attribute_;
+ NEXT();
+ EXPECT('=');
+ EXPECT(kTokenIntegerConstant);
+ EXPECT(';');
+
+ auto entry_table_name = ConvertCase(field_name, Case::kUpperCamel) + "Entry";
+ StructDef *entry_table;
+ ECHECK(StartStruct(entry_table_name, &entry_table));
+ entry_table->has_key = true;
+ FieldDef *key_field;
+ ECHECK(AddField(*entry_table, "key", key_type, &key_field));
+ key_field->key = true;
+ FieldDef *value_field;
+ ECHECK(AddField(*entry_table, "value", value_type, &value_field));
+
+ Type field_type;
+ field_type.base_type = BASE_TYPE_VECTOR;
+ field_type.element = BASE_TYPE_STRUCT;
+ field_type.struct_def = entry_table;
+ FieldDef *field;
+ ECHECK(AddField(*struct_def, field_name, field_type, &field));
+
+ return NoError();
+}
+
CheckedError Parser::ParseProtoKey() {
if (token_ == '(') {
NEXT();
@@ -3259,6 +3303,10 @@
return done;
}
+std::ptrdiff_t Parser::BytesConsumed() const {
+ return std::distance(source_, cursor_);
+}
+
CheckedError Parser::StartParseFile(const char *source,
const char *source_filename) {
file_being_parsed_ = source_filename ? source_filename : "";
@@ -3413,7 +3461,6 @@
return NoError();
}
-
CheckedError Parser::DoParse(const char *source, const char **include_paths,
const char *source_filename,
const char *include_filename) {
@@ -3601,9 +3648,11 @@
: nullptr);
}
}
- // Check that JSON file doesn't contain more objects or IDL directives.
- // Comments after JSON are allowed.
- EXPECT(kTokenEof);
+ if (opts.require_json_eof) {
+ // Check that JSON file doesn't contain more objects or IDL directives.
+ // Comments after JSON are allowed.
+ EXPECT(kTokenEof);
+ }
return NoError();
}
@@ -3635,6 +3684,44 @@
// Schema serialization functionality:
+static flatbuffers::Offset<
+ flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
+SerializeAttributesCommon(const SymbolTable<Value> &attributes,
+ FlatBufferBuilder *builder, const Parser &parser) {
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs;
+ for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) {
+ auto it = parser.known_attributes_.find(kv->first);
+ FLATBUFFERS_ASSERT(it != parser.known_attributes_.end());
+ if (parser.opts.binary_schema_builtins || !it->second) {
+ auto key = builder->CreateString(kv->first);
+ auto val = builder->CreateString(kv->second->constant);
+ attrs.push_back(reflection::CreateKeyValue(*builder, key, val));
+ }
+ }
+ if (attrs.size()) {
+ return builder->CreateVectorOfSortedTables(&attrs);
+ } else {
+ return 0;
+ }
+}
+
+static bool DeserializeAttributesCommon(
+ SymbolTable<Value> &attributes, Parser &parser,
+ const Vector<Offset<reflection::KeyValue>> *attrs) {
+ if (attrs == nullptr) return true;
+ for (uoffset_t i = 0; i < attrs->size(); ++i) {
+ auto kv = attrs->Get(i);
+ auto value = new Value();
+ if (kv->value()) { value->constant = kv->value()->str(); }
+ if (attributes.Add(kv->key()->str(), value)) {
+ delete value;
+ return false;
+ }
+ parser.known_attributes_[kv->key()->str()];
+ }
+ return true;
+}
+
void Parser::Serialize() {
builder_.Clear();
AssignIndices(structs_.vec);
@@ -3927,32 +4014,52 @@
return true;
}
-Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder,
- const Parser &parser) const {
- 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, type__, docs__);
+flatbuffers::Offset<
+ flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
+EnumVal::SerializeAttributes(FlatBufferBuilder *builder,
+ const Parser &parser) const {
+ return SerializeAttributesCommon(attributes, builder, parser);
}
-bool EnumVal::Deserialize(const Parser &parser,
- const reflection::EnumVal *val) {
+bool EnumVal::DeserializeAttributes(
+ Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs) {
+ return DeserializeAttributesCommon(attributes, parser, attrs);
+}
+
+Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const {
+ const auto name__ = builder->CreateString(name);
+ const auto type__ = union_type.Serialize(builder);
+ const auto attr__ = SerializeAttributes(builder, parser);
+ const auto docs__ = parser.opts.binary_schema_comments
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ return reflection::CreateEnumVal(*builder, name__, value, type__, docs__,
+ attr__);
+}
+
+bool EnumVal::Deserialize(Parser &parser, const reflection::EnumVal *val) {
name = val->name()->str();
value = val->value();
if (!union_type.Deserialize(parser, val->union_type())) return false;
+ if (!DeserializeAttributes(parser, val->attributes())) return false;
DeserializeDoc(doc_comment, val->documentation());
return true;
}
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
+ size_t element_size = SizeOf(element);
+ if (base_type == BASE_TYPE_VECTOR && element == BASE_TYPE_STRUCT &&
+ struct_def->bytesize != 0) {
+ // struct_def->bytesize==0 means struct is table
+ element_size = struct_def->bytesize;
+ }
return reflection::CreateType(
*builder, static_cast<reflection::BaseType>(base_type),
static_cast<reflection::BaseType>(element),
struct_def ? struct_def->index : (enum_def ? enum_def->index : -1),
fixed_length, static_cast<uint32_t>(SizeOf(base_type)),
- static_cast<uint32_t>(SizeOf(element)));
+ static_cast<uint32_t>(element_size));
}
bool Type::Deserialize(const Parser &parser, const reflection::Type *type) {
@@ -3986,37 +4093,12 @@
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
Definition::SerializeAttributes(FlatBufferBuilder *builder,
const Parser &parser) const {
- std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs;
- for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) {
- auto it = parser.known_attributes_.find(kv->first);
- FLATBUFFERS_ASSERT(it != parser.known_attributes_.end());
- if (parser.opts.binary_schema_builtins || !it->second) {
- auto key = builder->CreateString(kv->first);
- auto val = builder->CreateString(kv->second->constant);
- attrs.push_back(reflection::CreateKeyValue(*builder, key, val));
- }
- }
- if (attrs.size()) {
- return builder->CreateVectorOfSortedTables(&attrs);
- } else {
- return 0;
- }
+ return SerializeAttributesCommon(attributes, builder, parser);
}
bool Definition::DeserializeAttributes(
Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs) {
- if (attrs == nullptr) return true;
- for (uoffset_t i = 0; i < attrs->size(); ++i) {
- auto kv = attrs->Get(i);
- auto value = new Value();
- if (kv->value()) { value->constant = kv->value()->str(); }
- if (attributes.Add(kv->key()->str(), value)) {
- delete value;
- return false;
- }
- parser.known_attributes_[kv->key()->str()];
- }
- return true;
+ return DeserializeAttributesCommon(attributes, parser, attrs);
}
/************************************************************************/
@@ -4131,17 +4213,19 @@
struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name);
auto struct_def_base = base.LookupStruct(qualified_name);
if (!struct_def_base) continue;
+ std::set<FieldDef *> renamed_fields;
for (auto fit = struct_def.fields.vec.begin();
fit != struct_def.fields.vec.end(); ++fit) {
auto &field = **fit;
auto field_base = struct_def_base->fields.Lookup(field.name);
+ const auto qualified_field_name = qualified_name + "." + field.name;
if (field_base) {
if (field.value.offset != field_base->value.offset)
- return "offsets differ for field: " + field.name;
+ return "offsets differ for field: " + qualified_field_name;
if (field.value.constant != field_base->value.constant)
- return "defaults differ for field: " + field.name;
+ return "defaults differ for field: " + qualified_field_name;
if (!EqualByName(field.value.type, field_base->value.type))
- return "types differ for field: " + field.name;
+ return "types differ for field: " + qualified_field_name;
} else {
// Doesn't have to exist, deleting fields is fine.
// But we should check if there is a field that has the same offset
@@ -4150,14 +4234,28 @@
fbit != struct_def_base->fields.vec.end(); ++fbit) {
field_base = *fbit;
if (field.value.offset == field_base->value.offset) {
+ renamed_fields.insert(field_base);
if (!EqualByName(field.value.type, field_base->value.type))
- return "field renamed to different type: " + field.name;
+ return "field renamed to different type: " + qualified_field_name;
break;
}
}
}
}
+ // deletion of trailing fields are not allowed
+ for (auto fit = struct_def_base->fields.vec.begin();
+ fit != struct_def_base->fields.vec.end(); ++fit) {
+ auto &field_base = **fit;
+ // not a renamed field
+ if (renamed_fields.find(&field_base) == renamed_fields.end()) {
+ auto field = struct_def.fields.Lookup(field_base.name);
+ if (!field) {
+ return "field deleted: " + qualified_name + "." + field_base.name;
+ }
+ }
+ }
}
+
for (auto eit = enums_.vec.begin(); eit != enums_.vec.end(); ++eit) {
auto &enum_def = **eit;
auto qualified_name =
diff --git a/third_party/flatbuffers/src/reflection.cpp b/third_party/flatbuffers/src/reflection.cpp
index 7549859..5ddff63 100644
--- a/third_party/flatbuffers/src/reflection.cpp
+++ b/third_party/flatbuffers/src/reflection.cpp
@@ -689,9 +689,10 @@
FLATBUFFERS_FALLTHROUGH(); // fall thru
default: { // Scalars and structs.
auto element_size = GetTypeSize(element_base_type);
+ auto element_alignment = element_size; // For primitive elements
if (elemobjectdef && elemobjectdef->is_struct())
element_size = elemobjectdef->bytesize();
- fbb.StartVector(vec->size(), element_size);
+ fbb.StartVector(vec->size(), element_size, element_alignment);
fbb.PushBytes(vec->Data(), element_size * vec->size());
offset = fbb.EndVector(vec->size());
break;
diff --git a/third_party/flatbuffers/src/util.cpp b/third_party/flatbuffers/src/util.cpp
index df324e8..aabc23a 100644
--- a/third_party/flatbuffers/src/util.cpp
+++ b/third_party/flatbuffers/src/util.cpp
@@ -109,7 +109,7 @@
} else if (!islower(input[i])) {
// Prevent duplicate underscores for Upper_Snake_Case strings
// and UPPERCASE strings.
- if (islower(input[i - 1])) { s += '_'; }
+ if (islower(input[i - 1]) || (isdigit(input[i-1]) && !isdigit(input[i]))) { s += '_'; }
s += screaming ? CharToUpper(input[i]) : CharToLower(input[i]);
} else {
s += screaming ? CharToUpper(input[i]) : input[i];
@@ -135,7 +135,7 @@
} else if (!islower(input[i])) {
// Prevent duplicate underscores for Upper_Snake_Case strings
// and UPPERCASE strings.
- if (islower(input[i - 1])) { s += '_'; }
+ if (islower(input[i - 1]) || (isdigit(input[i-1]) && !isdigit(input[i]))) { s += '_'; }
s += CharToLower(input[i]);
} else {
s += input[i];