val->constant = NumToString(id - 1);
typefield->attributes.Add("id", val);
}
+ // if this field is a union that is deprecated,
+ // the automatically added type field should be deprecated as well
+ if (field->deprecated) {
+ typefield->deprecated = true;
+ }
}
EXPECT(';');
g:[int];
h:[TableB];
i:int = 1234;
+ j:Union;
}
-root_type Root;
\ No newline at end of file
+root_type Root;
{
"a": 459
}
- ]
-}
\ No newline at end of file
+ ],
+ "j": {
+ "a": 984
+ }
+}
namespace V1 {
struct TableA;
+struct TableABuilder;
struct TableB;
+struct TableBBuilder;
struct Struct;
struct Root;
+struct RootBuilder;
enum class Enum : int8_t {
King = 0,
}
inline const char *EnumNameEnum(Enum e) {
- if (e < Enum::King || e > Enum::Queen) return "";
+ if (flatbuffers::IsOutRange(e, Enum::King, Enum::Queen)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesEnum()[index];
}
}
inline const char *EnumNameUnion(Union e) {
- if (e < Union::NONE || e > Union::TableB) return "";
+ if (flatbuffers::IsOutRange(e, Union::NONE, Union::TableB)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesUnion()[index];
}
double b_;
public:
- Struct() {
- memset(static_cast<void *>(this), 0, sizeof(Struct));
+ Struct()
+ : a_(0),
+ padding0__(0),
+ b_(0) {
+ (void)padding0__;
}
Struct(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_);
FLATBUFFERS_STRUCT_END(Struct, 16);
struct TableA FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef TableABuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_A = 4,
VT_B = 6
};
struct TableABuilder {
+ typedef TableA Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_a(float a) {
}
struct TableB FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef TableBBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_A = 4
};
};
struct TableBBuilder {
+ typedef TableB Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_a(int32_t a) {
}
struct Root FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef RootBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_A = 4,
VT_B = 6,
VT_F = 16,
VT_G = 18,
VT_H = 20,
- VT_I = 22
+ VT_I = 22,
+ VT_J_TYPE = 24,
+ VT_J = 26
};
int32_t a() const {
return GetField<int32_t>(VT_A, 0);
int32_t i() const {
return GetField<int32_t>(VT_I, 1234);
}
+ Evolution::V1::Union j_type() const {
+ return static_cast<Evolution::V1::Union>(GetField<uint8_t>(VT_J_TYPE, 0));
+ }
+ const void *j() const {
+ return GetPointer<const void *>(VT_J);
+ }
+ template<typename T> const T *j_as() const;
+ const Evolution::V1::TableA *j_as_TableA() const {
+ return j_type() == Evolution::V1::Union::TableA ? static_cast<const Evolution::V1::TableA *>(j()) : nullptr;
+ }
+ const Evolution::V1::TableB *j_as_TableB() const {
+ return j_type() == Evolution::V1::Union::TableB ? static_cast<const Evolution::V1::TableB *>(j()) : nullptr;
+ }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<int32_t>(verifier, VT_A) &&
verifier.VerifyVector(h()) &&
verifier.VerifyVectorOfTables(h()) &&
VerifyField<int32_t>(verifier, VT_I) &&
+ VerifyField<uint8_t>(verifier, VT_J_TYPE) &&
+ VerifyOffset(verifier, VT_J) &&
+ VerifyUnion(verifier, j(), j_type()) &&
verifier.EndTable();
}
};
return c_as_TableB();
}
+template<> inline const Evolution::V1::TableA *Root::j_as<Evolution::V1::TableA>() const {
+ return j_as_TableA();
+}
+
+template<> inline const Evolution::V1::TableB *Root::j_as<Evolution::V1::TableB>() const {
+ return j_as_TableB();
+}
+
struct RootBuilder {
+ typedef Root Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_a(int32_t a) {
void add_i(int32_t i) {
fbb_.AddElement<int32_t>(Root::VT_I, i, 1234);
}
+ void add_j_type(Evolution::V1::Union j_type) {
+ fbb_.AddElement<uint8_t>(Root::VT_J_TYPE, static_cast<uint8_t>(j_type), 0);
+ }
+ void add_j(flatbuffers::Offset<void> j) {
+ fbb_.AddOffset(Root::VT_J, j);
+ }
explicit RootBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
const Evolution::V1::Struct *f = 0,
flatbuffers::Offset<flatbuffers::Vector<int32_t>> g = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Evolution::V1::TableB>>> h = 0,
- int32_t i = 1234) {
+ int32_t i = 1234,
+ Evolution::V1::Union j_type = Evolution::V1::Union::NONE,
+ flatbuffers::Offset<void> j = 0) {
RootBuilder builder_(_fbb);
+ builder_.add_j(j);
builder_.add_i(i);
builder_.add_h(h);
builder_.add_g(g);
builder_.add_e(e);
builder_.add_c(c);
builder_.add_a(a);
+ builder_.add_j_type(j_type);
builder_.add_d(d);
builder_.add_c_type(c_type);
builder_.add_b(b);
const Evolution::V1::Struct *f = 0,
const std::vector<int32_t> *g = nullptr,
const std::vector<flatbuffers::Offset<Evolution::V1::TableB>> *h = nullptr,
- int32_t i = 1234) {
+ int32_t i = 1234,
+ Evolution::V1::Union j_type = Evolution::V1::Union::NONE,
+ flatbuffers::Offset<void> j = 0) {
auto g__ = g ? _fbb.CreateVector<int32_t>(*g) : 0;
auto h__ = h ? _fbb.CreateVector<flatbuffers::Offset<Evolution::V1::TableB>>(*h) : 0;
return Evolution::V1::CreateRoot(
f,
g__,
h__,
- i);
+ i,
+ j_type,
+ j);
}
inline bool VerifyUnion(flatbuffers::Verifier &verifier, const void *obj, Union type) {
g:[int];
h:[TableB];
i:uint = 1234;
- j:TableC; // new in v2
- k:uint8 = 56; // new in v2
+ j:Union (deprecated); // deprecated in v2
+ k:TableC; // new in v2
+ l:uint8 = 56; // new in v2
}
-root_type Root;
\ No newline at end of file
+root_type Root;
}
],
"i": 4321,
- "j": {
+ "k": {
"a": 9874.342,
"b": "more please"
}
namespace V2 {
struct TableA;
+struct TableABuilder;
struct TableB;
+struct TableBBuilder;
struct TableC;
+struct TableCBuilder;
struct Struct;
struct Root;
+struct RootBuilder;
enum class Enum : int8_t {
King = 0,
}
inline const char *EnumNameEnum(Enum e) {
- if (e < Enum::King || e > Enum::Bishop) return "";
+ if (flatbuffers::IsOutRange(e, Enum::King, Enum::Bishop)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesEnum()[index];
}
}
inline const char *EnumNameUnion(Union e) {
- if (e < Union::NONE || e > Union::TableC) return "";
+ if (flatbuffers::IsOutRange(e, Union::NONE, Union::TableC)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesUnion()[index];
}
double b_;
public:
- Struct() {
- memset(static_cast<void *>(this), 0, sizeof(Struct));
+ Struct()
+ : a_(0),
+ padding0__(0),
+ b_(0) {
+ (void)padding0__;
}
Struct(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_);
FLATBUFFERS_STRUCT_END(Struct, 16);
struct TableA FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef TableABuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_A = 4,
VT_B = 6,
};
struct TableABuilder {
+ typedef TableA Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_a(float a) {
}
struct TableB FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef TableBBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_A = 4
};
};
struct TableBBuilder {
+ typedef TableB Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_a(int32_t a) {
}
struct TableC FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef TableCBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_A = 4,
VT_B = 6
};
struct TableCBuilder {
+ typedef TableC Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_a(double a) {
}
struct Root FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef RootBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_B = 6,
VT_C_TYPE = 8,
VT_G = 18,
VT_H = 20,
VT_I = 22,
- VT_J = 24,
- VT_K = 26
+ VT_K = 28,
+ VT_L = 30
};
bool b() const {
return GetField<uint8_t>(VT_B, 0) != 0;
uint32_t i() const {
return GetField<uint32_t>(VT_I, 1234);
}
- const Evolution::V2::TableC *j() const {
- return GetPointer<const Evolution::V2::TableC *>(VT_J);
+ const Evolution::V2::TableC *k() const {
+ return GetPointer<const Evolution::V2::TableC *>(VT_K);
}
- uint8_t k() const {
- return GetField<uint8_t>(VT_K, 56);
+ uint8_t l() const {
+ return GetField<uint8_t>(VT_L, 56);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
verifier.VerifyVector(h()) &&
verifier.VerifyVectorOfTables(h()) &&
VerifyField<uint32_t>(verifier, VT_I) &&
- VerifyOffset(verifier, VT_J) &&
- verifier.VerifyTable(j()) &&
- VerifyField<uint8_t>(verifier, VT_K) &&
+ VerifyOffset(verifier, VT_K) &&
+ verifier.VerifyTable(k()) &&
+ VerifyField<uint8_t>(verifier, VT_L) &&
verifier.EndTable();
}
};
}
struct RootBuilder {
+ typedef Root Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_b(bool b) {
void add_i(uint32_t i) {
fbb_.AddElement<uint32_t>(Root::VT_I, i, 1234);
}
- void add_j(flatbuffers::Offset<Evolution::V2::TableC> j) {
- fbb_.AddOffset(Root::VT_J, j);
+ void add_k(flatbuffers::Offset<Evolution::V2::TableC> k) {
+ fbb_.AddOffset(Root::VT_K, k);
}
- void add_k(uint8_t k) {
- fbb_.AddElement<uint8_t>(Root::VT_K, k, 56);
+ void add_l(uint8_t l) {
+ fbb_.AddElement<uint8_t>(Root::VT_L, l, 56);
}
explicit RootBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
flatbuffers::Offset<flatbuffers::Vector<int32_t>> g = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Evolution::V2::TableB>>> h = 0,
uint32_t i = 1234,
- flatbuffers::Offset<Evolution::V2::TableC> j = 0,
- uint8_t k = 56) {
+ flatbuffers::Offset<Evolution::V2::TableC> k = 0,
+ uint8_t l = 56) {
RootBuilder builder_(_fbb);
- builder_.add_j(j);
+ builder_.add_k(k);
builder_.add_i(i);
builder_.add_h(h);
builder_.add_g(g);
builder_.add_ff(ff);
builder_.add_e(e);
builder_.add_c(c);
- builder_.add_k(k);
+ builder_.add_l(l);
builder_.add_d(d);
builder_.add_c_type(c_type);
builder_.add_b(b);
const std::vector<int32_t> *g = nullptr,
const std::vector<flatbuffers::Offset<Evolution::V2::TableB>> *h = nullptr,
uint32_t i = 1234,
- flatbuffers::Offset<Evolution::V2::TableC> j = 0,
- uint8_t k = 56) {
+ flatbuffers::Offset<Evolution::V2::TableC> k = 0,
+ uint8_t l = 56) {
auto g__ = g ? _fbb.CreateVector<int32_t>(*g) : 0;
auto h__ = h ? _fbb.CreateVector<flatbuffers::Offset<Evolution::V2::TableB>>(*h) : 0;
return Evolution::V2::CreateRoot(
g__,
h__,
i,
- j,
- k);
+ k,
+ l);
}
inline bool VerifyUnion(flatbuffers::Verifier &verifier, const void *obj, Union type) {
// Test backwards compatibility by reading old data with an evolved schema.
auto root_v1_viewed_from_v2 = Evolution::V2::GetRoot(&binaries[0].front());
- // field 'j' is new in version 2, so it should be null.
- TEST_ASSERT(nullptr == root_v1_viewed_from_v2->j());
- // field 'k' is new in version 2 with a default of 56.
- TEST_EQ(root_v1_viewed_from_v2->k(), 56);
+ // field 'k' is new in version 2, so it should be null.
+ TEST_ASSERT(nullptr == root_v1_viewed_from_v2->k());
+ // field 'l' is new in version 2 with a default of 56.
+ TEST_EQ(root_v1_viewed_from_v2->l(), 56);
// field 'c' of 'TableA' is new in version 2, so it should be null.
TEST_ASSERT(nullptr == root_v1_viewed_from_v2->e()->c());
// 'TableC' was added to field 'c' union in version 2, so it should be null.
#endif
}
+void UnionDeprecationTest() {
+ const int NUM_VERSIONS = 2;
+ std::string schemas[NUM_VERSIONS];
+ std::string jsonfiles[NUM_VERSIONS];
+ std::vector<uint8_t> binaries[NUM_VERSIONS];
+
+ flatbuffers::IDLOptions idl_opts;
+ idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary;
+ flatbuffers::Parser parser(idl_opts);
+
+ // Load all the schema versions and their associated data.
+ for (int i = 0; i < NUM_VERSIONS; ++i) {
+ std::string schema = test_data_path + "evolution_test/evolution_v" +
+ flatbuffers::NumToString(i + 1) + ".fbs";
+ TEST_ASSERT(flatbuffers::LoadFile(schema.c_str(), false, &schemas[i]));
+ std::string json = test_data_path + "evolution_test/evolution_v" +
+ flatbuffers::NumToString(i + 1) + ".json";
+ TEST_ASSERT(flatbuffers::LoadFile(json.c_str(), false, &jsonfiles[i]));
+
+ TEST_ASSERT(parser.Parse(schemas[i].c_str()));
+ TEST_ASSERT(parser.Parse(jsonfiles[i].c_str()));
+
+ auto bufLen = parser.builder_.GetSize();
+ auto buf = parser.builder_.GetBufferPointer();
+ binaries[i].reserve(bufLen);
+ std::copy(buf, buf + bufLen, std::back_inserter(binaries[i]));
+ }
+
+ auto v2 = parser.LookupStruct("Evolution.V2.Root");
+ TEST_NOTNULL(v2);
+ auto j_type_field = v2->fields.Lookup("j_type");
+ TEST_NOTNULL(j_type_field);
+ TEST_ASSERT(j_type_field->deprecated);
+}
+
void UnionVectorTest() {
// load FlatBuffer fbs schema and json.
std::string schemafile, jsonfile;
ParseProtoTestWithSuffix();
ParseProtoTestWithIncludes();
EvolutionTest();
+ UnionDeprecationTest();
UnionVectorTest();
LoadVerifyBinaryTest();
GenerateTableTextTest();