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