diff options
author | Derek Bailey <derekbailey@google.com> | 2023-05-09 09:16:30 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-09 09:16:30 -0700 |
commit | 63b7b25289447313ab6e79191fa1733748dca0da (patch) | |
tree | 02dca2de1983039084f49d6f32b22e8c277e6cee /tests | |
parent | 13fc75cb6b7b44793f3f5b4ba025ff403d012c9f (diff) | |
download | flatbuffers-63b7b25289447313ab6e79191fa1733748dca0da.tar.gz flatbuffers-63b7b25289447313ab6e79191fa1733748dca0da.tar.bz2 flatbuffers-63b7b25289447313ab6e79191fa1733748dca0da.zip |
FlatBuffers 64 for C++ (#7935)
* First working hack of adding 64-bit. Don't judge :)
* Made vector_downward work on 64 bit types
* vector_downward uses size_t, added offset64 to reflection
* cleaned up adding offset64 in parser
* Add C++ testing skeleton for 64-bit
* working test for CreateVector64
* working >2 GiB buffers
* support for large strings
* simplified CreateString<> to just provide the offset type
* generalize CreateVector template
* update test_64.afb due to upstream format change
* Added Vector64 type, which is just an alias for vector ATM
* Switch to Offset64 for Vector64
* Update for reflection bfbs output change
* Starting to add support for vector64 type in C++
* made a generic CreateVector that can handle different offsets and vector types
* Support for 32-vector with 64-addressing
* Vector64 basic builder + tests working
* basic support for json vector64 support
* renamed fields in test_64bit.fbs to better reflect their use
* working C++ vector64 builder
* Apply --annotate-sparse-vector to 64-bit tests
* Enable Vector64 for --annotate-sparse-vectors
* Merged from upstream
* Add `near_string` field for testing 32-bit offsets alongside
* keep track of where the 32-bit and 64-bit regions are for flatbufferbuilder
* move template<> outside class body for GCC
* update run.sh to build and run tests
* basic assertion for adding 64-bit offset at the wrong time
* started to separate `FlatBufferBuilder` into two classes, 1 64-bit aware, the other not
* add test for nested flatbuffer vector64, fix bug in alignment of big vectors
* fixed CreateDirect method by iterating by Offset64 first
* internal refactoring of flatbufferbuilder
* block not supported languages in the parser from using 64-bit
* evolution tests for adding a vector64 field
* conformity tests for adding/removing offset64 attributes
* ensure test is for a big buffer
* add parser error tests for `offset64` and `vector64` attributes
* add missing static that GCC only complains about
* remove stdint-uintn.h header that gets automatically added
* move 64-bit CalculateOffset internal
* fixed return size of EndVector
* various fixes on windows
* add SizeT to vector_downward
* minimze range of size changes in vector and builder
* reworked how tracking if 64-offsets are added
* Add ReturnT to EndVector
* small cleanups
* remove need for second Array definition
* combine IndirectHelpers into one definition
* started support for vector of struct
* Support for 32/64-vectors of structs + Offset64
* small cleanups
* add verification for vector64
* add sized prefix for 64-bit buffers
* add fuzzer for 64-bit
* add example of adding many vectors using a wrapper table
* run the new -bfbs-gen-embed logic on the 64-bit tests
* remove run.sh and fix cmakelist issue
* fixed bazel rules
* fixed some PR comments
* add 64-bit tests to cmakelist
Diffstat (limited to 'tests')
24 files changed, 2039 insertions, 28 deletions
diff --git a/tests/64bit/evolution/v1.fbs b/tests/64bit/evolution/v1.fbs new file mode 100644 index 00000000..dcdc0bad --- /dev/null +++ b/tests/64bit/evolution/v1.fbs @@ -0,0 +1,8 @@ +namespace v1; + +table RootTable { + a:float; + b:[uint8]; +} + +root_type RootTable; diff --git a/tests/64bit/evolution/v1_generated.h b/tests/64bit/evolution/v1_generated.h new file mode 100644 index 00000000..49ed0f0e --- /dev/null +++ b/tests/64bit/evolution/v1_generated.h @@ -0,0 +1,219 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_V1_V1_H_ +#define FLATBUFFERS_GENERATED_V1_V1_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && + FLATBUFFERS_VERSION_MINOR == 5 && + FLATBUFFERS_VERSION_REVISION == 8, + "Non-compatible flatbuffers version included"); + +namespace v1 { + +struct RootTable; +struct RootTableBuilder; +struct RootTableT; + +bool operator==(const RootTableT &lhs, const RootTableT &rhs); +bool operator!=(const RootTableT &lhs, const RootTableT &rhs); + +inline const ::flatbuffers::TypeTable *RootTableTypeTable(); + +struct RootTableT : public ::flatbuffers::NativeTable { + typedef RootTable TableType; + float a = 0.0f; + std::vector<uint8_t> b{}; +}; + +struct RootTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef RootTableT NativeTableType; + typedef RootTableBuilder Builder; + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return RootTableTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_A = 4, + VT_B = 6 + }; + float a() const { + return GetField<float>(VT_A, 0.0f); + } + bool mutate_a(float _a = 0.0f) { + return SetField<float>(VT_A, _a, 0.0f); + } + const ::flatbuffers::Vector<uint8_t> *b() const { + return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_B); + } + ::flatbuffers::Vector<uint8_t> *mutable_b() { + return GetPointer<::flatbuffers::Vector<uint8_t> *>(VT_B); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<float>(verifier, VT_A, 4) && + VerifyOffset(verifier, VT_B) && + verifier.VerifyVector(b()) && + verifier.EndTable(); + } + RootTableT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(RootTableT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset<RootTable> Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RootTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct RootTableBuilder { + typedef RootTable Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + void add_a(float a) { + fbb_.AddElement<float>(RootTable::VT_A, a, 0.0f); + } + void add_b(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> b) { + fbb_.AddOffset(RootTable::VT_B, b); + } + explicit RootTableBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset<RootTable> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset<RootTable>(end); + return o; + } +}; + +inline ::flatbuffers::Offset<RootTable> CreateRootTable( + ::flatbuffers::FlatBufferBuilder &_fbb, + float a = 0.0f, + ::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> b = 0) { + RootTableBuilder builder_(_fbb); + builder_.add_b(b); + builder_.add_a(a); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset<RootTable> CreateRootTableDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + float a = 0.0f, + const std::vector<uint8_t> *b = nullptr) { + auto b__ = b ? _fbb.CreateVector<uint8_t>(*b) : 0; + return v1::CreateRootTable( + _fbb, + a, + b__); +} + +::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + + +inline bool operator==(const RootTableT &lhs, const RootTableT &rhs) { + return + (lhs.a == rhs.a) && + (lhs.b == rhs.b); +} + +inline bool operator!=(const RootTableT &lhs, const RootTableT &rhs) { + return !(lhs == rhs); +} + + +inline RootTableT *RootTable::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr<RootTableT>(new RootTableT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void RootTable::UnPackTo(RootTableT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = a(); _o->a = _e; } + { auto _e = b(); if (_e) { _o->b.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->b.begin()); } } +} + +inline ::flatbuffers::Offset<RootTable> RootTable::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RootTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateRootTable(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const RootTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _a = _o->a; + auto _b = _o->b.size() ? _fbb.CreateVector(_o->b) : 0; + return v1::CreateRootTable( + _fbb, + _a, + _b); +} + +inline const ::flatbuffers::TypeTable *RootTableTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_FLOAT, 0, -1 }, + { ::flatbuffers::ET_UCHAR, 1, -1 } + }; + static const char * const names[] = { + "a", + "b" + }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_TABLE, 2, type_codes, nullptr, nullptr, nullptr, names + }; + return &tt; +} + +inline const v1::RootTable *GetRootTable(const void *buf) { + return ::flatbuffers::GetRoot<v1::RootTable>(buf); +} + +inline const v1::RootTable *GetSizePrefixedRootTable(const void *buf) { + return ::flatbuffers::GetSizePrefixedRoot<v1::RootTable>(buf); +} + +inline RootTable *GetMutableRootTable(void *buf) { + return ::flatbuffers::GetMutableRoot<RootTable>(buf); +} + +inline v1::RootTable *GetMutableSizePrefixedRootTable(void *buf) { + return ::flatbuffers::GetMutableSizePrefixedRoot<v1::RootTable>(buf); +} + +inline bool VerifyRootTableBuffer( + ::flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer<v1::RootTable>(nullptr); +} + +inline bool VerifySizePrefixedRootTableBuffer( + ::flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer<v1::RootTable>(nullptr); +} + +inline void FinishRootTableBuffer( + ::flatbuffers::FlatBufferBuilder &fbb, + ::flatbuffers::Offset<v1::RootTable> root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedRootTableBuffer( + ::flatbuffers::FlatBufferBuilder &fbb, + ::flatbuffers::Offset<v1::RootTable> root) { + fbb.FinishSizePrefixed(root); +} + +inline std::unique_ptr<v1::RootTableT> UnPackRootTable( + const void *buf, + const ::flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr<v1::RootTableT>(GetRootTable(buf)->UnPack(res)); +} + +inline std::unique_ptr<v1::RootTableT> UnPackSizePrefixedRootTable( + const void *buf, + const ::flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr<v1::RootTableT>(GetSizePrefixedRootTable(buf)->UnPack(res)); +} + +} // namespace v1 + +#endif // FLATBUFFERS_GENERATED_V1_V1_H_ diff --git a/tests/64bit/evolution/v2.fbs b/tests/64bit/evolution/v2.fbs new file mode 100644 index 00000000..f83e5109 --- /dev/null +++ b/tests/64bit/evolution/v2.fbs @@ -0,0 +1,9 @@ +namespace v2; + +table RootTable { + a:float; + b:[uint8]; + big_vector:[uint8] (vector64); +} + +root_type RootTable; diff --git a/tests/64bit/evolution/v2_generated.h b/tests/64bit/evolution/v2_generated.h new file mode 100644 index 00000000..a46847df --- /dev/null +++ b/tests/64bit/evolution/v2_generated.h @@ -0,0 +1,243 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_V2_V2_H_ +#define FLATBUFFERS_GENERATED_V2_V2_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && + FLATBUFFERS_VERSION_MINOR == 5 && + FLATBUFFERS_VERSION_REVISION == 8, + "Non-compatible flatbuffers version included"); + +namespace v2 { + +struct RootTable; +struct RootTableBuilder; +struct RootTableT; + +bool operator==(const RootTableT &lhs, const RootTableT &rhs); +bool operator!=(const RootTableT &lhs, const RootTableT &rhs); + +inline const ::flatbuffers::TypeTable *RootTableTypeTable(); + +struct RootTableT : public ::flatbuffers::NativeTable { + typedef RootTable TableType; + float a = 0.0f; + std::vector<uint8_t> b{}; + std::vector<uint8_t> big_vector{}; +}; + +struct RootTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef RootTableT NativeTableType; + typedef RootTableBuilder Builder; + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return RootTableTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_A = 4, + VT_B = 6, + VT_BIG_VECTOR = 8 + }; + float a() const { + return GetField<float>(VT_A, 0.0f); + } + bool mutate_a(float _a = 0.0f) { + return SetField<float>(VT_A, _a, 0.0f); + } + const ::flatbuffers::Vector<uint8_t> *b() const { + return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_B); + } + ::flatbuffers::Vector<uint8_t> *mutable_b() { + return GetPointer<::flatbuffers::Vector<uint8_t> *>(VT_B); + } + const ::flatbuffers::Vector64<uint8_t> *big_vector() const { + return GetPointer64<const ::flatbuffers::Vector64<uint8_t> *>(VT_BIG_VECTOR); + } + ::flatbuffers::Vector64<uint8_t> *mutable_big_vector() { + return GetPointer64<::flatbuffers::Vector64<uint8_t> *>(VT_BIG_VECTOR); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<float>(verifier, VT_A, 4) && + VerifyOffset(verifier, VT_B) && + verifier.VerifyVector(b()) && + VerifyOffset64(verifier, VT_BIG_VECTOR) && + verifier.VerifyVector(big_vector()) && + verifier.EndTable(); + } + RootTableT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(RootTableT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset<RootTable> Pack(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct RootTableBuilder { + typedef RootTable Table; + ::flatbuffers::FlatBufferBuilder64 &fbb_; + ::flatbuffers::uoffset_t start_; + void add_a(float a) { + fbb_.AddElement<float>(RootTable::VT_A, a, 0.0f); + } + void add_b(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> b) { + fbb_.AddOffset(RootTable::VT_B, b); + } + void add_big_vector(::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> big_vector) { + fbb_.AddOffset(RootTable::VT_BIG_VECTOR, big_vector); + } + explicit RootTableBuilder(::flatbuffers::FlatBufferBuilder64 &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset<RootTable> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset<RootTable>(end); + return o; + } +}; + +inline ::flatbuffers::Offset<RootTable> CreateRootTable( + ::flatbuffers::FlatBufferBuilder64 &_fbb, + float a = 0.0f, + ::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> b = 0, + ::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> big_vector = 0) { + RootTableBuilder builder_(_fbb); + builder_.add_big_vector(big_vector); + builder_.add_b(b); + builder_.add_a(a); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset<RootTable> CreateRootTableDirect( + ::flatbuffers::FlatBufferBuilder64 &_fbb, + float a = 0.0f, + const std::vector<uint8_t> *b = nullptr, + const std::vector<uint8_t> *big_vector = nullptr) { + auto big_vector__ = big_vector ? _fbb.CreateVector64(*big_vector) : 0; + auto b__ = b ? _fbb.CreateVector<uint8_t>(*b) : 0; + return v2::CreateRootTable( + _fbb, + a, + b__, + big_vector__); +} + +::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + + +inline bool operator==(const RootTableT &lhs, const RootTableT &rhs) { + return + (lhs.a == rhs.a) && + (lhs.b == rhs.b) && + (lhs.big_vector == rhs.big_vector); +} + +inline bool operator!=(const RootTableT &lhs, const RootTableT &rhs) { + return !(lhs == rhs); +} + + +inline RootTableT *RootTable::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr<RootTableT>(new RootTableT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void RootTable::UnPackTo(RootTableT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = a(); _o->a = _e; } + { auto _e = b(); if (_e) { _o->b.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->b.begin()); } } + { auto _e = big_vector(); if (_e) { _o->big_vector.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->big_vector.begin()); } } +} + +inline ::flatbuffers::Offset<RootTable> RootTable::Pack(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateRootTable(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder64 *__fbb; const RootTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _a = _o->a; + auto _b = _o->b.size() ? _fbb.CreateVector(_o->b) : 0; + auto _big_vector = _o->big_vector.size() ? _fbb.CreateVector64(_o->big_vector) : 0; + return v2::CreateRootTable( + _fbb, + _a, + _b, + _big_vector); +} + +inline const ::flatbuffers::TypeTable *RootTableTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_FLOAT, 0, -1 }, + { ::flatbuffers::ET_UCHAR, 1, -1 }, + { ::flatbuffers::ET_UCHAR, 1, -1 } + }; + static const char * const names[] = { + "a", + "b", + "big_vector" + }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_TABLE, 3, type_codes, nullptr, nullptr, nullptr, names + }; + return &tt; +} + +inline const v2::RootTable *GetRootTable(const void *buf) { + return ::flatbuffers::GetRoot<v2::RootTable>(buf); +} + +inline const v2::RootTable *GetSizePrefixedRootTable(const void *buf) { + return ::flatbuffers::GetSizePrefixedRoot<v2::RootTable,::flatbuffers::uoffset64_t>(buf); +} + +inline RootTable *GetMutableRootTable(void *buf) { + return ::flatbuffers::GetMutableRoot<RootTable>(buf); +} + +inline v2::RootTable *GetMutableSizePrefixedRootTable(void *buf) { + return ::flatbuffers::GetMutableSizePrefixedRoot<v2::RootTable,::flatbuffers::uoffset64_t>(buf); +} + +inline bool VerifyRootTableBuffer( + ::flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer<v2::RootTable>(nullptr); +} + +inline bool VerifySizePrefixedRootTableBuffer( + ::flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer<v2::RootTable,::flatbuffers::uoffset64_t>(nullptr); +} + +inline void FinishRootTableBuffer( + ::flatbuffers::FlatBufferBuilder64 &fbb, + ::flatbuffers::Offset<v2::RootTable> root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedRootTableBuffer( + ::flatbuffers::FlatBufferBuilder64 &fbb, + ::flatbuffers::Offset<v2::RootTable> root) { + fbb.FinishSizePrefixed(root); +} + +inline std::unique_ptr<v2::RootTableT> UnPackRootTable( + const void *buf, + const ::flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr<v2::RootTableT>(GetRootTable(buf)->UnPack(res)); +} + +inline std::unique_ptr<v2::RootTableT> UnPackSizePrefixedRootTable( + const void *buf, + const ::flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr<v2::RootTableT>(GetSizePrefixedRootTable(buf)->UnPack(res)); +} + +} // namespace v2 + +#endif // FLATBUFFERS_GENERATED_V2_V2_H_ diff --git a/tests/64bit/offset64_test.cpp b/tests/64bit/offset64_test.cpp new file mode 100644 index 00000000..8e91fbea --- /dev/null +++ b/tests/64bit/offset64_test.cpp @@ -0,0 +1,447 @@ +#include "offset64_test.h" + +#include <stdint.h> + +#include <cstdint> +#include <fstream> +#include <limits> +#include <ostream> + +#include "evolution/v1_generated.h" +#include "evolution/v2_generated.h" +#include "flatbuffers/base.h" +#include "flatbuffers/buffer.h" +#include "flatbuffers/flatbuffer_builder.h" +#include "flatbuffers/flatbuffers.h" +#include "test_64bit_generated.h" +#include "test_assert.h" + +namespace flatbuffers { +namespace tests { + +void Offset64Test() { + FlatBufferBuilder64 builder; + + const size_t far_vector_size = 1LL << 2; + const size_t big_vector_size = 1LL << 31; + + { + // First create the vectors that will be copied to the buffer. + std::vector<uint8_t> far_data; + far_data.resize(far_vector_size); + far_data[0] = 4; + far_data[far_vector_size - 1] = 2; + + std::vector<uint8_t> big_data; + big_data.resize(big_vector_size); + big_data[0] = 8; + big_data[big_vector_size - 1] = 3; + + // Then serialize all the fields that have 64-bit offsets, as these must be + // serialized before any 32-bit fields are added to the buffer. + const Offset64<Vector<uint8_t>> far_vector_offset = + builder.CreateVector64<Vector>(far_data); + + const Offset64<String> far_string_offset = + builder.CreateString<Offset64>("some far string"); + + const Offset64<Vector64<uint8_t>> big_vector_offset = + builder.CreateVector64(big_data); + + // Now that we are done with the 64-bit fields, we can create and add the + // normal fields. + const Offset<String> near_string_offset = + builder.CreateString("some near string"); + + // Finish by building the root table by passing in all the offsets. + const Offset<RootTable> root_table_offset = + CreateRootTable(builder, far_vector_offset, 0, far_string_offset, + big_vector_offset, near_string_offset); + + // Finish the buffer. + builder.Finish(root_table_offset); + + // Ensure the buffer is big. + TEST_ASSERT(builder.GetSize() > FLATBUFFERS_MAX_BUFFER_SIZE); + + Verifier::Options options; + // Allow the verifier to verify 64-bit buffers. + options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE; + options.assert = true; + + Verifier verifier(builder.GetBufferPointer(), builder.GetSize(), options); + + TEST_EQ(VerifyRootTableBuffer(verifier), true); + } + + { + const RootTable *root_table = GetRootTable(builder.GetBufferPointer()); + + // Expect the far vector to be properly sized. + TEST_EQ(root_table->far_vector()->size(), far_vector_size); + TEST_EQ(root_table->far_vector()->Get(0), 4); + TEST_EQ(root_table->far_vector()->Get(far_vector_size - 1), 2); + + TEST_EQ_STR(root_table->far_string()->c_str(), "some far string"); + + // Expect the big vector to be properly sized. + TEST_EQ(root_table->big_vector()->size(), big_vector_size); + TEST_EQ(root_table->big_vector()->Get(0), 8); + TEST_EQ(root_table->big_vector()->Get(big_vector_size - 1), 3); + + TEST_EQ_STR(root_table->near_string()->c_str(), "some near string"); + } +} + +void Offset64SerializedFirst() { + FlatBufferBuilder64 fbb; + + // First create the vectors that will be copied to the buffer. + std::vector<uint8_t> data; + data.resize(64); + + // Then serialize all the fields that have 64-bit offsets, as these must be + // serialized before any 32-bit fields are added to the buffer. + fbb.CreateVector64(data); + + // TODO(derekbailey): figure out how to test assertions. + // Uncommenting this line should fail the test with an assertion. + // fbb.CreateString("some near string"); + + fbb.CreateVector64(data); +} + +void Offset64NestedFlatBuffer() { + FlatBufferBuilder64 fbb; + + // First serialize a nested buffer. + const Offset<String> near_string_offset = + fbb.CreateString("nested: some near string"); + + // Finish by building the root table by passing in all the offsets. + const Offset<RootTable> root_table_offset = + CreateRootTable(fbb, 0, 0, 0, 0, near_string_offset, 0); + + // Finish the buffer. + fbb.Finish(root_table_offset); + + // Ensure the buffer is valid. + const RootTable *root_table = GetRootTable(fbb.GetBufferPointer()); + TEST_EQ_STR(root_table->near_string()->c_str(), "nested: some near string"); + + // Copy the data out of the builder. + std::vector<uint8_t> nested_data{ fbb.GetBufferPointer(), + fbb.GetBufferPointer() + fbb.GetSize() }; + + { + // Clear so we can reuse the builder. + fbb.Clear(); + + const Offset64<Vector64<uint8_t>> nested_flatbuffer_offset = + fbb.CreateVector64<Vector64>(nested_data); + + // Now that we are done with the 64-bit fields, we can create and add the + // normal fields. + const Offset<String> near_string_offset = + fbb.CreateString("some near string"); + + // Finish by building the root table by passing in all the offsets. + const Offset<RootTable> root_table_offset = CreateRootTable( + fbb, 0, 0, 0, 0, near_string_offset, nested_flatbuffer_offset); + + // Finish the buffer. + fbb.Finish(root_table_offset); + + Verifier::Options options; + // Allow the verifier to verify 64-bit buffers. + options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE; + options.assert = true; + + Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize(), options); + + TEST_EQ(VerifyRootTableBuffer(verifier), true); + } + + { + const RootTable *root_table = GetRootTable(fbb.GetBufferPointer()); + + // Test that the parent buffer field is ok. + TEST_EQ_STR(root_table->near_string()->c_str(), "some near string"); + + // Expect nested buffer to be properly sized. + TEST_EQ(root_table->nested_root()->size(), nested_data.size()); + + // Expect the direct accessors to the nested buffer work. + TEST_EQ_STR(root_table->nested_root_nested_root()->near_string()->c_str(), + "nested: some near string"); + } +} + +void Offset64CreateDirect() { + FlatBufferBuilder64 fbb; + + // Create a vector of some data + std::vector<uint8_t> data{ 0, 1, 2 }; + + // Call the "Direct" creation method to ensure that things are added to the + // buffer in the correct order, Offset64 first followed by any Offsets. + const Offset<RootTable> root_table_offset = CreateRootTableDirect( + fbb, &data, 0, "some far string", &data, "some near string"); + + // Finish the buffer. + fbb.Finish(root_table_offset); + + Verifier::Options options; + // Allow the verifier to verify 64-bit buffers. + options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE; + options.assert = true; + + Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize(), options); + + TEST_EQ(VerifyRootTableBuffer(verifier), true); + + // Verify the data. + const RootTable *root_table = GetRootTable(fbb.GetBufferPointer()); + TEST_EQ(root_table->far_vector()->size(), data.size()); + TEST_EQ(root_table->big_vector()->size(), data.size()); + TEST_EQ_STR(root_table->far_string()->c_str(), "some far string"); + TEST_EQ_STR(root_table->near_string()->c_str(), "some near string"); +} + +void Offset64Evolution() { + // Some common data for the tests. + const std::vector<uint8_t> data = { 1, 2, 3, 4 }; + const std::vector<uint8_t> big_data = { 6, 7, 8, 9, 10 }; + + // Built V1 read V2 + { + // Use the 32-bit builder since V1 doesn't have any 64-bit offsets. + FlatBufferBuilder builder; + + builder.Finish(v1::CreateRootTableDirect(builder, 1234, &data)); + + // Use each version to get a view at the root table. + auto v1_root = v1::GetRootTable(builder.GetBufferPointer()); + auto v2_root = v2::GetRootTable(builder.GetBufferPointer()); + + // Test field equivalents for fields common to V1 and V2. + TEST_EQ(v1_root->a(), v2_root->a()); + + TEST_EQ(v1_root->b(), v2_root->b()); + TEST_EQ(v1_root->b()->Get(2), 3); + TEST_EQ(v2_root->b()->Get(2), 3); + + // This field is added in V2, so it should be null since V1 couldn't have + // written it. + TEST_ASSERT(v2_root->big_vector() == nullptr); + } + + // Built V2 read V1 + { + // Use the 64-bit builder since V2 has 64-bit offsets. + FlatBufferBuilder64 builder; + + builder.Finish(v2::CreateRootTableDirect(builder, 1234, &data, &big_data)); + + // Use each version to get a view at the root table. + auto v1_root = v1::GetRootTable(builder.GetBufferPointer()); + auto v2_root = v2::GetRootTable(builder.GetBufferPointer()); + + // Test field equivalents for fields common to V1 and V2. + TEST_EQ(v1_root->a(), v2_root->a()); + + TEST_EQ(v1_root->b(), v2_root->b()); + TEST_EQ(v1_root->b()->Get(2), 3); + TEST_EQ(v2_root->b()->Get(2), 3); + + // Test that V2 can read the big vector, which V1 doesn't even have + // accessors for (i.e. v1_root->big_vector() doesn't exist). + TEST_ASSERT(v2_root->big_vector() != nullptr); + TEST_EQ(v2_root->big_vector()->size(), big_data.size()); + TEST_EQ(v2_root->big_vector()->Get(2), 8); + } + + // Built V2 read V1, bigger than max 32-bit buffer sized. + // This checks that even a large buffer can still be read by V1. + { + // Use the 64-bit builder since V2 has 64-bit offsets. + FlatBufferBuilder64 builder; + + std::vector<uint8_t> giant_data; + giant_data.resize(1LL << 31); + giant_data[2] = 42; + + builder.Finish( + v2::CreateRootTableDirect(builder, 1234, &data, &giant_data)); + + // Ensure the buffer is bigger than the 32-bit size limit for V1. + TEST_ASSERT(builder.GetSize() > FLATBUFFERS_MAX_BUFFER_SIZE); + + // Use each version to get a view at the root table. + auto v1_root = v1::GetRootTable(builder.GetBufferPointer()); + auto v2_root = v2::GetRootTable(builder.GetBufferPointer()); + + // Test field equivalents for fields common to V1 and V2. + TEST_EQ(v1_root->a(), v2_root->a()); + + TEST_EQ(v1_root->b(), v2_root->b()); + TEST_EQ(v1_root->b()->Get(2), 3); + TEST_EQ(v2_root->b()->Get(2), 3); + + // Test that V2 can read the big vector, which V1 doesn't even have + // accessors for (i.e. v1_root->big_vector() doesn't exist). + TEST_ASSERT(v2_root->big_vector() != nullptr); + TEST_EQ(v2_root->big_vector()->size(), giant_data.size()); + TEST_EQ(v2_root->big_vector()->Get(2), 42); + } +} + +void Offset64VectorOfStructs() { + FlatBufferBuilder64 builder; + + std::vector<LeafStruct> far_leaves; + far_leaves.emplace_back(LeafStruct{ 123, 4.567 }); + far_leaves.emplace_back(LeafStruct{ 987, 6.543 }); + + std::vector<LeafStruct> big_leaves; + big_leaves.emplace_back(LeafStruct{ 72, 72.8 }); + big_leaves.emplace_back(LeafStruct{ 82, 82.8 }); + big_leaves.emplace_back(LeafStruct{ 92, 92.8 }); + + // Add the two vectors of leaf structs. + const Offset<RootTable> root_table_offset = + CreateRootTableDirect(builder, nullptr, 0, nullptr, nullptr, nullptr, + nullptr, &far_leaves, &big_leaves); + + // Finish the buffer. + builder.Finish(root_table_offset); + + Verifier::Options options; + // Allow the verifier to verify 64-bit buffers. + options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE; + options.assert = true; + + Verifier verifier(builder.GetBufferPointer(), builder.GetSize(), options); + + TEST_EQ(VerifyRootTableBuffer(verifier), true); + + // Verify the data. + const RootTable *root_table = GetRootTable(builder.GetBufferPointer()); + TEST_EQ(root_table->far_struct_vector()->size(), far_leaves.size()); + TEST_EQ(root_table->far_struct_vector()->Get(0)->a(), 123); + TEST_EQ(root_table->far_struct_vector()->Get(0)->b(), 4.567); + TEST_EQ(root_table->far_struct_vector()->Get(1)->a(), 987); + TEST_EQ(root_table->far_struct_vector()->Get(1)->b(), 6.543); + + TEST_EQ(root_table->big_struct_vector()->size(), big_leaves.size()); + TEST_EQ(root_table->big_struct_vector()->Get(0)->a(), 72); + TEST_EQ(root_table->big_struct_vector()->Get(0)->b(), 72.8); + TEST_EQ(root_table->big_struct_vector()->Get(1)->a(), 82); + TEST_EQ(root_table->big_struct_vector()->Get(1)->b(), 82.8); + TEST_EQ(root_table->big_struct_vector()->Get(2)->a(), 92); + TEST_EQ(root_table->big_struct_vector()->Get(2)->b(), 92.8); +} + +void Offset64SizePrefix() { + FlatBufferBuilder64 builder; + + // First serialize a nested buffer. + const Offset<String> near_string_offset = + builder.CreateString("some near string"); + + // Finish by building the root table by passing in all the offsets. + const Offset<RootTable> root_table_offset = + CreateRootTable(builder, 0, 0, 0, 0, near_string_offset, 0); + + // Finish the buffer. + FinishSizePrefixedRootTableBuffer(builder, root_table_offset); + + TEST_EQ(GetPrefixedSize<uoffset64_t>(builder.GetBufferPointer()), + builder.GetSize() - sizeof(uoffset64_t)); + + Verifier::Options options; + // Allow the verifier to verify 64-bit buffers. + options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE; + options.assert = true; + + Verifier verifier(builder.GetBufferPointer(), builder.GetSize(), options); + + TEST_EQ(VerifySizePrefixedRootTableBuffer(verifier), true); + + const RootTable *root_table = + GetSizePrefixedRootTable(builder.GetBufferPointer()); + + // Verify the fields. + TEST_EQ_STR(root_table->near_string()->c_str(), "some near string"); +} + +void Offset64ManyVectors() { + FlatBufferBuilder64 builder; + + // Setup some data to serialize. + std::vector<int8_t> data; + data.resize(20); + data.front() = 42; + data.back() = 18; + + const size_t kNumVectors = 20; + + // First serialize all the 64-bit address vectors. We need to store all the + // offsets to later add to a wrapper table. We cannot serialize one vector and + // then add it to a table immediately, as it would violate the strict ordering + // of putting all 64-bit things at the tail of the buffer. + std::array<Offset64<Vector<int8_t>>, kNumVectors> offsets_64bit; + for (size_t i = 0; i < kNumVectors; ++i) { + offsets_64bit[i] = builder.CreateVector64<Vector>(data); + } + + // Create some unrelated, 64-bit offset value for later testing. + const Offset64<String> far_string_offset = + builder.CreateString<Offset64>("some far string"); + + // Now place all the offsets into their own wrapper tables. Again, we have to + // store the offsets before we can add them to the root table vector. + std::array<Offset<WrapperTable>, kNumVectors> offsets_wrapper; + for (size_t i = 0; i < kNumVectors; ++i) { + offsets_wrapper[i] = CreateWrapperTable(builder, offsets_64bit[i]); + } + + // Now create the 32-bit vector that is stored in the root table. + // TODO(derekbailey): the array type wasn't auto deduced, see if that could be + // fixed. + const Offset<Vector<Offset<WrapperTable>>> many_vectors_offset = + builder.CreateVector<Offset<WrapperTable>>(offsets_wrapper); + + // Finish by building using the root table builder, to exercise a different + // code path than the other tests. + RootTableBuilder root_table_builder(builder); + root_table_builder.add_many_vectors(many_vectors_offset); + root_table_builder.add_far_string(far_string_offset); + const Offset<RootTable> root_table_offset = root_table_builder.Finish(); + + // Finish the buffer. + FinishRootTableBuffer(builder, root_table_offset); + + Verifier::Options options; + // Allow the verifier to verify 64-bit buffers. + options.max_size = FLATBUFFERS_MAX_64_BUFFER_SIZE; + options.assert = true; + + Verifier verifier(builder.GetBufferPointer(), builder.GetSize(), options); + + TEST_EQ(VerifyRootTableBuffer(verifier), true); + + const RootTable *root_table = GetRootTable(builder.GetBufferPointer()); + + // Verify the fields. + TEST_EQ_STR(root_table->far_string()->c_str(), "some far string"); + TEST_EQ(root_table->many_vectors()->size(), kNumVectors); + + // Spot check one of the vectors. + TEST_EQ(root_table->many_vectors()->Get(12)->vector()->size(), 20); + TEST_EQ(root_table->many_vectors()->Get(12)->vector()->Get(0), 42); + TEST_EQ(root_table->many_vectors()->Get(12)->vector()->Get(19), 18); +} + +} // namespace tests +} // namespace flatbuffers diff --git a/tests/64bit/offset64_test.h b/tests/64bit/offset64_test.h new file mode 100644 index 00000000..8dacee1f --- /dev/null +++ b/tests/64bit/offset64_test.h @@ -0,0 +1,19 @@ +#ifndef TESTS_64BIT_OFFSET64_TEST_H +#define TESTS_64BIT_OFFSET64_TEST_H + +namespace flatbuffers { +namespace tests { + +void Offset64Test(); +void Offset64SerializedFirst(); +void Offset64NestedFlatBuffer(); +void Offset64CreateDirect(); +void Offset64Evolution(); +void Offset64VectorOfStructs(); +void Offset64SizePrefix(); +void Offset64ManyVectors(); + +} // namespace tests +} // namespace flatbuffers + +#endif // TESTS_64BIT_OFFSET64_TEST_H diff --git a/tests/64bit/test_64bit.afb b/tests/64bit/test_64bit.afb new file mode 100644 index 00000000..f6cef00e --- /dev/null +++ b/tests/64bit/test_64bit.afb @@ -0,0 +1,74 @@ +// Annotated Flatbuffer Binary +// +// Schema file: tests/64bit/test_64bit.fbs +// Binary file: tests/64bit/test_64bit.bin + +header: + +0x00 | 1C 00 00 00 | UOffset32 | 0x0000001C (28) Loc: 0x1C | offset to root table `RootTable` + +padding: + +0x04 | 00 00 00 00 | uint8_t[4] | .... | padding + +vtable (RootTable): + +0x08 | 14 00 | uint16_t | 0x0014 (20) | size of this vtable + +0x0A | 34 00 | uint16_t | 0x0034 (52) | size of referring table + +0x0C | 04 00 | VOffset16 | 0x0004 (4) | offset to field `far_vector` (id: 0) + +0x0E | 10 00 | VOffset16 | 0x0010 (16) | offset to field `a` (id: 1) + +0x10 | 14 00 | VOffset16 | 0x0014 (20) | offset to field `far_string` (id: 2) + +0x12 | 24 00 | VOffset16 | 0x0024 (36) | offset to field `big_vector` (id: 3) + +0x14 | 20 00 | VOffset16 | 0x0020 (32) | offset to field `near_string` (id: 4) + +0x16 | 00 00 | VOffset16 | 0x0000 (0) | offset to field `nested_root` (id: 5) <null> (Vector64) + +0x18 | 00 00 | VOffset16 | 0x0000 (0) | offset to field `far_struct_vector` (id: 6) <null> (Vector) + +0x1A | 2C 00 | VOffset16 | 0x002C (44) | offset to field `big_struct_vector` (id: 7) + +root_table (RootTable): + +0x1C | 14 00 00 00 | SOffset32 | 0x00000014 (20) Loc: 0x08 | offset to vtable + +0x20 | D0 00 00 00 00 00 00 00 | UOffset64 | 0x00000000000000D0 (208) Loc: 0xF0 | offset to field `far_vector` (vector) + +0x28 | 00 00 00 00 | uint8_t[4] | .... | padding + +0x2C | D2 04 00 00 | uint32_t | 0x000004D2 (1234) | table field `a` (Int) + +0x30 | 8C 00 00 00 00 00 00 00 | UOffset64 | 0x000000000000008C (140) Loc: 0xBC | offset to field `far_string` (string) + +0x38 | 00 00 00 00 | uint8_t[4] | .... | padding + +0x3C | 40 00 00 00 | UOffset32 | 0x00000040 (64) Loc: 0x7C | offset to field `near_string` (string) + +0x40 | 70 00 00 00 00 00 00 00 | UOffset64 | 0x0000000000000070 (112) Loc: 0xB0 | offset to field `big_vector` (vector64) + +0x48 | 08 00 00 00 00 00 00 00 | UOffset64 | 0x0000000000000008 (8) Loc: 0x50 | offset to field `big_struct_vector` (vector64) + +vector64 (RootTable.big_struct_vector): + +0x50 | 02 00 00 00 00 00 00 00 | uint64_t | 0x0000000000000002 (2) | length of vector (# items) + +0x58 | 0C 00 00 00 | uint32_t | 0x0000000C (12) | struct field `[0].a` of 'LeafStruct' (Int) + <4 regions omitted> + +0x70 | 33 33 33 33 33 33 22 40 | double | 0x4022333333333333 (9.1) | struct field `[1].b` of 'LeafStruct' (Double) + +padding: + +0x78 | 00 00 00 00 | uint8_t[4] | .... | padding + +string (RootTable.near_string): + +0x7C | 2F 00 00 00 | uint32_t | 0x0000002F (47) | length of string + +0x80 | 74 68 69 73 20 69 73 20 | char[47] | this is | string literal + +0x88 | 61 20 6E 65 61 72 20 73 | | a near s + +0x90 | 74 72 69 6E 67 20 77 68 | | tring wh + +0x98 | 69 63 68 20 68 61 73 20 | | ich has + +0xA0 | 61 20 33 32 2D 62 69 74 | | a 32-bit + +0xA8 | 20 6F 66 66 73 65 74 | | offset + +0xAF | 00 | char | 0x00 (0) | string terminator + +vector64 (RootTable.big_vector): + +0xB0 | 04 00 00 00 00 00 00 00 | uint64_t | 0x0000000000000004 (4) | length of vector (# items) + +0xB8 | 05 | uint8_t | 0x05 (5) | value[0] + <2 regions omitted> + +0xBB | 08 | uint8_t | 0x08 (8) | value[3] + +string (RootTable.far_string): + +0xBC | 2E 00 00 00 | uint32_t | 0x0000002E (46) | length of string + +0xC0 | 74 68 69 73 20 69 73 20 | char[46] | this is | string literal + +0xC8 | 61 20 66 61 72 20 73 74 | | a far st + +0xD0 | 72 69 6E 67 20 77 68 69 | | ring whi + +0xD8 | 63 68 20 68 61 73 20 61 | | ch has a + +0xE0 | 20 36 34 2D 62 69 74 20 | | 64-bit + +0xE8 | 6F 66 66 73 65 74 | | offset + +0xEE | 00 | char | 0x00 (0) | string terminator + +vector (RootTable.far_vector): + +0xF0 | 03 00 00 00 | uint32_t | 0x00000003 (3) | length of vector (# items) + +0xF4 | 01 | uint8_t | 0x01 (1) | value[0] + +0xF5 | 02 | uint8_t | 0x02 (2) | value[1] + +0xF6 | 03 | uint8_t | 0x03 (3) | value[2] diff --git a/tests/64bit/test_64bit.bfbs b/tests/64bit/test_64bit.bfbs Binary files differnew file mode 100644 index 00000000..29360deb --- /dev/null +++ b/tests/64bit/test_64bit.bfbs diff --git a/tests/64bit/test_64bit.bin b/tests/64bit/test_64bit.bin Binary files differnew file mode 100644 index 00000000..a8d2d2e1 --- /dev/null +++ b/tests/64bit/test_64bit.bin diff --git a/tests/64bit/test_64bit.fbs b/tests/64bit/test_64bit.fbs new file mode 100644 index 00000000..6bc787e9 --- /dev/null +++ b/tests/64bit/test_64bit.fbs @@ -0,0 +1,49 @@ +struct LeafStruct { + a:int; + b:double; +} + +table WrapperTable { + // A normal 32-bit sized vector that could be very far away (64-bit address). + vector:[int8] (offset64); +} + +table RootTable { + // A normal 32-bit sized vector, that could be very far away (64-bit address). + far_vector:[ubyte] (offset64); + + // An inplace value just to check that vtable offsets are correct. + a:int; + + // A normal 32-bit sized string, that could be very far away (64-bit address). + far_string:string (offset64); + + // A big 64-bit sized vector, that could be very far away (64-bit address). + big_vector:[ubyte] (vector64); + + // A normal 32-bit sized string that is no far away (32-bit address). + near_string:string; + + // A big 64-bit sized vector that is a nested flatbuffers (64-bit address). + nested_root:[ubyte] (vector64, nested_flatbuffer: "RootTable"); + + // A normal 32-bit size vector of structs, that could be very far away + // (64-bit address) + far_struct_vector:[LeafStruct] (offset64); + + // A big 64-bit size vector of structs that could be very far away + // (64-bit address) + big_struct_vector:[LeafStruct] (vector64); + + // A normal 32-bit size vector of tables. Currently 64-bit vectors don't + // support tables as it would require serializing a table (32-bit) before the + // vector (64-bit), which is not allowed. + // + // This demonstrates how you could have many vectors in the buffer, by + // effectively having a vector of 64-bit vectors. The IDL doesn't support + // nested vecotrs (e.g.: [[type]] ), so going through a wrapper table allows + // this. + many_vectors:[WrapperTable]; +} + +root_type RootTable; diff --git a/tests/64bit/test_64bit.json b/tests/64bit/test_64bit.json new file mode 100644 index 00000000..4b24f4e7 --- /dev/null +++ b/tests/64bit/test_64bit.json @@ -0,0 +1,17 @@ +{ + "far_vector": [1, 2, 3], + "a": 1234, + "far_string": "this is a far string which has a 64-bit offset", + "big_vector": [5, 6, 7, 8], + "near_string": "this is a near string which has a 32-bit offset", + "big_struct_vector": [ + { + "a": 12, + "b": 3.456 + }, + { + "a": 78, + "b": 9.10 + } + ] +} diff --git a/tests/64bit/test_64bit_bfbs_generated.h b/tests/64bit/test_64bit_bfbs_generated.h new file mode 100644 index 00000000..ca017e78 --- /dev/null +++ b/tests/64bit/test_64bit_bfbs_generated.h @@ -0,0 +1,93 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_TEST64BIT_BFBS_H_ +#define FLATBUFFERS_GENERATED_TEST64BIT_BFBS_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && + FLATBUFFERS_VERSION_MINOR == 5 && + FLATBUFFERS_VERSION_REVISION == 8, + "Non-compatible flatbuffers version included"); + +struct RootTableBinarySchema { + static const uint8_t *data() { + // Buffer containing the binary schema. + static const uint8_t bfbsData[1180] = { + 0x1C,0x00,0x00,0x00,0x42,0x46,0x42,0x53,0x14,0x00,0x20,0x00,0x04,0x00,0x08,0x00,0x0C,0x00,0x10,0x00, + 0x14,0x00,0x18,0x00,0x00,0x00,0x1C,0x00,0x14,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x2C,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x54,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x2C,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x60,0x03,0x00,0x00,0x28,0x00,0x00,0x00,0xBC,0x02,0x00,0x00, + 0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x00,0x00, + 0x5C,0x03,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xFD,0xFF,0xFF,0x38,0x00,0x00,0x00, + 0x0C,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x40,0x03,0x00,0x00,0x09,0x00,0x00,0x00,0x1C,0x02,0x00,0x00, + 0x68,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xE0,0x01,0x00,0x00,0xAC,0x00,0x00,0x00,0x2C,0x02,0x00,0x00, + 0x1C,0x00,0x00,0x00,0x3C,0x01,0x00,0x00,0xE8,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x52,0x6F,0x6F,0x74, + 0x54,0x61,0x62,0x6C,0x65,0x00,0x00,0x00,0xF8,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x01,0x08,0x00,0x14,0x00, + 0x18,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x78,0xFF,0xFF,0xFF,0x00,0x00,0x0E,0x0F,0x02,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x6D,0x61,0x6E,0x79,0x5F,0x76,0x65,0x63,0x74,0x6F,0x72,0x73, + 0x00,0x00,0x00,0x00,0xA0,0xFE,0xFF,0xFF,0x00,0x00,0x01,0x01,0x07,0x00,0x12,0x00,0x2C,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x10,0x00,0x14,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x00,0x00,0x0C,0x00,0x10,0x00, + 0x10,0x00,0x00,0x00,0x00,0x00,0x12,0x0F,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x11,0x00,0x00,0x00,0x62,0x69,0x67,0x5F,0x73,0x74,0x72,0x75,0x63,0x74,0x5F,0x76,0x65,0x63,0x74,0x6F, + 0x72,0x00,0x00,0x00,0xF0,0xFE,0xFF,0xFF,0x00,0x00,0x01,0x01,0x06,0x00,0x10,0x00,0x28,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x06,0x00,0x07,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x0C,0x00, + 0x10,0x00,0x00,0x00,0x00,0x00,0x0E,0x0F,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x00,0x00,0x00, + 0x66,0x61,0x72,0x5F,0x73,0x74,0x72,0x75,0x63,0x74,0x5F,0x76,0x65,0x63,0x74,0x6F,0x72,0x00,0x00,0x00, + 0x3C,0xFF,0xFF,0xFF,0x00,0x00,0x01,0x01,0x05,0x00,0x0E,0x00,0x18,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x80,0xFF,0xFF,0xFF,0x00,0x00,0x12,0x04,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0B,0x00,0x00,0x00, + 0x6E,0x65,0x73,0x74,0x65,0x64,0x5F,0x72,0x6F,0x6F,0x74,0x00,0x1C,0x00,0x14,0x00,0x0C,0x00,0x10,0x00, + 0x08,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00, + 0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x00,0x0C,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x90,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x0D,0x01,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x6E,0x65,0x61,0x72, + 0x5F,0x73,0x74,0x72,0x69,0x6E,0x67,0x00,0xBC,0xFF,0xFF,0xFF,0x00,0x00,0x01,0x01,0x03,0x00,0x0A,0x00, + 0x28,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x06,0x00,0x07,0x00,0x00,0x00,0x00,0x00, + 0x08,0x00,0x0C,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x12,0x04,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x0A,0x00,0x00,0x00,0x62,0x69,0x67,0x5F,0x76,0x65,0x63,0x74,0x6F,0x72,0x00,0x00,0x20,0x00,0x14,0x00, + 0x0C,0x00,0x10,0x00,0x08,0x00,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0x00,0x00,0x07,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x00,0x08,0x00, + 0x14,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x24,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x0D,0x01,0x00,0x00,0x00, + 0x0A,0x00,0x00,0x00,0x66,0x61,0x72,0x5F,0x73,0x74,0x72,0x69,0x6E,0x67,0x00,0x00,0xB0,0xFE,0xFF,0xFF, + 0x01,0x00,0x06,0x00,0x14,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x50,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x07, + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x90,0xFF,0xFF,0xFF,0x01,0x01,0x04,0x00, + 0x14,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x70,0xFF,0xFF,0xFF,0x00,0x00,0x0E,0x04,0x01,0x00,0x00,0x00, + 0x0A,0x00,0x00,0x00,0x66,0x61,0x72,0x5F,0x76,0x65,0x63,0x74,0x6F,0x72,0x00,0x00,0x14,0x00,0x14,0x00, + 0x04,0x00,0x08,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x14,0x00,0x00,0x00, + 0x18,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xA8,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x38,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x57,0x72,0x61,0x70,0x70,0x65,0x72,0x54,0x61,0x62,0x6C,0x65, + 0x00,0x00,0x00,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x20,0x00,0x00,0x00, + 0x01,0x01,0x04,0x00,0x24,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x10,0x00,0x0C,0x00,0x06,0x00,0x07,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0E,0x03,0x01,0x00,0x00,0x00, + 0x06,0x00,0x00,0x00,0x76,0x65,0x63,0x74,0x6F,0x72,0x00,0x00,0x14,0x00,0x1C,0x00,0x08,0x00,0x0C,0x00, + 0x07,0x00,0x10,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x38,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x10,0x00,0x00,0x00,0x2F,0x2F,0x74,0x65,0x73,0x74,0x5F,0x36,0x34,0x62,0x69,0x74,0x2E,0x66,0x62,0x73, + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x0A,0x00,0x00,0x00, + 0x4C,0x65,0x61,0x66,0x53,0x74,0x72,0x75,0x63,0x74,0x00,0x00,0x0C,0x00,0x10,0x00,0x08,0x00,0x0C,0x00, + 0x04,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x28,0x00,0x00,0x00,0x14,0x00,0x00,0x00, + 0x10,0x00,0x10,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0C,0x00,0x10,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0C,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x62,0x00,0x1E,0x00, + 0x10,0x00,0x08,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x24,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x10,0x00,0x0C,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00, + 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x61,0x00,0x00,0x00 + }; + return bfbsData; + } + static size_t size() { + return 1180; + } + const uint8_t *begin() { + return data(); + } + const uint8_t *end() { + return data() + size(); + } +}; + +#endif // FLATBUFFERS_GENERATED_TEST64BIT_BFBS_H_ diff --git a/tests/64bit/test_64bit_generated.h b/tests/64bit/test_64bit_generated.h new file mode 100644 index 00000000..3bd40698 --- /dev/null +++ b/tests/64bit/test_64bit_generated.h @@ -0,0 +1,625 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_TEST64BIT_H_ +#define FLATBUFFERS_GENERATED_TEST64BIT_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && + FLATBUFFERS_VERSION_MINOR == 5 && + FLATBUFFERS_VERSION_REVISION == 8, + "Non-compatible flatbuffers version included"); + +// For access to the binary schema that produced this file. +#include "test_64bit_bfbs_generated.h" + +struct LeafStruct; + +struct WrapperTable; +struct WrapperTableBuilder; +struct WrapperTableT; + +struct RootTable; +struct RootTableBuilder; +struct RootTableT; + +bool operator==(const LeafStruct &lhs, const LeafStruct &rhs); +bool operator!=(const LeafStruct &lhs, const LeafStruct &rhs); +bool operator==(const WrapperTableT &lhs, const WrapperTableT &rhs); +bool operator!=(const WrapperTableT &lhs, const WrapperTableT &rhs); +bool operator==(const RootTableT &lhs, const RootTableT &rhs); +bool operator!=(const RootTableT &lhs, const RootTableT &rhs); + +inline const ::flatbuffers::TypeTable *LeafStructTypeTable(); + +inline const ::flatbuffers::TypeTable *WrapperTableTypeTable(); + +inline const ::flatbuffers::TypeTable *RootTableTypeTable(); + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) LeafStruct FLATBUFFERS_FINAL_CLASS { + private: + int32_t a_; + int32_t padding0__; + double b_; + + public: + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return LeafStructTypeTable(); + } + LeafStruct() + : a_(0), + padding0__(0), + b_(0) { + (void)padding0__; + } + LeafStruct(int32_t _a, double _b) + : a_(::flatbuffers::EndianScalar(_a)), + padding0__(0), + b_(::flatbuffers::EndianScalar(_b)) { + (void)padding0__; + } + int32_t a() const { + return ::flatbuffers::EndianScalar(a_); + } + void mutate_a(int32_t _a) { + ::flatbuffers::WriteScalar(&a_, _a); + } + double b() const { + return ::flatbuffers::EndianScalar(b_); + } + void mutate_b(double _b) { + ::flatbuffers::WriteScalar(&b_, _b); + } +}; +FLATBUFFERS_STRUCT_END(LeafStruct, 16); + +inline bool operator==(const LeafStruct &lhs, const LeafStruct &rhs) { + return + (lhs.a() == rhs.a()) && + (lhs.b() == rhs.b()); +} + +inline bool operator!=(const LeafStruct &lhs, const LeafStruct &rhs) { + return !(lhs == rhs); +} + + +struct WrapperTableT : public ::flatbuffers::NativeTable { + typedef WrapperTable TableType; + std::vector<int8_t> vector{}; +}; + +struct WrapperTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef WrapperTableT NativeTableType; + typedef WrapperTableBuilder Builder; + typedef RootTableBinarySchema BinarySchema; + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return WrapperTableTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_VECTOR = 4 + }; + const ::flatbuffers::Vector<int8_t> *vector() const { + return GetPointer64<const ::flatbuffers::Vector<int8_t> *>(VT_VECTOR); + } + ::flatbuffers::Vector<int8_t> *mutable_vector() { + return GetPointer64<::flatbuffers::Vector<int8_t> *>(VT_VECTOR); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset64(verifier, VT_VECTOR) && + verifier.VerifyVector(vector()) && + verifier.EndTable(); + } + WrapperTableT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(WrapperTableT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset<WrapperTable> Pack(::flatbuffers::FlatBufferBuilder64 &_fbb, const WrapperTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct WrapperTableBuilder { + typedef WrapperTable Table; + ::flatbuffers::FlatBufferBuilder64 &fbb_; + ::flatbuffers::uoffset_t start_; + void add_vector(::flatbuffers::Offset64<::flatbuffers::Vector<int8_t>> vector) { + fbb_.AddOffset(WrapperTable::VT_VECTOR, vector); + } + explicit WrapperTableBuilder(::flatbuffers::FlatBufferBuilder64 &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset<WrapperTable> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset<WrapperTable>(end); + return o; + } +}; + +inline ::flatbuffers::Offset<WrapperTable> CreateWrapperTable( + ::flatbuffers::FlatBufferBuilder64 &_fbb, + ::flatbuffers::Offset64<::flatbuffers::Vector<int8_t>> vector = 0) { + WrapperTableBuilder builder_(_fbb); + builder_.add_vector(vector); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset<WrapperTable> CreateWrapperTableDirect( + ::flatbuffers::FlatBufferBuilder64 &_fbb, + const std::vector<int8_t> *vector = nullptr) { + auto vector__ = vector ? _fbb.CreateVector64<::flatbuffers::Vector>(*vector) : 0; + return CreateWrapperTable( + _fbb, + vector__); +} + +::flatbuffers::Offset<WrapperTable> CreateWrapperTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const WrapperTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct RootTableT : public ::flatbuffers::NativeTable { + typedef RootTable TableType; + std::vector<uint8_t> far_vector{}; + int32_t a = 0; + std::string far_string{}; + std::vector<uint8_t> big_vector{}; + std::string near_string{}; + std::vector<uint8_t> nested_root{}; + std::vector<LeafStruct> far_struct_vector{}; + std::vector<LeafStruct> big_struct_vector{}; + std::vector<std::unique_ptr<WrapperTableT>> many_vectors{}; + RootTableT() = default; + RootTableT(const RootTableT &o); + RootTableT(RootTableT&&) FLATBUFFERS_NOEXCEPT = default; + RootTableT &operator=(RootTableT o) FLATBUFFERS_NOEXCEPT; +}; + +struct RootTable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef RootTableT NativeTableType; + typedef RootTableBuilder Builder; + typedef RootTableBinarySchema BinarySchema; + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return RootTableTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_FAR_VECTOR = 4, + VT_A = 6, + VT_FAR_STRING = 8, + VT_BIG_VECTOR = 10, + VT_NEAR_STRING = 12, + VT_NESTED_ROOT = 14, + VT_FAR_STRUCT_VECTOR = 16, + VT_BIG_STRUCT_VECTOR = 18, + VT_MANY_VECTORS = 20 + }; + const ::flatbuffers::Vector<uint8_t> *far_vector() const { + return GetPointer64<const ::flatbuffers::Vector<uint8_t> *>(VT_FAR_VECTOR); + } + ::flatbuffers::Vector<uint8_t> *mutable_far_vector() { + return GetPointer64<::flatbuffers::Vector<uint8_t> *>(VT_FAR_VECTOR); + } + int32_t a() const { + return GetField<int32_t>(VT_A, 0); + } + bool mutate_a(int32_t _a = 0) { + return SetField<int32_t>(VT_A, _a, 0); + } + const ::flatbuffers::String *far_string() const { + return GetPointer64<const ::flatbuffers::String *>(VT_FAR_STRING); + } + ::flatbuffers::String *mutable_far_string() { + return GetPointer64<::flatbuffers::String *>(VT_FAR_STRING); + } + const ::flatbuffers::Vector64<uint8_t> *big_vector() const { + return GetPointer64<const ::flatbuffers::Vector64<uint8_t> *>(VT_BIG_VECTOR); + } + ::flatbuffers::Vector64<uint8_t> *mutable_big_vector() { + return GetPointer64<::flatbuffers::Vector64<uint8_t> *>(VT_BIG_VECTOR); + } + const ::flatbuffers::String *near_string() const { + return GetPointer<const ::flatbuffers::String *>(VT_NEAR_STRING); + } + ::flatbuffers::String *mutable_near_string() { + return GetPointer<::flatbuffers::String *>(VT_NEAR_STRING); + } + const ::flatbuffers::Vector64<uint8_t> *nested_root() const { + return GetPointer64<const ::flatbuffers::Vector64<uint8_t> *>(VT_NESTED_ROOT); + } + ::flatbuffers::Vector64<uint8_t> *mutable_nested_root() { + return GetPointer64<::flatbuffers::Vector64<uint8_t> *>(VT_NESTED_ROOT); + } + const RootTable *nested_root_nested_root() const { + const auto _f = nested_root(); + return _f ? ::flatbuffers::GetRoot<RootTable>(_f->Data()) + : nullptr; + } + const ::flatbuffers::Vector<const LeafStruct *> *far_struct_vector() const { + return GetPointer64<const ::flatbuffers::Vector<const LeafStruct *> *>(VT_FAR_STRUCT_VECTOR); + } + ::flatbuffers::Vector<const LeafStruct *> *mutable_far_struct_vector() { + return GetPointer64<::flatbuffers::Vector<const LeafStruct *> *>(VT_FAR_STRUCT_VECTOR); + } + const ::flatbuffers::Vector64<const LeafStruct *> *big_struct_vector() const { + return GetPointer64<const ::flatbuffers::Vector64<const LeafStruct *> *>(VT_BIG_STRUCT_VECTOR); + } + ::flatbuffers::Vector64<const LeafStruct *> *mutable_big_struct_vector() { + return GetPointer64<::flatbuffers::Vector64<const LeafStruct *> *>(VT_BIG_STRUCT_VECTOR); + } + const ::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>> *many_vectors() const { + return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>> *>(VT_MANY_VECTORS); + } + ::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>> *mutable_many_vectors() { + return GetPointer<::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>> *>(VT_MANY_VECTORS); + } + bool Verify(::flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset64(verifier, VT_FAR_VECTOR) && + verifier.VerifyVector(far_vector()) && + VerifyField<int32_t>(verifier, VT_A, 4) && + VerifyOffset64(verifier, VT_FAR_STRING) && + verifier.VerifyString(far_string()) && + VerifyOffset64(verifier, VT_BIG_VECTOR) && + verifier.VerifyVector(big_vector()) && + VerifyOffset(verifier, VT_NEAR_STRING) && + verifier.VerifyString(near_string()) && + VerifyOffset64(verifier, VT_NESTED_ROOT) && + verifier.VerifyVector(nested_root()) && + verifier.VerifyNestedFlatBuffer<RootTable>(nested_root(), nullptr) && + VerifyOffset64(verifier, VT_FAR_STRUCT_VECTOR) && + verifier.VerifyVector(far_struct_vector()) && + VerifyOffset64(verifier, VT_BIG_STRUCT_VECTOR) && + verifier.VerifyVector(big_struct_vector()) && + VerifyOffset(verifier, VT_MANY_VECTORS) && + verifier.VerifyVector(many_vectors()) && + verifier.VerifyVectorOfTables(many_vectors()) && + verifier.EndTable(); + } + RootTableT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(RootTableT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset<RootTable> Pack(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct RootTableBuilder { + typedef RootTable Table; + ::flatbuffers::FlatBufferBuilder64 &fbb_; + ::flatbuffers::uoffset_t start_; + void add_far_vector(::flatbuffers::Offset64<::flatbuffers::Vector<uint8_t>> far_vector) { + fbb_.AddOffset(RootTable::VT_FAR_VECTOR, far_vector); + } + void add_a(int32_t a) { + fbb_.AddElement<int32_t>(RootTable::VT_A, a, 0); + } + void add_far_string(::flatbuffers::Offset64<::flatbuffers::String> far_string) { + fbb_.AddOffset(RootTable::VT_FAR_STRING, far_string); + } + void add_big_vector(::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> big_vector) { + fbb_.AddOffset(RootTable::VT_BIG_VECTOR, big_vector); + } + void add_near_string(::flatbuffers::Offset<::flatbuffers::String> near_string) { + fbb_.AddOffset(RootTable::VT_NEAR_STRING, near_string); + } + void add_nested_root(::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> nested_root) { + fbb_.AddOffset(RootTable::VT_NESTED_ROOT, nested_root); + } + void add_far_struct_vector(::flatbuffers::Offset64<::flatbuffers::Vector<const LeafStruct *>> far_struct_vector) { + fbb_.AddOffset(RootTable::VT_FAR_STRUCT_VECTOR, far_struct_vector); + } + void add_big_struct_vector(::flatbuffers::Offset64<::flatbuffers::Vector64<const LeafStruct *>> big_struct_vector) { + fbb_.AddOffset(RootTable::VT_BIG_STRUCT_VECTOR, big_struct_vector); + } + void add_many_vectors(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>>> many_vectors) { + fbb_.AddOffset(RootTable::VT_MANY_VECTORS, many_vectors); + } + explicit RootTableBuilder(::flatbuffers::FlatBufferBuilder64 &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset<RootTable> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset<RootTable>(end); + return o; + } +}; + +inline ::flatbuffers::Offset<RootTable> CreateRootTable( + ::flatbuffers::FlatBufferBuilder64 &_fbb, + ::flatbuffers::Offset64<::flatbuffers::Vector<uint8_t>> far_vector = 0, + int32_t a = 0, + ::flatbuffers::Offset64<::flatbuffers::String> far_string = 0, + ::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> big_vector = 0, + ::flatbuffers::Offset<::flatbuffers::String> near_string = 0, + ::flatbuffers::Offset64<::flatbuffers::Vector64<uint8_t>> nested_root = 0, + ::flatbuffers::Offset64<::flatbuffers::Vector<const LeafStruct *>> far_struct_vector = 0, + ::flatbuffers::Offset64<::flatbuffers::Vector64<const LeafStruct *>> big_struct_vector = 0, + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<WrapperTable>>> many_vectors = 0) { + RootTableBuilder builder_(_fbb); + builder_.add_big_struct_vector(big_struct_vector); + builder_.add_nested_root(nested_root); + builder_.add_big_vector(big_vector); + builder_.add_many_vectors(many_vectors); + builder_.add_far_struct_vector(far_struct_vector); + builder_.add_near_string(near_string); + builder_.add_far_string(far_string); + builder_.add_a(a); + builder_.add_far_vector(far_vector); + return builder_.Finish(); +} + +inline ::flatbuffers::Offset<RootTable> CreateRootTableDirect( + ::flatbuffers::FlatBufferBuilder64 &_fbb, + const std::vector<uint8_t> *far_vector = nullptr, + int32_t a = 0, + const char *far_string = nullptr, + const std::vector<uint8_t> *big_vector = nullptr, + const char *near_string = nullptr, + const std::vector<uint8_t> *nested_root = nullptr, + const std::vector<LeafStruct> *far_struct_vector = nullptr, + const std::vector<LeafStruct> *big_struct_vector = nullptr, + const std::vector<::flatbuffers::Offset<WrapperTable>> *many_vectors = nullptr) { + auto far_vector__ = far_vector ? _fbb.CreateVector64<::flatbuffers::Vector>(*far_vector) : 0; + auto far_string__ = far_string ? _fbb.CreateString<::flatbuffers::Offset64>(far_string) : 0; + auto big_vector__ = big_vector ? _fbb.CreateVector64(*big_vector) : 0; + auto nested_root__ = nested_root ? _fbb.CreateVector64(*nested_root) : 0; + auto far_struct_vector__ = far_struct_vector ? _fbb.CreateVectorOfStructs64<::flatbuffers::Vector>(*far_struct_vector) : 0; + auto big_struct_vector__ = big_struct_vector ? _fbb.CreateVectorOfStructs64(*big_struct_vector) : 0; + auto near_string__ = near_string ? _fbb.CreateString(near_string) : 0; + auto many_vectors__ = many_vectors ? _fbb.CreateVector<::flatbuffers::Offset<WrapperTable>>(*many_vectors) : 0; + return CreateRootTable( + _fbb, + far_vector__, + a, + far_string__, + big_vector__, + near_string__, + nested_root__, + far_struct_vector__, + big_struct_vector__, + many_vectors__); +} + +::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + + +inline bool operator==(const WrapperTableT &lhs, const WrapperTableT &rhs) { + return + (lhs.vector == rhs.vector); +} + +inline bool operator!=(const WrapperTableT &lhs, const WrapperTableT &rhs) { + return !(lhs == rhs); +} + + +inline WrapperTableT *WrapperTable::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr<WrapperTableT>(new WrapperTableT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void WrapperTable::UnPackTo(WrapperTableT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = vector(); if (_e) { _o->vector.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->vector.begin()); } } +} + +inline ::flatbuffers::Offset<WrapperTable> WrapperTable::Pack(::flatbuffers::FlatBufferBuilder64 &_fbb, const WrapperTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateWrapperTable(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset<WrapperTable> CreateWrapperTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const WrapperTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder64 *__fbb; const WrapperTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _vector = _o->vector.size() ? _fbb.CreateVector64<::flatbuffers::Vector>(_o->vector) : 0; + return CreateWrapperTable( + _fbb, + _vector); +} + + +inline bool operator==(const RootTableT &lhs, const RootTableT &rhs) { + return + (lhs.far_vector == rhs.far_vector) && + (lhs.a == rhs.a) && + (lhs.far_string == rhs.far_string) && + (lhs.big_vector == rhs.big_vector) && + (lhs.near_string == rhs.near_string) && + (lhs.nested_root == rhs.nested_root) && + (lhs.far_struct_vector == rhs.far_struct_vector) && + (lhs.big_struct_vector == rhs.big_struct_vector) && + (lhs.many_vectors.size() == rhs.many_vectors.size() && std::equal(lhs.many_vectors.cbegin(), lhs.many_vectors.cend(), rhs.many_vectors.cbegin(), [](std::unique_ptr<WrapperTableT> const &a, std::unique_ptr<WrapperTableT> const &b) { return (a == b) || (a && b && *a == *b); })); +} + +inline bool operator!=(const RootTableT &lhs, const RootTableT &rhs) { + return !(lhs == rhs); +} + + +inline RootTableT::RootTableT(const RootTableT &o) + : far_vector(o.far_vector), + a(o.a), + far_string(o.far_string), + big_vector(o.big_vector), + near_string(o.near_string), + nested_root(o.nested_root), + far_struct_vector(o.far_struct_vector), + big_struct_vector(o.big_struct_vector) { + many_vectors.reserve(o.many_vectors.size()); + for (const auto &many_vectors_ : o.many_vectors) { many_vectors.emplace_back((many_vectors_) ? new WrapperTableT(*many_vectors_) : nullptr); } +} + +inline RootTableT &RootTableT::operator=(RootTableT o) FLATBUFFERS_NOEXCEPT { + std::swap(far_vector, o.far_vector); + std::swap(a, o.a); + std::swap(far_string, o.far_string); + std::swap(big_vector, o.big_vector); + std::swap(near_string, o.near_string); + std::swap(nested_root, o.nested_root); + std::swap(far_struct_vector, o.far_struct_vector); + std::swap(big_struct_vector, o.big_struct_vector); + std::swap(many_vectors, o.many_vectors); + return *this; +} + +inline RootTableT *RootTable::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr<RootTableT>(new RootTableT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void RootTable::UnPackTo(RootTableT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = far_vector(); if (_e) { _o->far_vector.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->far_vector.begin()); } } + { auto _e = a(); _o->a = _e; } + { auto _e = far_string(); if (_e) _o->far_string = _e->str(); } + { auto _e = big_vector(); if (_e) { _o->big_vector.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->big_vector.begin()); } } + { auto _e = near_string(); if (_e) _o->near_string = _e->str(); } + { auto _e = nested_root(); if (_e) { _o->nested_root.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->nested_root.begin()); } } + { auto _e = far_struct_vector(); if (_e) { _o->far_struct_vector.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->far_struct_vector[_i] = *_e->Get(_i); } } else { _o->far_struct_vector.resize(0); } } + { auto _e = big_struct_vector(); if (_e) { _o->big_struct_vector.resize(_e->size()); for (::flatbuffers::uoffset64_t _i = 0; _i < _e->size(); _i++) { _o->big_struct_vector[_i] = *_e->Get(_i); } } else { _o->big_struct_vector.resize(0); } } + { auto _e = many_vectors(); if (_e) { _o->many_vectors.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->many_vectors[_i]) { _e->Get(_i)->UnPackTo(_o->many_vectors[_i].get(), _resolver); } else { _o->many_vectors[_i] = std::unique_ptr<WrapperTableT>(_e->Get(_i)->UnPack(_resolver)); }; } } else { _o->many_vectors.resize(0); } } +} + +inline ::flatbuffers::Offset<RootTable> RootTable::Pack(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return CreateRootTable(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset<RootTable> CreateRootTable(::flatbuffers::FlatBufferBuilder64 &_fbb, const RootTableT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder64 *__fbb; const RootTableT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _far_vector = _o->far_vector.size() ? _fbb.CreateVector64<::flatbuffers::Vector>(_o->far_vector) : 0; + auto _a = _o->a; + auto _far_string = _o->far_string.empty() ? 0 : _fbb.CreateString<::flatbuffers::Offset64>(_o->far_string); + auto _big_vector = _o->big_vector.size() ? _fbb.CreateVector64(_o->big_vector) : 0; + auto _near_string = _o->near_string.empty() ? 0 : _fbb.CreateString(_o->near_string); + auto _nested_root = _o->nested_root.size() ? _fbb.CreateVector64(_o->nested_root) : 0; + auto _far_struct_vector = _o->far_struct_vector.size() ? _fbb.CreateVectorOfStructs64<::flatbuffers::Vector>(_o->far_struct_vector) : 0; + auto _big_struct_vector = _o->big_struct_vector.size() ? _fbb.CreateVectorOfStructs64(_o->big_struct_vector) : 0; + auto _many_vectors = _o->many_vectors.size() ? _fbb.CreateVector<::flatbuffers::Offset<WrapperTable>> (_o->many_vectors.size(), [](size_t i, _VectorArgs *__va) { return CreateWrapperTable(*__va->__fbb, __va->__o->many_vectors[i].get(), __va->__rehasher); }, &_va ) : 0; + return CreateRootTable( + _fbb, + _far_vector, + _a, + _far_string, + _big_vector, + _near_string, + _nested_root, + _far_struct_vector, + _big_struct_vector, + _many_vectors); +} + +inline const ::flatbuffers::TypeTable *LeafStructTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_INT, 0, -1 }, + { ::flatbuffers::ET_DOUBLE, 0, -1 } + }; + static const int64_t values[] = { 0, 8, 16 }; + static const char * const names[] = { + "a", + "b" + }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_STRUCT, 2, type_codes, nullptr, nullptr, values, names + }; + return &tt; +} + +inline const ::flatbuffers::TypeTable *WrapperTableTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_CHAR, 1, -1 } + }; + static const char * const names[] = { + "vector" + }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_TABLE, 1, type_codes, nullptr, nullptr, nullptr, names + }; + return &tt; +} + +inline const ::flatbuffers::TypeTable *RootTableTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_UCHAR, 1, -1 }, + { ::flatbuffers::ET_INT, 0, -1 }, + { ::flatbuffers::ET_STRING, 0, -1 }, + { ::flatbuffers::ET_UCHAR, 1, -1 }, + { ::flatbuffers::ET_STRING, 0, -1 }, + { ::flatbuffers::ET_UCHAR, 1, -1 }, + { ::flatbuffers::ET_SEQUENCE, 1, 0 }, + { ::flatbuffers::ET_SEQUENCE, 1, 0 }, + { ::flatbuffers::ET_SEQUENCE, 1, 1 } + }; + static const ::flatbuffers::TypeFunction type_refs[] = { + LeafStructTypeTable, + WrapperTableTypeTable + }; + static const char * const names[] = { + "far_vector", + "a", + "far_string", + "big_vector", + "near_string", + "nested_root", + "far_struct_vector", + "big_struct_vector", + "many_vectors" + }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_TABLE, 9, type_codes, type_refs, nullptr, nullptr, names + }; + return &tt; +} + +inline const RootTable *GetRootTable(const void *buf) { + return ::flatbuffers::GetRoot<RootTable>(buf); +} + +inline const RootTable *GetSizePrefixedRootTable(const void *buf) { + return ::flatbuffers::GetSizePrefixedRoot<RootTable,::flatbuffers::uoffset64_t>(buf); +} + +inline RootTable *GetMutableRootTable(void *buf) { + return ::flatbuffers::GetMutableRoot<RootTable>(buf); +} + +inline RootTable *GetMutableSizePrefixedRootTable(void *buf) { + return ::flatbuffers::GetMutableSizePrefixedRoot<RootTable,::flatbuffers::uoffset64_t>(buf); +} + +inline bool VerifyRootTableBuffer( + ::flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer<RootTable>(nullptr); +} + +inline bool VerifySizePrefixedRootTableBuffer( + ::flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer<RootTable,::flatbuffers::uoffset64_t>(nullptr); +} + +inline void FinishRootTableBuffer( + ::flatbuffers::FlatBufferBuilder64 &fbb, + ::flatbuffers::Offset<RootTable> root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedRootTableBuffer( + ::flatbuffers::FlatBufferBuilder64 &fbb, + ::flatbuffers::Offset<RootTable> root) { + fbb.FinishSizePrefixed(root); +} + +inline std::unique_ptr<RootTableT> UnPackRootTable( + const void *buf, + const ::flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr<RootTableT>(GetRootTable(buf)->UnPack(res)); +} + +inline std::unique_ptr<RootTableT> UnPackSizePrefixedRootTable( + const void *buf, + const ::flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr<RootTableT>(GetSizePrefixedRootTable(buf)->UnPack(res)); +} + +#endif // FLATBUFFERS_GENERATED_TEST64BIT_H_ diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel index 96fd9c1e..923890f6 100644 --- a/tests/BUILD.bazel +++ b/tests/BUILD.bazel @@ -20,6 +20,12 @@ cc_test( name = "flatbuffers_test", testonly = 1, srcs = [ + "64bit/evolution/v1_generated.h", + "64bit/evolution/v2_generated.h", + "64bit/offset64_test.cpp", + "64bit/offset64_test.h", + "64bit/test_64bit_bfbs_generated.h", + "64bit/test_64bit_generated.h", "alignment_test.cpp", "alignment_test.h", "alignment_test_generated.h", diff --git a/tests/MyGame/Example/Monster.php b/tests/MyGame/Example/Monster.php index 29976e4a..44649403 100644 --- a/tests/MyGame/Example/Monster.php +++ b/tests/MyGame/Example/Monster.php @@ -910,7 +910,7 @@ class Monster extends Table /** * @param FlatBufferBuilder $builder - * @param int + * @param VectorOffset * @return void */ public static function addPos(FlatBufferBuilder $builder, $pos) @@ -1111,7 +1111,7 @@ class Monster extends Table /** * @param FlatBufferBuilder $builder - * @param int + * @param VectorOffset * @return void */ public static function addEnemy(FlatBufferBuilder $builder, $enemy) @@ -1155,7 +1155,7 @@ class Monster extends Table /** * @param FlatBufferBuilder $builder - * @param int + * @param VectorOffset * @return void */ public static function addTestempty(FlatBufferBuilder $builder, $testempty) @@ -1523,7 +1523,7 @@ class Monster extends Table /** * @param FlatBufferBuilder $builder - * @param int + * @param VectorOffset * @return void */ public static function addParentNamespaceTest(FlatBufferBuilder $builder, $parentNamespaceTest) @@ -1875,7 +1875,7 @@ class Monster extends Table /** * @param FlatBufferBuilder $builder - * @param int + * @param VectorOffset * @return void */ public static function addNativeInline(FlatBufferBuilder $builder, $nativeInline) diff --git a/tests/evolution_test.cpp b/tests/evolution_test.cpp index 6c23d3fe..6ed2f574 100644 --- a/tests/evolution_test.cpp +++ b/tests/evolution_test.cpp @@ -80,7 +80,6 @@ void EvolutionTest(const std::string &tests_data_path) { #endif } - void ConformTest() { const char ref[] = "table T { A:int; } enum E:byte { A }"; @@ -111,9 +110,41 @@ void ConformTest() { const char ref2[] = "enum E:byte { A } table T2 { f:E; } "; test_conform(ref2, "enum E:int32 { A } table T2 { df:byte; f:E; }", "field renamed to different type: T2.df (renamed from T2.f)"); + + // Check conformity for Offset64-related changes. + { + const char ref[] = "table T { a:[uint8]; b:string; }"; + + // Adding a 'vector64' changes the type. + test_conform(ref, "table T { a:[uint8] (vector64); b:string; }", + "types differ for field: T.a"); + + // Adding a 'offset64' to the vector changes the type. + test_conform(ref, "table T { a:[uint8] (offset64); b:string; }", + "offset types differ for field: T.a"); + + // Adding a 'offset64' to the string also changes the type. + test_conform(ref, "table T { a:[uint8]; b:string (offset64); }", + "offset types differ for field: T.b"); + + // Now try the opposite direction of removing an attribute from an existing + // field. + + // Removing a 'vector64' changes the type. + test_conform("table T { a:[uint8] (vector64); b:string; }", ref, + "types differ for field: T.a"); + + // Removing a 'offset64' to the string also changes the type. + test_conform("table T { a:[uint8] (offset64); b:string; }", ref, + "offset types differ for field: T.a"); + + // Remove a 'offset64' to the string also changes the type. + test_conform("table T { a:[uint8]; b:string (offset64); }", ref, + "offset types differ for field: T.b"); + } } -void UnionDeprecationTest(const std::string& tests_data_path) { +void UnionDeprecationTest(const std::string &tests_data_path) { const int NUM_VERSIONS = 2; std::string schemas[NUM_VERSIONS]; std::string jsonfiles[NUM_VERSIONS]; diff --git a/tests/fuzzer/.gitignore b/tests/fuzzer/.gitignore index 2e4d1d19..720146cf 100644 --- a/tests/fuzzer/.gitignore +++ b/tests/fuzzer/.gitignore @@ -15,4 +15,6 @@ fuzz-*.log annotated_binary.bfbs annotated_binary.bin +test_64bit.bin + monster_test.bfbs
\ No newline at end of file diff --git a/tests/fuzzer/CMakeLists.txt b/tests/fuzzer/CMakeLists.txt index 63bda687..b0c4ae6d 100644 --- a/tests/fuzzer/CMakeLists.txt +++ b/tests/fuzzer/CMakeLists.txt @@ -117,6 +117,7 @@ set(FlatBuffers_Library_SRCS ${FLATBUFFERS_DIR}/src/binary_annotator.cpp ${FLATBUFFERS_DIR}/src/util.cpp ${FLATBUFFERS_DIR}/tests/test_assert.cpp + ${FLATBUFFERS_DIR}/tests/64bit/test_64bit_bfbs_generated.h ) include_directories(${FLATBUFFERS_DIR}/include) @@ -175,6 +176,16 @@ add_custom_command( ${CMAKE_CURRENT_BINARY_DIR}/seed_annotator/annotated_binary.bin ) +add_executable(64bit_fuzzer flatbuffers_64bit_fuzzer.cc) +target_link_libraries(64bit_fuzzer PRIVATE flatbuffers_fuzzed) +add_custom_command( + TARGET 64bit_fuzzer PRE_BUILD + + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_SOURCE_DIR}/../64bit/test_64bit.bin + ${CMAKE_CURRENT_BINARY_DIR}/seed_64bit/test_64bit.bin +) + # Build debugger for weird cases found with fuzzer. if(BUILD_DEBUGGER) add_library(flatbuffers_nonfuzz STATIC ${FlatBuffers_Library_SRCS}) diff --git a/tests/fuzzer/flatbuffers_64bit_fuzzer.cc b/tests/fuzzer/flatbuffers_64bit_fuzzer.cc new file mode 100644 index 00000000..efb629d3 --- /dev/null +++ b/tests/fuzzer/flatbuffers_64bit_fuzzer.cc @@ -0,0 +1,121 @@ +#include <cstdint> +#include <filesystem> +#include <type_traits> + +#include "64bit/test_64bit_bfbs_generated.h" +#include "64bit/test_64bit_generated.h" +#include "flatbuffers/base.h" +#include "flatbuffers/flatbuffer_builder.h" +#include "flatbuffers/flatbuffers.h" +#include "flatbuffers/reflection.h" +#include "flatbuffers/verifier.h" +#include "test_assert.h" +#include "test_init.h" + +OneTimeTestInit OneTimeTestInit::one_time_init_; + +static RootTableBinarySchema schema; + +static constexpr uint8_t flags_sized_prefixed = 0b00000001; + +static const uint64_t kFnvPrime = 0x00000100000001b3ULL; +static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL; + +namespace flatbuffers { + +template<typename T, typename = std::enable_if_t<std::is_integral_v<T>>> +uint64_t Hash(T value, uint64_t hash) { + return (hash * kFnvPrime) ^ value; +} + +uint64_t Hash(double value, uint64_t hash) { + static_assert(sizeof(double) == sizeof(uint64_t)); + return (hash * kFnvPrime) ^ static_cast<uint64_t>(value); +} + +uint64_t Hash(const flatbuffers::String *value, uint64_t hash) { + if (value == nullptr) { return hash * kFnvPrime; } + for (auto &c : value->str()) { hash = Hash(static_cast<uint8_t>(c), hash); } + return hash; +} + +uint64_t Hash(const LeafStruct *value, uint64_t hash) { + if (value == nullptr) { return hash * kFnvPrime; } + hash = Hash(value->a(), hash); + hash = Hash(value->b(), hash); + return hash; +} + +template<typename T> uint64_t Hash(const Vector<T> *value, uint64_t hash) { + if (value == nullptr) { return hash * kFnvPrime; } + for (const T c : *value) { hash = Hash(c, hash); } + return hash; +} + +template<typename T> uint64_t Hash(const Vector64<T> *value, uint64_t hash) { + if (value == nullptr) { return hash * kFnvPrime; } + for (const T c : *value) { hash = Hash(c, hash); } + return hash; +} + +uint64_t Hash(const RootTable *value, uint64_t hash) { + if (value == nullptr) { return hash * kFnvPrime; } + // Hash all the fields so we can exercise all parts of the code. + hash = Hash(value->far_vector(), hash); + hash = Hash(value->a(), hash); + hash = Hash(value->far_string(), hash); + hash = Hash(value->big_vector(), hash); + hash = Hash(value->near_string(), hash); + hash = Hash(value->nested_root(), hash); + hash = Hash(value->far_struct_vector(), hash); + hash = Hash(value->big_struct_vector(), hash); + return hash; +} + +static int AccessBuffer(const uint8_t *data, size_t size, + bool is_size_prefixed) { + const RootTable *root_table = + is_size_prefixed ? GetSizePrefixedRootTable(data) : GetRootTable(data); + TEST_NOTNULL(root_table); + + uint64_t hash = kOffsetBasis; + hash = Hash(root_table, hash); + hash = Hash(root_table->nested_root_nested_root(), hash); + + return 0; +} + +extern "C" int LLVMFuzzerInitialize(int *, char ***argv) { + Verifier verifier(schema.begin(), schema.size()); + TEST_EQ(true, reflection::VerifySchemaBuffer(verifier)); + + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size < FLATBUFFERS_MIN_BUFFER_SIZE) { return 0; } + + // Take the first bit of data as a flag to control things. + const uint8_t flags = data[0]; + data++; + size--; + + Verifier::Options options; + options.assert = true; + options.check_alignment = true; + options.check_nested_flatbuffers = true; + + Verifier verifier(data, size, options); + + const bool is_size_prefixed = flags & flags_sized_prefixed; + + // Filter out data that isn't valid. + if ((is_size_prefixed && !VerifySizePrefixedRootTableBuffer(verifier)) || + !VerifyRootTableBuffer(verifier)) { + return 0; + } + + return AccessBuffer(data, size, is_size_prefixed); +} + +} // namespace flatbuffers
\ No newline at end of file diff --git a/tests/fuzzer/flatbuffers_annotator_fuzzer.cc b/tests/fuzzer/flatbuffers_annotator_fuzzer.cc index 7ff43137..08c1e0bc 100644 --- a/tests/fuzzer/flatbuffers_annotator_fuzzer.cc +++ b/tests/fuzzer/flatbuffers_annotator_fuzzer.cc @@ -46,7 +46,7 @@ extern "C" int LLVMFuzzerInitialize(int *, char ***argv) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { flatbuffers::BinaryAnnotator annotator(schema_bfbs_, schema_bfbs_length_, - data, size); + data, size, false); annotator.Annotate(); return 0; diff --git a/tests/parser_test.cpp b/tests/parser_test.cpp index 7bcf62bf..83c67e85 100644 --- a/tests/parser_test.cpp +++ b/tests/parser_test.cpp @@ -16,8 +16,9 @@ static const auto infinity_f = std::numeric_limits<float>::infinity(); static const auto infinity_d = std::numeric_limits<double>::infinity(); // Test that parser errors are actually generated. -static void TestError_(const char *src, const char *error_substr, bool strict_json, - const char *file, int line, const char *func) { +static void TestError_(const char *src, const char *error_substr, + bool strict_json, const char *file, int line, + const char *func) { flatbuffers::IDLOptions opts; opts.strict_json = strict_json; flatbuffers::Parser parser(opts); @@ -32,8 +33,8 @@ static void TestError_(const char *src, const char *error_substr, bool strict_js } } -static void TestError_(const char *src, const char *error_substr, const char *file, - int line, const char *func) { +static void TestError_(const char *src, const char *error_substr, + const char *file, int line, const char *func) { TestError_(src, error_substr, false, file, line, func); } @@ -47,7 +48,7 @@ static void TestError_(const char *src, const char *error_substr, const char *fi static bool FloatCompare(float a, float b) { return fabs(a - b) < 0.001; } -} // namespace +} // namespace // Test that parsing errors occur as we'd expect. // Also useful for coverage, making sure these paths are run. @@ -124,6 +125,34 @@ void ErrorTest() { // An identifier can't start from sign (+|-) TestError("table X { -Y: int; } root_type Y: {Y:1.0}", "identifier"); TestError("table X { +Y: int; } root_type Y: {Y:1.0}", "identifier"); + + // Offset64 + TestError("table X { a:int (vector64); }", "`vector64` attribute"); + TestError("table X { a:int (offset64); }", "`offset64` attribute"); + TestError("table X { a:string (vector64); }", "`vector64` attribute"); + TestError("table y { a:int; } table X { a:y (offset64); }", + "`offset64` attribute"); + TestError("struct y { a:int; } table X { a:y (offset64); }", + "`offset64` attribute"); + TestError("table y { a:int; } table X { a:y (vector64); }", + "`vector64` attribute"); + TestError("union Y { } table X { ys:Y (offset64); }", "`offset64` attribute"); + + TestError("table Y { a:int; } table X { ys:[Y] (offset64); }", + "only vectors of scalars are allowed to be 64-bit."); + TestError("table Y { a:int; } table X { ys:[Y] (vector64); }", + "only vectors of scalars are allowed to be 64-bit."); + TestError("union Y { } table X { ys:[Y] (vector64); }", + "only vectors of scalars are allowed to be 64-bit."); + + // TOOD(derekbailey): the following three could be allowed once the code gen + // supports the output. + TestError("table X { y:[string] (offset64); }", + "only vectors of scalars are allowed to be 64-bit."); + TestError("table X { y:[string] (vector64); }", + "only vectors of scalars are allowed to be 64-bit."); + TestError("enum X:byte {Z} table X { y:[X] (offset64); }", + "only vectors of scalars are allowed to be 64-bit."); } void EnumOutOfRangeTest() { @@ -776,8 +805,6 @@ void UnicodeSurrogatesTest() { TEST_EQ_STR(string->c_str(), "\xF0\x9F\x92\xA9"); } - - void UnknownFieldsTest() { flatbuffers::IDLOptions opts; opts.skip_unexpected_fields_in_json = true; diff --git a/tests/test.cpp b/tests/test.cpp index 1faf33e4..ec60251a 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -42,7 +42,7 @@ #if !defined(_MSC_VER) || _MSC_VER >= 1700 # include "arrays_test_generated.h" #endif - +#include "64bit/offset64_test.h" #include "flexbuffers_test.h" #include "is_quiet_nan.h" #include "monster_test_bfbs_generated.h" // Generated using --bfbs-comments --bfbs-builtins --cpp --bfbs-gen-embed @@ -74,7 +74,7 @@ static_assert(flatbuffers::is_same<uint8_t, char>::value || using namespace MyGame::Example; void TriviallyCopyableTest() { -// clang-format off + // clang-format off #if __GNUG__ && __GNUC__ < 5 && \ !(defined(__clang__) && __clang_major__ >= 16) TEST_EQ(__has_trivial_copy(Vec3), true); @@ -1540,6 +1540,17 @@ void DoNotRequireEofTest(const std::string &tests_data_path) { } #endif +static void Offset64Tests() { + Offset64Test(); + Offset64SerializedFirst(); + Offset64NestedFlatBuffer(); + Offset64CreateDirect(); + Offset64Evolution(); + Offset64VectorOfStructs(); + Offset64SizePrefix(); + Offset64ManyVectors(); +} + int FlatBufferTests(const std::string &tests_data_path) { // Run our various test suites: @@ -1651,6 +1662,7 @@ int FlatBufferTests(const std::string &tests_data_path) { NestedStructKeyInStructTest(); FixedSizedStructArrayKeyInStructTest(); EmbeddedSchemaAccess(); + Offset64Tests(); return 0; } } // namespace diff --git a/tests/test_builder.cpp b/tests/test_builder.cpp index 047a380c..3b0eaa04 100644 --- a/tests/test_builder.cpp +++ b/tests/test_builder.cpp @@ -1,20 +1,22 @@ #include "test_builder.h" +#include "flatbuffers/flatbuffer_builder.h" #include "flatbuffers/stl_emulation.h" #include "monster_test_generated.h" using namespace MyGame::Example; +using namespace flatbuffers; -struct OwnedAllocator : public flatbuffers::DefaultAllocator {}; +struct OwnedAllocator : public DefaultAllocator {}; -class TestHeapBuilder : public flatbuffers::FlatBufferBuilder { +class TestHeapBuilder : public FlatBufferBuilder { private: TestHeapBuilder(const TestHeapBuilder &); TestHeapBuilder &operator=(const TestHeapBuilder &); public: TestHeapBuilder() - : flatbuffers::FlatBufferBuilder(2048, new OwnedAllocator(), true) {} + : FlatBufferBuilder(2048, new OwnedAllocator(), true) {} TestHeapBuilder(TestHeapBuilder &&other) : FlatBufferBuilder(std::move(other)) {} @@ -31,14 +33,14 @@ struct AllocatorMember { }; struct GrpcLikeMessageBuilder : private AllocatorMember, - public flatbuffers::FlatBufferBuilder { + public FlatBufferBuilder { private: GrpcLikeMessageBuilder(const GrpcLikeMessageBuilder &); GrpcLikeMessageBuilder &operator=(const GrpcLikeMessageBuilder &); public: GrpcLikeMessageBuilder() - : flatbuffers::FlatBufferBuilder(1024, &member_allocator_, false) {} + : FlatBufferBuilder(1024, &member_allocator_, false) {} GrpcLikeMessageBuilder(GrpcLikeMessageBuilder &&other) : FlatBufferBuilder(1024, &member_allocator_, false) { diff --git a/tests/test_builder.h b/tests/test_builder.h index 75338b04..8a214bab 100644 --- a/tests/test_builder.h +++ b/tests/test_builder.h @@ -17,10 +17,6 @@ class MessageBuilder; } } // namespace flatbuffers -template<class T, class U> struct is_same { static const bool value = false; }; - -template<class T> struct is_same<T, T> { static const bool value = true; }; - inline std::string m1_name() { return "Cyberdemon"; } inline std::string m2_name() { return "Imp"; } inline MyGame::Example::Color m1_color() { @@ -166,7 +162,7 @@ struct BuilderTests { } static void builder_swap_before_finish_test( - bool run = is_same<DestBuilder, SrcBuilder>::value) { + bool run = std::is_same<DestBuilder, SrcBuilder>::value) { /// Swap is allowed only when lhs and rhs are the same concrete type. if (run) { SrcBuilder src; @@ -186,7 +182,7 @@ struct BuilderTests { } static void builder_swap_after_finish_test( - bool run = is_same<DestBuilder, SrcBuilder>::value) { + bool run = std::is_same<DestBuilder, SrcBuilder>::value) { /// Swap is allowed only when lhs and rhs are the same concrete type. if (run) { SrcBuilder src; |