diff --git a/CMakeLists.txt b/CMakeLists.txt index 9201d679a..ca06af42e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,6 +158,8 @@ set(FlatBuffers_Tests_SRCS ${CMAKE_CURRENT_BINARY_DIR}/tests/monster_extra_generated.h # file generate by running compiler on tests/monster_test.fbs ${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_bfbs_generated.h + # file generate by running compiler on tests/optional_scalars.fbs + ${CMAKE_CURRENT_BINARY_DIR}/tests/optional_scalars_generated.h ) set(FlatBuffers_Tests_CPP17_SRCS @@ -168,6 +170,8 @@ set(FlatBuffers_Tests_CPP17_SRCS # file generate by running compiler on tests/monster_test.fbs ${CMAKE_CURRENT_BINARY_DIR}/tests/cpp17/generated_cpp17/monster_test_generated.h ${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h + ${CMAKE_CURRENT_BINARY_DIR}/tests/cpp17/generated_cpp17/optional_scalars_generated.h + ${CMAKE_CURRENT_BINARY_DIR}/tests/optional_scalars_generated.h ) set(FlatBuffers_Sample_Binary_SRCS diff --git a/include/flatbuffers/base.h b/include/flatbuffers/base.h index d83c7756e..8e97c0848 100644 --- a/include/flatbuffers/base.h +++ b/include/flatbuffers/base.h @@ -47,22 +47,17 @@ #include #if defined(__unix__) && !defined(FLATBUFFERS_LOCALE_INDEPENDENT) -#include -#endif + #include +#endif #ifdef _STLPORT_VERSION #define FLATBUFFERS_CPP98_STL #endif -#ifndef FLATBUFFERS_CPP98_STL - #include -#endif #ifdef __ANDROID__ #include #endif -#include "flatbuffers/stl_emulation.h" - #if defined(__ICCARM__) #include #endif @@ -162,10 +157,12 @@ namespace flatbuffers { defined(__clang__) #define FLATBUFFERS_FINAL_CLASS final #define FLATBUFFERS_OVERRIDE override + #define FLATBUFFERS_EXPLICIT_CPP11 explicit #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t #else #define FLATBUFFERS_FINAL_CLASS #define FLATBUFFERS_OVERRIDE + #define FLATBUFFERS_EXPLICIT_CPP11 #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE #endif @@ -173,10 +170,14 @@ namespace flatbuffers { (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ (defined(__cpp_constexpr) && __cpp_constexpr >= 200704) #define FLATBUFFERS_CONSTEXPR constexpr + #define FLATBUFFERS_CONSTEXPR_CPP11 constexpr + #define FLATBUFFERS_CONSTEXPR_DEFINED #else #define FLATBUFFERS_CONSTEXPR const + #define FLATBUFFERS_CONSTEXPR_CPP11 #endif +// This macro is never used in code! #if (defined(__cplusplus) && __cplusplus >= 201402L) || \ (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR @@ -202,6 +203,16 @@ namespace flatbuffers { #define FLATBUFFERS_DELETE_FUNC(func) private: func; #endif +// Check if we can use template aliases +// Not possible if Microsoft Compiler before 2012 +// Possible is the language feature __cpp_alias_templates is defined well +// Or possible if the C++ std is C+11 or newer +#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \ + || (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \ + || (defined(__cplusplus) && __cplusplus >= 201103L) + #define FLATBUFFERS_TEMPLATES_ALIASES +#endif + #ifndef FLATBUFFERS_HAS_STRING_VIEW // Only provide flatbuffers::string_view if __has_include can be used // to detect a header that provides an implementation diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 12ab68af5..28441248e 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -18,6 +18,11 @@ #define FLATBUFFERS_H_ #include "flatbuffers/base.h" +#include "flatbuffers/stl_emulation.h" + +#ifndef FLATBUFFERS_CPP98_STL + #include +#endif #if defined(FLATBUFFERS_NAN_DEFAULTS) # include @@ -1303,6 +1308,11 @@ class FlatBufferBuilder { TrackField(field, off); } + template void AddElement(voffset_t field, T e) { + auto off = PushElement(e); + TrackField(field, off); + } + template void AddOffset(voffset_t field, Offset off) { if (off.IsNull()) return; // Don't store. AddElement(field, ReferTo(off.o), static_cast(0)); @@ -2460,12 +2470,26 @@ class Table { return field_offset ? reinterpret_cast

(p) : nullptr; } + template + flatbuffers::Optional GetOptional(voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + auto p = data_ + field_offset; + return field_offset ? Optional(static_cast(ReadScalar(p))) + : Optional(); + } + template bool SetField(voffset_t field, T val, T def) { auto field_offset = GetOptionalFieldOffset(field); if (!field_offset) return IsTheSameAs(val, def); WriteScalar(data_ + field_offset, val); return true; } + template bool SetField(voffset_t field, T val) { + auto field_offset = GetOptionalFieldOffset(field); + if (!field_offset) return false; + WriteScalar(data_ + field_offset, val); + return true; + } bool SetPointer(voffset_t field, const uint8_t *val) { auto field_offset = GetOptionalFieldOffset(field); @@ -2533,6 +2557,17 @@ class Table { uint8_t data_[1]; }; +// This specialization allows avoiding warnings like: +// MSVC C4800: type: forcing value to bool 'true' or 'false'. +template<> +inline flatbuffers::Optional Table::GetOptional( + voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + auto p = data_ + field_offset; + return field_offset ? Optional(ReadScalar(p) != 0) + : Optional(); +} + template void FlatBufferBuilder::Required(Offset table, voffset_t field) { auto table_ptr = reinterpret_cast(buf_.data_at(table.o)); diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index a361c6530..a3c318839 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -847,6 +847,11 @@ class Parser : public ParserState { FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg); + // @brief Verify that any of 'opts.lang_to_generate' supports Optional scalars + // in a schema. + // @param opts Options used to parce a schema and generate code. + static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts); + private: void Message(const std::string &msg); void Warning(const std::string &msg); diff --git a/include/flatbuffers/stl_emulation.h b/include/flatbuffers/stl_emulation.h index d7d655eff..c9a1a8bfa 100644 --- a/include/flatbuffers/stl_emulation.h +++ b/include/flatbuffers/stl_emulation.h @@ -18,6 +18,7 @@ #define FLATBUFFERS_STL_EMULATION_H_ // clang-format off +#include "flatbuffers/base.h" #include #include @@ -25,6 +26,17 @@ #include #include +// Detect C++17 compatible compiler. +// __cplusplus >= 201703L - a compiler has support of 'static inline' variables. +#if defined(FLATBUFFERS_USE_STD_OPTIONAL) \ + || (defined(__cplusplus) && __cplusplus >= 201703L) \ + || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)) + #include + #ifndef FLATBUFFERS_USE_STD_OPTIONAL + #define FLATBUFFERS_USE_STD_OPTIONAL + #endif +#endif + #if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL) #define FLATBUFFERS_CPP98_STL #endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL) @@ -33,16 +45,6 @@ #include #endif // defined(FLATBUFFERS_CPP98_STL) -// Check if we can use template aliases -// Not possible if Microsoft Compiler before 2012 -// Possible is the language feature __cpp_alias_templates is defined well -// Or possible if the C++ std is C+11 or newer -#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \ - || (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \ - || (defined(__cplusplus) && __cplusplus >= 201103L) - #define FLATBUFFERS_TEMPLATES_ALIASES -#endif - // This header provides backwards compatibility for C++98 STLs like stlport. namespace flatbuffers { @@ -302,6 +304,146 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { #endif // !FLATBUFFERS_CPP98_STL +#ifdef FLATBUFFERS_USE_STD_OPTIONAL +template +using Optional = std::optional; +using nullopt_t = std::nullopt_t; +inline constexpr nullopt_t nullopt = std::nullopt; + +#else +// Limited implementation of Optional type for a scalar T. +// This implementation limited by trivial types compatible with +// std::is_arithmetic or std::is_enum type traits. + +// A tag to indicate an empty flatbuffers::optional. +struct nullopt_t { + explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {} +}; + +#if defined(FLATBUFFERS_CONSTEXPR_DEFINED) + namespace internal { + template struct nullopt_holder { + static constexpr nullopt_t instance_ = nullopt_t(0); + }; + template + constexpr nullopt_t nullopt_holder::instance_; + } + static constexpr const nullopt_t &nullopt = internal::nullopt_holder::instance_; + +#else + namespace internal { + template struct nullopt_holder { + static const nullopt_t instance_; + }; + template + const nullopt_t nullopt_holder::instance_ = nullopt_t(0); + } + static const nullopt_t &nullopt = internal::nullopt_holder::instance_; + +#endif + +template +class Optional FLATBUFFERS_FINAL_CLASS { + // Non-scalar 'T' would extremely complicated Optional. + // Use is_scalar checking because flatbuffers flatbuffers::is_arithmetic + // isn't implemented. + static_assert(flatbuffers::is_scalar::value, "unexpected type T"); + + public: + ~Optional() {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT + : value_(), has_value_(false) {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT + : value_(), has_value_(false) {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT + : value_(val), has_value_(true) {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT + : value_(other.value_), has_value_(other.has_value_) {} + + FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT { + value_ = other.value_; + has_value_ = other.has_value_; + return *this; + } + + FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT { + value_ = T(); + has_value_ = false; + return *this; + } + + FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT { + value_ = val; + has_value_ = true; + return *this; + } + + void reset() FLATBUFFERS_NOEXCEPT { + *this = nullopt; + } + + void swap(Optional &other) FLATBUFFERS_NOEXCEPT { + std::swap(value_, other.value_); + std::swap(has_value_, other.has_value_); + } + + FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT { + return has_value_; + } + + FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT { + return has_value_; + } + + FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT { + return value_; + } + + const T& value() const { + FLATBUFFERS_ASSERT(has_value()); + return value_; + } + + T value_or(T default_value) const FLATBUFFERS_NOEXCEPT { + return has_value() ? value_ : default_value; + } + + private: + T value_; + bool has_value_; +}; + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional& opt, nullopt_t) FLATBUFFERS_NOEXCEPT { + return !opt; +} +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional& opt) FLATBUFFERS_NOEXCEPT { + return !opt; +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT { + return static_cast(lhs) && (*lhs == rhs); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional& rhs) FLATBUFFERS_NOEXCEPT { + return static_cast(rhs) && (lhs == *rhs); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional& lhs, const Optional& rhs) FLATBUFFERS_NOEXCEPT { + return static_cast(lhs) != static_cast(rhs) + ? false + : !static_cast(lhs) ? false : (*lhs == *rhs); +} +#endif // FLATBUFFERS_USE_STD_OPTIONAL + } // namespace flatbuffers #endif // FLATBUFFERS_STL_EMULATION_H_ diff --git a/include/flatbuffers/util.h b/include/flatbuffers/util.h index b6340a2a9..37ea1b912 100644 --- a/include/flatbuffers/util.h +++ b/include/flatbuffers/util.h @@ -20,6 +20,7 @@ #include #include "flatbuffers/base.h" +#include "flatbuffers/stl_emulation.h" #ifndef FLATBUFFERS_PREFER_PRINTF # include diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index f7b14b552..890845b91 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -751,6 +751,12 @@ class CppGenerator : public BaseGenerator { return ptr_type == "naked" ? "" : ".get()"; } + std::string GenOptionalNull() { return "flatbuffers::nullopt"; } + + std::string GenOptionalDecl(const Type &type) { + return "flatbuffers::Optional<" + GenTypeBasic(type, true) + ">"; + } + std::string GenTypeNative(const Type &type, bool invector, const FieldDef &field) { switch (type.base_type) { @@ -788,7 +794,8 @@ class CppGenerator : public BaseGenerator { return type_name + "Union"; } default: { - return GenTypeBasic(type, true); + return field.IsScalarOptional() ? GenOptionalDecl(type) + : GenTypeBasic(type, true); } } } @@ -1581,17 +1588,17 @@ class CppGenerator : public BaseGenerator { } std::string GetDefaultScalarValue(const FieldDef &field, bool is_ctor) { - if (field.value.type.enum_def && IsScalar(field.value.type.base_type)) { - auto ev = field.value.type.enum_def->FindByValue(field.value.constant); + const auto &type = field.value.type; + if (type.enum_def && IsScalar(type.base_type)) { + auto ev = type.enum_def->FindByValue(field.value.constant); if (ev) { - return WrapInNameSpace(field.value.type.enum_def->defined_namespace, - GetEnumValUse(*field.value.type.enum_def, *ev)); + return WrapInNameSpace(type.enum_def->defined_namespace, + GetEnumValUse(*type.enum_def, *ev)); } else { return GenUnderlyingCast( - field, true, - NumToStringCpp(field.value.constant, field.value.type.base_type)); + field, true, NumToStringCpp(field.value.constant, type.base_type)); } - } else if (field.value.type.base_type == BASE_TYPE_BOOL) { + } else if (type.base_type == BASE_TYPE_BOOL) { return field.value.constant == "0" ? "false" : "true"; } else if (field.attributes.Lookup("cpp_type")) { if (is_ctor) { @@ -1604,7 +1611,8 @@ class CppGenerator : public BaseGenerator { return "0"; } } else { - return GenDefaultConstant(field); + return field.IsScalarOptional() ? GenOptionalNull() + : GenDefaultConstant(field); } } @@ -1629,8 +1637,14 @@ class CppGenerator : public BaseGenerator { } code_.SetValue("PARAM_VALUE", "nullptr"); } else { - code_.SetValue("PARAM_TYPE", GenTypeWire(field.value.type, " ", true)); - code_.SetValue("PARAM_VALUE", GetDefaultScalarValue(field, false)); + const auto &type = field.value.type; + if (field.IsScalarOptional()) { + code_.SetValue("PARAM_TYPE", GenOptionalDecl(type)); + code_.SetValue("PARAM_VALUE", GenOptionalNull()); + } else { + code_.SetValue("PARAM_TYPE", GenTypeWire(type, " ", true)); + code_.SetValue("PARAM_VALUE", GetDefaultScalarValue(field, false)); + } } code_ += "{{PRE}}{{PARAM_TYPE}}{{PARAM_NAME}} = {{PARAM_VALUE}}\\"; } @@ -1692,7 +1706,9 @@ class CppGenerator : public BaseGenerator { auto native_default = field.attributes.Lookup("native_default"); // Scalar types get parsed defaults, raw pointers get nullptrs. if (IsScalar(field.value.type.base_type)) { - if (!initializer_list.empty()) { initializer_list += ",\n "; } + if (!initializer_list.empty()) { + initializer_list += ",\n "; + } initializer_list += Name(field); initializer_list += "(" + @@ -1906,16 +1922,6 @@ class CppGenerator : public BaseGenerator { } } - std::string GetFieldAccessor(const FieldDef &field) const { - const auto &type = field.value.type; - if (IsScalar(type.base_type)) - return "GetField<"; - else if (IsStruct(type)) - return "GetStruct<"; - else - return "GetPointer<"; - } - void GenTableUnionAsGetters(const FieldDef &field) { const auto &type = field.value.type; auto u = type.enum_def; @@ -1950,33 +1956,47 @@ class CppGenerator : public BaseGenerator { } void GenTableFieldGetter(const FieldDef &field) { - const auto& type = field.value.type; - const bool is_scalar = IsScalar(type.base_type); + const auto &type = field.value.type; + const auto offset_str = GenFieldOffsetName(field); - // Call a different accessor for pointers, that indirects. - auto accessor = GetFieldAccessor(field); - auto offset_str = GenFieldOffsetName(field); - auto offset_type = GenTypeGet(type, "", "const ", " *", false); - - auto call = accessor + offset_type + ">(" + offset_str; - // Default value as second arg for non-pointer types. - if (is_scalar) { call += ", " + GenDefaultConstant(field); } - call += ")"; - - std::string afterptr = " *" + NullableExtension(); GenComment(field.doc_comment, " "); - code_.SetValue("FIELD_TYPE", GenTypeGet(type, " ", "const ", - afterptr.c_str(), true)); - code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, call)); - code_.SetValue("NULLABLE_EXT", NullableExtension()); + // Call a different accessor for pointers, that indirects. + if (false == field.IsScalarOptional()) { + const bool is_scalar = IsScalar(type.base_type); + std::string accessor; + if (is_scalar) + accessor = "GetField<"; + else if (IsStruct(type)) + accessor = "GetStruct<"; + else + accessor = "GetPointer<"; + auto offset_type = GenTypeGet(type, "", "const ", " *", false); + auto call = accessor + offset_type + ">(" + offset_str; + // Default value as second arg for non-pointer types. + if (is_scalar) { call += ", " + GenDefaultConstant(field); } + call += ")"; - code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {"; - code_ += " return {{FIELD_VALUE}};"; - code_ += " }"; - - if (type.base_type == BASE_TYPE_UNION) { - GenTableUnionAsGetters(field); + std::string afterptr = " *" + NullableExtension(); + code_.SetValue("FIELD_TYPE", + GenTypeGet(type, " ", "const ", afterptr.c_str(), true)); + code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, call)); + code_.SetValue("NULLABLE_EXT", NullableExtension()); + code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {"; + code_ += " return {{FIELD_VALUE}};"; + code_ += " }"; } + else { + auto wire_type = GenTypeBasic(type, false); + auto face_type = GenTypeBasic(type, true); + auto opt_value = "GetOptional<" + wire_type + ", " + face_type + ">(" + + offset_str + ")"; + code_.SetValue("FIELD_TYPE", GenOptionalDecl(type)); + code_ += " {{FIELD_TYPE}} {{FIELD_NAME}}() const {"; + code_ += " return " + opt_value + ";"; + code_ += " }"; + } + + if (type.base_type == BASE_TYPE_UNION) { GenTableUnionAsGetters(field); } } void GenTableFieldSetter(const FieldDef &field) { @@ -1984,7 +2004,7 @@ class CppGenerator : public BaseGenerator { const bool is_scalar = IsScalar(type.base_type); if (is_scalar && IsUnion(type)) return; // changing of a union's type is forbidden - auto accessor = GetFieldAccessor(field); + auto offset_str = GenFieldOffsetName(field); if (is_scalar) { const auto wire_type = GenTypeWire(type, "", false); @@ -1993,18 +2013,23 @@ class CppGenerator : public BaseGenerator { code_.SetValue("FIELD_TYPE", GenTypeBasic(type, true)); code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, false, "_" + Name(field))); - code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field)); code_ += " bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} " "_{{FIELD_NAME}}) {"; - code_ += - " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, " - "{{DEFAULT_VALUE}});"; + if (false == field.IsScalarOptional()) { + code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field)); + code_ += + " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, " + "{{DEFAULT_VALUE}});"; + } else { + code_ += " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}});"; + } code_ += " }"; } else { auto postptr = " *" + NullableExtension(); auto wire_type = GenTypeGet(type, " ", "", postptr.c_str(), true); + std::string accessor = IsStruct(type) ? "GetStruct<" : "GetPointer<"; auto underlying = accessor + wire_type + ">(" + offset_str + ")"; code_.SetValue("FIELD_TYPE", wire_type); code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, underlying)); @@ -2073,7 +2098,7 @@ class CppGenerator : public BaseGenerator { // Deprecated fields won't be accessible. continue; } - + code_.SetValue("FIELD_NAME", Name(field)); GenTableFieldGetter(field); if (opts_.mutable_buffer) { @@ -2219,43 +2244,44 @@ class CppGenerator : public BaseGenerator { for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; - if (!field.deprecated) { - const bool is_scalar = IsScalar(field.value.type.base_type); - const bool is_string = field.value.type.base_type == BASE_TYPE_STRING; - const bool is_vector = field.value.type.base_type == BASE_TYPE_VECTOR; - if (is_string || is_vector) { has_string_or_vector_fields = true; } + if (field.deprecated) + continue; + const bool is_scalar = IsScalar(field.value.type.base_type); + const bool is_default_scalar = is_scalar && !field.IsScalarOptional(); + const bool is_string = field.value.type.base_type == BASE_TYPE_STRING; + const bool is_vector = field.value.type.base_type == BASE_TYPE_VECTOR; + if (is_string || is_vector) { has_string_or_vector_fields = true; } - std::string offset = GenFieldOffsetName(field); - std::string name = GenUnderlyingCast(field, false, Name(field)); - std::string value = is_scalar ? GenDefaultConstant(field) : ""; + std::string offset = GenFieldOffsetName(field); + std::string name = GenUnderlyingCast(field, false, Name(field)); + std::string value = is_default_scalar ? GenDefaultConstant(field) : ""; - // Generate accessor functions of the form: - // void add_name(type name) { - // fbb_.AddElement(offset, name, default); - // } - code_.SetValue("FIELD_NAME", Name(field)); - code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true)); - code_.SetValue("ADD_OFFSET", Name(struct_def) + "::" + offset); - code_.SetValue("ADD_NAME", name); - code_.SetValue("ADD_VALUE", value); - if (is_scalar) { - const auto type = GenTypeWire(field.value.type, "", false); - code_.SetValue("ADD_FN", "AddElement<" + type + ">"); - } else if (IsStruct(field.value.type)) { - code_.SetValue("ADD_FN", "AddStruct"); - } else { - code_.SetValue("ADD_FN", "AddOffset"); - } - - code_ += " void add_{{FIELD_NAME}}({{FIELD_TYPE}}{{FIELD_NAME}}) {"; - code_ += " fbb_.{{ADD_FN}}(\\"; - if (is_scalar) { - code_ += "{{ADD_OFFSET}}, {{ADD_NAME}}, {{ADD_VALUE}});"; - } else { - code_ += "{{ADD_OFFSET}}, {{ADD_NAME}});"; - } - code_ += " }"; + // Generate accessor functions of the form: + // void add_name(type name) { + // fbb_.AddElement(offset, name, default); + // } + code_.SetValue("FIELD_NAME", Name(field)); + code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true)); + code_.SetValue("ADD_OFFSET", Name(struct_def) + "::" + offset); + code_.SetValue("ADD_NAME", name); + code_.SetValue("ADD_VALUE", value); + if (is_scalar) { + const auto type = GenTypeWire(field.value.type, "", false); + code_.SetValue("ADD_FN", "AddElement<" + type + ">"); + } else if (IsStruct(field.value.type)) { + code_.SetValue("ADD_FN", "AddStruct"); + } else { + code_.SetValue("ADD_FN", "AddOffset"); } + + code_ += " void add_{{FIELD_NAME}}({{FIELD_TYPE}}{{FIELD_NAME}}) {"; + code_ += " fbb_.{{ADD_FN}}(\\"; + if (is_default_scalar) { + code_ += "{{ADD_OFFSET}}, {{ADD_NAME}}, {{ADD_VALUE}});"; + } else { + code_ += "{{ADD_OFFSET}}, {{ADD_NAME}});"; + } + code_ += " }"; } // Builder constructor @@ -2307,7 +2333,13 @@ class CppGenerator : public BaseGenerator { if (!field.deprecated && (!struct_def.sortbysize || size == SizeOf(field.value.type.base_type))) { code_.SetValue("FIELD_NAME", Name(field)); - code_ += " builder_.add_{{FIELD_NAME}}({{FIELD_NAME}});"; + if (field.IsScalarOptional()) { + code_ += + " if({{FIELD_NAME}}) { " + "builder_.add_{{FIELD_NAME}}(*{{FIELD_NAME}}); }"; + } else { + code_ += " builder_.add_{{FIELD_NAME}}({{FIELD_NAME}});"; + } } } } diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 05b1b1942..088246fca 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -743,6 +743,34 @@ CheckedError Parser::ParseField(StructDef &struct_def) { return Error( "default values currently only supported for scalars in tables"); } + + // Mark the optional scalars. Note that a side effect of ParseSingleValue is + // fixing field->value.constant to null. + if (IsScalar(type.base_type)) { + field->optional = (field->value.constant == "null"); + if (field->optional) { + if (type.enum_def && type.enum_def->Lookup("null")) { + FLATBUFFERS_ASSERT(IsInteger(type.base_type)); + return Error( + "the default 'null' is reserved for declaring optional scalar " + "fields, it conflicts with declaration of enum '" + + type.enum_def->name + "'."); + } + if (field->attributes.Lookup("key")) { + return Error("only a non-optional scalar field can be used as a 'key' field"); + } + if (!SupportsOptionalScalars()) { + return Error( + "Optional scalars are not yet supported in at least one the of " + "the specified programming languages."); + } + } + } else { + // For nonscalars, only required fields are non-optional. + // At least until https://github.com/google/flatbuffers/issues/6053 + field->optional = !field->required; + } + // Append .0 if the value has not it (skip hex and scientific floats). // This suffix needed for generated C++ code. if (IsFloat(type.base_type)) { @@ -772,6 +800,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) { } else { // All unions should have the NONE ("0") enum value. auto in_enum = type.enum_def->attributes.Lookup("bit_flags") || + field->IsScalarOptional() || type.enum_def->FindByValue(field->value.constant); if (false == in_enum) return Error("default value of " + field->value.constant + @@ -833,17 +862,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) { if (field->required && (struct_def.fixed || IsScalar(type.base_type))) return Error("only non-scalar fields in tables may be 'required'"); - // Mark the optional scalars. Note that a side effect of ParseSingleValue is - // fixing field->value.constant to null. - if (IsScalar(type.base_type)) { - field->optional = (field->value.constant == "null"); - if (field->optional && !SupportsOptionalScalars()) { - return Error( - "Optional scalars are not yet supported in at least one the of " - "the specified programming languages." - ); - } - } else { + if(!IsScalar(type.base_type)) { // For nonscalars, only required fields are non-optional. // At least until https://github.com/google/flatbuffers/issues/6053 field->optional = !field->required; @@ -2260,11 +2279,17 @@ CheckedError Parser::CheckClash(std::vector &fields, return NoError(); } +bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts){ + static FLATBUFFERS_CONSTEXPR unsigned long supported_langs = + IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster | + IDLOptions::kKotlin | IDLOptions::kCpp; + unsigned long langs = opts.lang_to_generate; + return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs); +} bool Parser::SupportsOptionalScalars() const { - return !(opts.lang_to_generate & - ~(IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster | - IDLOptions::kKotlin)); + // Check in general if a language isn't specified. + return opts.lang_to_generate == 0 || SupportsOptionalScalars(opts); } bool Parser::SupportsAdvancedUnionFeatures() const { diff --git a/tests/BUILD b/tests/BUILD index f66d4142d..203a08cd9 100644 --- a/tests/BUILD +++ b/tests/BUILD @@ -20,6 +20,7 @@ cc_test( "test_builder.cpp", "test_builder.h", "union_vector/union_vector_generated.h", + "optional_scalars_generated.h", ], copts = [ "-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE", @@ -53,6 +54,7 @@ cc_test( ":unicode_test.json", ":union_vector/union_vector.fbs", ":union_vector/union_vector.json", + ":optional_scalars.fbs", ], includes = [ "", diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/optional_scalars_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/optional_scalars_generated.swift index 1d7dc97c1..7669a3fee 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/optional_scalars_generated.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/optional_scalars_generated.swift @@ -3,12 +3,25 @@ import FlatBuffers +public enum optional_scalars_OptionalByte: Int8, Enum { + public typealias T = Int8 + public static var byteSize: Int { return MemoryLayout.size } + public var value: Int8 { return self.rawValue } + case none_ = 0 + case one = 1 + + + public static var max: optional_scalars_OptionalByte { return .one } + public static var min: optional_scalars_OptionalByte { return .none_ } +} + public struct optional_scalars_ScalarStuff: FlatBufferObject { static func validateVersion() { FlatBuffersVersion_1_12_0() } public var __buffer: ByteBuffer! { return _accessor.bb } private var _accessor: Table + public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset, prefix: Bool = false) { fbb.finish(offset: end, fileId: "NULL", addPrefix: prefix) } public static func getRootAsScalarStuff(bb: ByteBuffer) -> optional_scalars_ScalarStuff { return optional_scalars_ScalarStuff(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) } private init(_ t: Table) { _accessor = t } @@ -48,6 +61,8 @@ public struct optional_scalars_ScalarStuff: FlatBufferObject { case justBool = 64 case maybeBool = 66 case defaultBool = 68 + case justEnum = 70 + case defaultEnum = 72 var v: Int32 { Int32(self.rawValue) } var p: VOffset { self.rawValue } } @@ -85,7 +100,9 @@ public struct optional_scalars_ScalarStuff: FlatBufferObject { public var justBool: Bool { let o = _accessor.offset(VTOFFSET.justBool.v); return o == 0 ? false : 0 != _accessor.readBuffer(of: Byte.self, at: o) } public var maybeBool: Bool? { let o = _accessor.offset(VTOFFSET.maybeBool.v); return o == 0 ? true : 0 != _accessor.readBuffer(of: Byte.self, at: o) } public var defaultBool: Bool { let o = _accessor.offset(VTOFFSET.defaultBool.v); return o == 0 ? true : 0 != _accessor.readBuffer(of: Byte.self, at: o) } - public static func startScalarStuff(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 33) } + public var justEnum: optional_scalars_OptionalByte { let o = _accessor.offset(VTOFFSET.justEnum.v); return o == 0 ? .none_ : optional_scalars_OptionalByte(rawValue: _accessor.readBuffer(of: Int8.self, at: o)) ?? .none_ } + public var defaultEnum: optional_scalars_OptionalByte { let o = _accessor.offset(VTOFFSET.defaultEnum.v); return o == 0 ? .one : optional_scalars_OptionalByte(rawValue: _accessor.readBuffer(of: Int8.self, at: o)) ?? .one } + public static func startScalarStuff(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 35) } public static func add(justI8: Int8, _ fbb: inout FlatBufferBuilder) { fbb.add(element: justI8, def: 0, at: VTOFFSET.justI8.p) } public static func add(maybeI8: Int8?, _ fbb: inout FlatBufferBuilder) { fbb.add(element: maybeI8, at: VTOFFSET.maybeI8.p) } public static func add(defaultI8: Int8, _ fbb: inout FlatBufferBuilder) { fbb.add(element: defaultI8, def: 42, at: VTOFFSET.defaultI8.p) } @@ -121,6 +138,8 @@ public struct optional_scalars_ScalarStuff: FlatBufferObject { public static func add(maybeBool: Bool?, _ fbb: inout FlatBufferBuilder) { fbb.add(element: maybeBool, at: VTOFFSET.maybeBool.p) } public static func add(defaultBool: Bool, _ fbb: inout FlatBufferBuilder) { fbb.add(element: defaultBool, def: true, at: VTOFFSET.defaultBool.p) } + public static func add(justEnum: optional_scalars_OptionalByte, _ fbb: inout FlatBufferBuilder) { fbb.add(element: justEnum.rawValue, def: 0, at: VTOFFSET.justEnum.p) } + public static func add(defaultEnum: optional_scalars_OptionalByte, _ fbb: inout FlatBufferBuilder) { fbb.add(element: defaultEnum.rawValue, def: 1, at: VTOFFSET.defaultEnum.p) } public static func endScalarStuff(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end } public static func createScalarStuff( _ fbb: inout FlatBufferBuilder, @@ -156,7 +175,9 @@ public struct optional_scalars_ScalarStuff: FlatBufferObject { defaultF64: Double = 42.0, justBool: Bool = false, maybeBool: Bool? = nil, - defaultBool: Bool = true + defaultBool: Bool = true, + justEnum: optional_scalars_OptionalByte = .none_, + defaultEnum: optional_scalars_OptionalByte = .one ) -> Offset { let __start = optional_scalars_ScalarStuff.startScalarStuff(&fbb) optional_scalars_ScalarStuff.add(justI8: justI8, &fbb) @@ -192,6 +213,8 @@ public struct optional_scalars_ScalarStuff: FlatBufferObject { optional_scalars_ScalarStuff.add(justBool: justBool, &fbb) optional_scalars_ScalarStuff.add(maybeBool: maybeBool, &fbb) optional_scalars_ScalarStuff.add(defaultBool: defaultBool, &fbb) + optional_scalars_ScalarStuff.add(justEnum: justEnum, &fbb) + optional_scalars_ScalarStuff.add(defaultEnum: defaultEnum, &fbb) return optional_scalars_ScalarStuff.endScalarStuff(&fbb, start: __start) } } diff --git a/tests/cpp17/generated_cpp17/optional_scalars_generated.h b/tests/cpp17/generated_cpp17/optional_scalars_generated.h new file mode 100644 index 000000000..cc879137c --- /dev/null +++ b/tests/cpp17/generated_cpp17/optional_scalars_generated.h @@ -0,0 +1,878 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_OPTIONALSCALARS_OPTIONAL_SCALARS_H_ +#define FLATBUFFERS_GENERATED_OPTIONALSCALARS_OPTIONAL_SCALARS_H_ + +#include "flatbuffers/flatbuffers.h" + +namespace optional_scalars { + +struct ScalarStuff; +struct ScalarStuffBuilder; +struct ScalarStuffT; + +inline const flatbuffers::TypeTable *ScalarStuffTypeTable(); + +enum class OptionalByte : int8_t { + None = 0, + One = 1, + MIN = None, + MAX = One +}; + +inline const OptionalByte (&EnumValuesOptionalByte())[2] { + static const OptionalByte values[] = { + OptionalByte::None, + OptionalByte::One + }; + return values; +} + +inline const char * const *EnumNamesOptionalByte() { + static const char * const names[3] = { + "None", + "One", + nullptr + }; + return names; +} + +inline const char *EnumNameOptionalByte(OptionalByte e) { + if (flatbuffers::IsOutRange(e, OptionalByte::None, OptionalByte::One)) return ""; + const size_t index = static_cast(e); + return EnumNamesOptionalByte()[index]; +} + +struct ScalarStuffT : public flatbuffers::NativeTable { + typedef ScalarStuff TableType; + int8_t just_i8 = 0; + flatbuffers::Optional maybe_i8 = flatbuffers::nullopt; + int8_t default_i8 = 42; + uint8_t just_u8 = 0; + flatbuffers::Optional maybe_u8 = flatbuffers::nullopt; + uint8_t default_u8 = 42; + int16_t just_i16 = 0; + flatbuffers::Optional maybe_i16 = flatbuffers::nullopt; + int16_t default_i16 = 42; + uint16_t just_u16 = 0; + flatbuffers::Optional maybe_u16 = flatbuffers::nullopt; + uint16_t default_u16 = 42; + int32_t just_i32 = 0; + flatbuffers::Optional maybe_i32 = flatbuffers::nullopt; + int32_t default_i32 = 42; + uint32_t just_u32 = 0; + flatbuffers::Optional maybe_u32 = flatbuffers::nullopt; + uint32_t default_u32 = 42; + int64_t just_i64 = 0; + flatbuffers::Optional maybe_i64 = flatbuffers::nullopt; + int64_t default_i64 = 42LL; + uint64_t just_u64 = 0; + flatbuffers::Optional maybe_u64 = flatbuffers::nullopt; + uint64_t default_u64 = 42ULL; + float just_f32 = 0.0f; + flatbuffers::Optional maybe_f32 = flatbuffers::nullopt; + float default_f32 = 42.0f; + double just_f64 = 0.0; + flatbuffers::Optional maybe_f64 = flatbuffers::nullopt; + double default_f64 = 42.0; + bool just_bool = false; + flatbuffers::Optional maybe_bool = true; + bool default_bool = true; + optional_scalars::OptionalByte just_enum = optional_scalars::OptionalByte::None; + optional_scalars::OptionalByte default_enum = optional_scalars::OptionalByte::One; +}; + +struct ScalarStuff FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ScalarStuffT NativeTableType; + typedef ScalarStuffBuilder Builder; + struct Traits; + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return ScalarStuffTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_JUST_I8 = 4, + VT_MAYBE_I8 = 6, + VT_DEFAULT_I8 = 8, + VT_JUST_U8 = 10, + VT_MAYBE_U8 = 12, + VT_DEFAULT_U8 = 14, + VT_JUST_I16 = 16, + VT_MAYBE_I16 = 18, + VT_DEFAULT_I16 = 20, + VT_JUST_U16 = 22, + VT_MAYBE_U16 = 24, + VT_DEFAULT_U16 = 26, + VT_JUST_I32 = 28, + VT_MAYBE_I32 = 30, + VT_DEFAULT_I32 = 32, + VT_JUST_U32 = 34, + VT_MAYBE_U32 = 36, + VT_DEFAULT_U32 = 38, + VT_JUST_I64 = 40, + VT_MAYBE_I64 = 42, + VT_DEFAULT_I64 = 44, + VT_JUST_U64 = 46, + VT_MAYBE_U64 = 48, + VT_DEFAULT_U64 = 50, + VT_JUST_F32 = 52, + VT_MAYBE_F32 = 54, + VT_DEFAULT_F32 = 56, + VT_JUST_F64 = 58, + VT_MAYBE_F64 = 60, + VT_DEFAULT_F64 = 62, + VT_JUST_BOOL = 64, + VT_MAYBE_BOOL = 66, + VT_DEFAULT_BOOL = 68, + VT_JUST_ENUM = 70, + VT_DEFAULT_ENUM = 72 + }; + int8_t just_i8() const { + return GetField(VT_JUST_I8, 0); + } + bool mutate_just_i8(int8_t _just_i8) { + return SetField(VT_JUST_I8, _just_i8, 0); + } + flatbuffers::Optional maybe_i8() const { + return GetOptional(VT_MAYBE_I8); + } + bool mutate_maybe_i8(int8_t _maybe_i8) { + return SetField(VT_MAYBE_I8, _maybe_i8); + } + int8_t default_i8() const { + return GetField(VT_DEFAULT_I8, 42); + } + bool mutate_default_i8(int8_t _default_i8) { + return SetField(VT_DEFAULT_I8, _default_i8, 42); + } + uint8_t just_u8() const { + return GetField(VT_JUST_U8, 0); + } + bool mutate_just_u8(uint8_t _just_u8) { + return SetField(VT_JUST_U8, _just_u8, 0); + } + flatbuffers::Optional maybe_u8() const { + return GetOptional(VT_MAYBE_U8); + } + bool mutate_maybe_u8(uint8_t _maybe_u8) { + return SetField(VT_MAYBE_U8, _maybe_u8); + } + uint8_t default_u8() const { + return GetField(VT_DEFAULT_U8, 42); + } + bool mutate_default_u8(uint8_t _default_u8) { + return SetField(VT_DEFAULT_U8, _default_u8, 42); + } + int16_t just_i16() const { + return GetField(VT_JUST_I16, 0); + } + bool mutate_just_i16(int16_t _just_i16) { + return SetField(VT_JUST_I16, _just_i16, 0); + } + flatbuffers::Optional maybe_i16() const { + return GetOptional(VT_MAYBE_I16); + } + bool mutate_maybe_i16(int16_t _maybe_i16) { + return SetField(VT_MAYBE_I16, _maybe_i16); + } + int16_t default_i16() const { + return GetField(VT_DEFAULT_I16, 42); + } + bool mutate_default_i16(int16_t _default_i16) { + return SetField(VT_DEFAULT_I16, _default_i16, 42); + } + uint16_t just_u16() const { + return GetField(VT_JUST_U16, 0); + } + bool mutate_just_u16(uint16_t _just_u16) { + return SetField(VT_JUST_U16, _just_u16, 0); + } + flatbuffers::Optional maybe_u16() const { + return GetOptional(VT_MAYBE_U16); + } + bool mutate_maybe_u16(uint16_t _maybe_u16) { + return SetField(VT_MAYBE_U16, _maybe_u16); + } + uint16_t default_u16() const { + return GetField(VT_DEFAULT_U16, 42); + } + bool mutate_default_u16(uint16_t _default_u16) { + return SetField(VT_DEFAULT_U16, _default_u16, 42); + } + int32_t just_i32() const { + return GetField(VT_JUST_I32, 0); + } + bool mutate_just_i32(int32_t _just_i32) { + return SetField(VT_JUST_I32, _just_i32, 0); + } + flatbuffers::Optional maybe_i32() const { + return GetOptional(VT_MAYBE_I32); + } + bool mutate_maybe_i32(int32_t _maybe_i32) { + return SetField(VT_MAYBE_I32, _maybe_i32); + } + int32_t default_i32() const { + return GetField(VT_DEFAULT_I32, 42); + } + bool mutate_default_i32(int32_t _default_i32) { + return SetField(VT_DEFAULT_I32, _default_i32, 42); + } + uint32_t just_u32() const { + return GetField(VT_JUST_U32, 0); + } + bool mutate_just_u32(uint32_t _just_u32) { + return SetField(VT_JUST_U32, _just_u32, 0); + } + flatbuffers::Optional maybe_u32() const { + return GetOptional(VT_MAYBE_U32); + } + bool mutate_maybe_u32(uint32_t _maybe_u32) { + return SetField(VT_MAYBE_U32, _maybe_u32); + } + uint32_t default_u32() const { + return GetField(VT_DEFAULT_U32, 42); + } + bool mutate_default_u32(uint32_t _default_u32) { + return SetField(VT_DEFAULT_U32, _default_u32, 42); + } + int64_t just_i64() const { + return GetField(VT_JUST_I64, 0); + } + bool mutate_just_i64(int64_t _just_i64) { + return SetField(VT_JUST_I64, _just_i64, 0); + } + flatbuffers::Optional maybe_i64() const { + return GetOptional(VT_MAYBE_I64); + } + bool mutate_maybe_i64(int64_t _maybe_i64) { + return SetField(VT_MAYBE_I64, _maybe_i64); + } + int64_t default_i64() const { + return GetField(VT_DEFAULT_I64, 42LL); + } + bool mutate_default_i64(int64_t _default_i64) { + return SetField(VT_DEFAULT_I64, _default_i64, 42LL); + } + uint64_t just_u64() const { + return GetField(VT_JUST_U64, 0); + } + bool mutate_just_u64(uint64_t _just_u64) { + return SetField(VT_JUST_U64, _just_u64, 0); + } + flatbuffers::Optional maybe_u64() const { + return GetOptional(VT_MAYBE_U64); + } + bool mutate_maybe_u64(uint64_t _maybe_u64) { + return SetField(VT_MAYBE_U64, _maybe_u64); + } + uint64_t default_u64() const { + return GetField(VT_DEFAULT_U64, 42ULL); + } + bool mutate_default_u64(uint64_t _default_u64) { + return SetField(VT_DEFAULT_U64, _default_u64, 42ULL); + } + float just_f32() const { + return GetField(VT_JUST_F32, 0.0f); + } + bool mutate_just_f32(float _just_f32) { + return SetField(VT_JUST_F32, _just_f32, 0.0f); + } + flatbuffers::Optional maybe_f32() const { + return GetOptional(VT_MAYBE_F32); + } + bool mutate_maybe_f32(float _maybe_f32) { + return SetField(VT_MAYBE_F32, _maybe_f32); + } + float default_f32() const { + return GetField(VT_DEFAULT_F32, 42.0f); + } + bool mutate_default_f32(float _default_f32) { + return SetField(VT_DEFAULT_F32, _default_f32, 42.0f); + } + double just_f64() const { + return GetField(VT_JUST_F64, 0.0); + } + bool mutate_just_f64(double _just_f64) { + return SetField(VT_JUST_F64, _just_f64, 0.0); + } + flatbuffers::Optional maybe_f64() const { + return GetOptional(VT_MAYBE_F64); + } + bool mutate_maybe_f64(double _maybe_f64) { + return SetField(VT_MAYBE_F64, _maybe_f64); + } + double default_f64() const { + return GetField(VT_DEFAULT_F64, 42.0); + } + bool mutate_default_f64(double _default_f64) { + return SetField(VT_DEFAULT_F64, _default_f64, 42.0); + } + bool just_bool() const { + return GetField(VT_JUST_BOOL, 0) != 0; + } + bool mutate_just_bool(bool _just_bool) { + return SetField(VT_JUST_BOOL, static_cast(_just_bool), 0); + } + flatbuffers::Optional maybe_bool() const { + return GetOptional(VT_MAYBE_BOOL); + } + bool mutate_maybe_bool(bool _maybe_bool) { + return SetField(VT_MAYBE_BOOL, static_cast(_maybe_bool)); + } + bool default_bool() const { + return GetField(VT_DEFAULT_BOOL, 1) != 0; + } + bool mutate_default_bool(bool _default_bool) { + return SetField(VT_DEFAULT_BOOL, static_cast(_default_bool), 1); + } + optional_scalars::OptionalByte just_enum() const { + return static_cast(GetField(VT_JUST_ENUM, 0)); + } + bool mutate_just_enum(optional_scalars::OptionalByte _just_enum) { + return SetField(VT_JUST_ENUM, static_cast(_just_enum), 0); + } + optional_scalars::OptionalByte default_enum() const { + return static_cast(GetField(VT_DEFAULT_ENUM, 1)); + } + bool mutate_default_enum(optional_scalars::OptionalByte _default_enum) { + return SetField(VT_DEFAULT_ENUM, static_cast(_default_enum), 1); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_JUST_I8) && + VerifyField(verifier, VT_MAYBE_I8) && + VerifyField(verifier, VT_DEFAULT_I8) && + VerifyField(verifier, VT_JUST_U8) && + VerifyField(verifier, VT_MAYBE_U8) && + VerifyField(verifier, VT_DEFAULT_U8) && + VerifyField(verifier, VT_JUST_I16) && + VerifyField(verifier, VT_MAYBE_I16) && + VerifyField(verifier, VT_DEFAULT_I16) && + VerifyField(verifier, VT_JUST_U16) && + VerifyField(verifier, VT_MAYBE_U16) && + VerifyField(verifier, VT_DEFAULT_U16) && + VerifyField(verifier, VT_JUST_I32) && + VerifyField(verifier, VT_MAYBE_I32) && + VerifyField(verifier, VT_DEFAULT_I32) && + VerifyField(verifier, VT_JUST_U32) && + VerifyField(verifier, VT_MAYBE_U32) && + VerifyField(verifier, VT_DEFAULT_U32) && + VerifyField(verifier, VT_JUST_I64) && + VerifyField(verifier, VT_MAYBE_I64) && + VerifyField(verifier, VT_DEFAULT_I64) && + VerifyField(verifier, VT_JUST_U64) && + VerifyField(verifier, VT_MAYBE_U64) && + VerifyField(verifier, VT_DEFAULT_U64) && + VerifyField(verifier, VT_JUST_F32) && + VerifyField(verifier, VT_MAYBE_F32) && + VerifyField(verifier, VT_DEFAULT_F32) && + VerifyField(verifier, VT_JUST_F64) && + VerifyField(verifier, VT_MAYBE_F64) && + VerifyField(verifier, VT_DEFAULT_F64) && + VerifyField(verifier, VT_JUST_BOOL) && + VerifyField(verifier, VT_MAYBE_BOOL) && + VerifyField(verifier, VT_DEFAULT_BOOL) && + VerifyField(verifier, VT_JUST_ENUM) && + VerifyField(verifier, VT_DEFAULT_ENUM) && + verifier.EndTable(); + } + ScalarStuffT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ScalarStuffT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ScalarStuffT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ScalarStuffBuilder { + typedef ScalarStuff Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_just_i8(int8_t just_i8) { + fbb_.AddElement(ScalarStuff::VT_JUST_I8, just_i8, 0); + } + void add_maybe_i8(int8_t maybe_i8) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_I8, maybe_i8); + } + void add_default_i8(int8_t default_i8) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_I8, default_i8, 42); + } + void add_just_u8(uint8_t just_u8) { + fbb_.AddElement(ScalarStuff::VT_JUST_U8, just_u8, 0); + } + void add_maybe_u8(uint8_t maybe_u8) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_U8, maybe_u8); + } + void add_default_u8(uint8_t default_u8) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_U8, default_u8, 42); + } + void add_just_i16(int16_t just_i16) { + fbb_.AddElement(ScalarStuff::VT_JUST_I16, just_i16, 0); + } + void add_maybe_i16(int16_t maybe_i16) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_I16, maybe_i16); + } + void add_default_i16(int16_t default_i16) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_I16, default_i16, 42); + } + void add_just_u16(uint16_t just_u16) { + fbb_.AddElement(ScalarStuff::VT_JUST_U16, just_u16, 0); + } + void add_maybe_u16(uint16_t maybe_u16) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_U16, maybe_u16); + } + void add_default_u16(uint16_t default_u16) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_U16, default_u16, 42); + } + void add_just_i32(int32_t just_i32) { + fbb_.AddElement(ScalarStuff::VT_JUST_I32, just_i32, 0); + } + void add_maybe_i32(int32_t maybe_i32) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_I32, maybe_i32); + } + void add_default_i32(int32_t default_i32) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_I32, default_i32, 42); + } + void add_just_u32(uint32_t just_u32) { + fbb_.AddElement(ScalarStuff::VT_JUST_U32, just_u32, 0); + } + void add_maybe_u32(uint32_t maybe_u32) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_U32, maybe_u32); + } + void add_default_u32(uint32_t default_u32) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_U32, default_u32, 42); + } + void add_just_i64(int64_t just_i64) { + fbb_.AddElement(ScalarStuff::VT_JUST_I64, just_i64, 0); + } + void add_maybe_i64(int64_t maybe_i64) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_I64, maybe_i64); + } + void add_default_i64(int64_t default_i64) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_I64, default_i64, 42LL); + } + void add_just_u64(uint64_t just_u64) { + fbb_.AddElement(ScalarStuff::VT_JUST_U64, just_u64, 0); + } + void add_maybe_u64(uint64_t maybe_u64) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_U64, maybe_u64); + } + void add_default_u64(uint64_t default_u64) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_U64, default_u64, 42ULL); + } + void add_just_f32(float just_f32) { + fbb_.AddElement(ScalarStuff::VT_JUST_F32, just_f32, 0.0f); + } + void add_maybe_f32(float maybe_f32) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_F32, maybe_f32); + } + void add_default_f32(float default_f32) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_F32, default_f32, 42.0f); + } + void add_just_f64(double just_f64) { + fbb_.AddElement(ScalarStuff::VT_JUST_F64, just_f64, 0.0); + } + void add_maybe_f64(double maybe_f64) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_F64, maybe_f64); + } + void add_default_f64(double default_f64) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_F64, default_f64, 42.0); + } + void add_just_bool(bool just_bool) { + fbb_.AddElement(ScalarStuff::VT_JUST_BOOL, static_cast(just_bool), 0); + } + void add_maybe_bool(bool maybe_bool) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_BOOL, static_cast(maybe_bool)); + } + void add_default_bool(bool default_bool) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_BOOL, static_cast(default_bool), 1); + } + void add_just_enum(optional_scalars::OptionalByte just_enum) { + fbb_.AddElement(ScalarStuff::VT_JUST_ENUM, static_cast(just_enum), 0); + } + void add_default_enum(optional_scalars::OptionalByte default_enum) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_ENUM, static_cast(default_enum), 1); + } + explicit ScalarStuffBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateScalarStuff( + flatbuffers::FlatBufferBuilder &_fbb, + int8_t just_i8 = 0, + flatbuffers::Optionalmaybe_i8 = flatbuffers::nullopt, + int8_t default_i8 = 42, + uint8_t just_u8 = 0, + flatbuffers::Optionalmaybe_u8 = flatbuffers::nullopt, + uint8_t default_u8 = 42, + int16_t just_i16 = 0, + flatbuffers::Optionalmaybe_i16 = flatbuffers::nullopt, + int16_t default_i16 = 42, + uint16_t just_u16 = 0, + flatbuffers::Optionalmaybe_u16 = flatbuffers::nullopt, + uint16_t default_u16 = 42, + int32_t just_i32 = 0, + flatbuffers::Optionalmaybe_i32 = flatbuffers::nullopt, + int32_t default_i32 = 42, + uint32_t just_u32 = 0, + flatbuffers::Optionalmaybe_u32 = flatbuffers::nullopt, + uint32_t default_u32 = 42, + int64_t just_i64 = 0, + flatbuffers::Optionalmaybe_i64 = flatbuffers::nullopt, + int64_t default_i64 = 42LL, + uint64_t just_u64 = 0, + flatbuffers::Optionalmaybe_u64 = flatbuffers::nullopt, + uint64_t default_u64 = 42ULL, + float just_f32 = 0.0f, + flatbuffers::Optionalmaybe_f32 = flatbuffers::nullopt, + float default_f32 = 42.0f, + double just_f64 = 0.0, + flatbuffers::Optionalmaybe_f64 = flatbuffers::nullopt, + double default_f64 = 42.0, + bool just_bool = false, + flatbuffers::Optionalmaybe_bool = flatbuffers::nullopt, + bool default_bool = true, + optional_scalars::OptionalByte just_enum = optional_scalars::OptionalByte::None, + optional_scalars::OptionalByte default_enum = optional_scalars::OptionalByte::One) { + ScalarStuffBuilder builder_(_fbb); + builder_.add_default_f64(default_f64); + if(maybe_f64) { builder_.add_maybe_f64(*maybe_f64); } + builder_.add_just_f64(just_f64); + builder_.add_default_u64(default_u64); + if(maybe_u64) { builder_.add_maybe_u64(*maybe_u64); } + builder_.add_just_u64(just_u64); + builder_.add_default_i64(default_i64); + if(maybe_i64) { builder_.add_maybe_i64(*maybe_i64); } + builder_.add_just_i64(just_i64); + builder_.add_default_f32(default_f32); + if(maybe_f32) { builder_.add_maybe_f32(*maybe_f32); } + builder_.add_just_f32(just_f32); + builder_.add_default_u32(default_u32); + if(maybe_u32) { builder_.add_maybe_u32(*maybe_u32); } + builder_.add_just_u32(just_u32); + builder_.add_default_i32(default_i32); + if(maybe_i32) { builder_.add_maybe_i32(*maybe_i32); } + builder_.add_just_i32(just_i32); + builder_.add_default_u16(default_u16); + if(maybe_u16) { builder_.add_maybe_u16(*maybe_u16); } + builder_.add_just_u16(just_u16); + builder_.add_default_i16(default_i16); + if(maybe_i16) { builder_.add_maybe_i16(*maybe_i16); } + builder_.add_just_i16(just_i16); + builder_.add_default_enum(default_enum); + builder_.add_just_enum(just_enum); + builder_.add_default_bool(default_bool); + if(maybe_bool) { builder_.add_maybe_bool(*maybe_bool); } + builder_.add_just_bool(just_bool); + builder_.add_default_u8(default_u8); + if(maybe_u8) { builder_.add_maybe_u8(*maybe_u8); } + builder_.add_just_u8(just_u8); + builder_.add_default_i8(default_i8); + if(maybe_i8) { builder_.add_maybe_i8(*maybe_i8); } + builder_.add_just_i8(just_i8); + return builder_.Finish(); +} + +struct ScalarStuff::Traits { + using type = ScalarStuff; + static auto constexpr Create = CreateScalarStuff; +}; + +flatbuffers::Offset CreateScalarStuff(flatbuffers::FlatBufferBuilder &_fbb, const ScalarStuffT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +inline ScalarStuffT *ScalarStuff::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::make_unique(); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ScalarStuff::UnPackTo(ScalarStuffT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = just_i8(); _o->just_i8 = _e; } + { auto _e = maybe_i8(); _o->maybe_i8 = _e; } + { auto _e = default_i8(); _o->default_i8 = _e; } + { auto _e = just_u8(); _o->just_u8 = _e; } + { auto _e = maybe_u8(); _o->maybe_u8 = _e; } + { auto _e = default_u8(); _o->default_u8 = _e; } + { auto _e = just_i16(); _o->just_i16 = _e; } + { auto _e = maybe_i16(); _o->maybe_i16 = _e; } + { auto _e = default_i16(); _o->default_i16 = _e; } + { auto _e = just_u16(); _o->just_u16 = _e; } + { auto _e = maybe_u16(); _o->maybe_u16 = _e; } + { auto _e = default_u16(); _o->default_u16 = _e; } + { auto _e = just_i32(); _o->just_i32 = _e; } + { auto _e = maybe_i32(); _o->maybe_i32 = _e; } + { auto _e = default_i32(); _o->default_i32 = _e; } + { auto _e = just_u32(); _o->just_u32 = _e; } + { auto _e = maybe_u32(); _o->maybe_u32 = _e; } + { auto _e = default_u32(); _o->default_u32 = _e; } + { auto _e = just_i64(); _o->just_i64 = _e; } + { auto _e = maybe_i64(); _o->maybe_i64 = _e; } + { auto _e = default_i64(); _o->default_i64 = _e; } + { auto _e = just_u64(); _o->just_u64 = _e; } + { auto _e = maybe_u64(); _o->maybe_u64 = _e; } + { auto _e = default_u64(); _o->default_u64 = _e; } + { auto _e = just_f32(); _o->just_f32 = _e; } + { auto _e = maybe_f32(); _o->maybe_f32 = _e; } + { auto _e = default_f32(); _o->default_f32 = _e; } + { auto _e = just_f64(); _o->just_f64 = _e; } + { auto _e = maybe_f64(); _o->maybe_f64 = _e; } + { auto _e = default_f64(); _o->default_f64 = _e; } + { auto _e = just_bool(); _o->just_bool = _e; } + { auto _e = maybe_bool(); _o->maybe_bool = _e; } + { auto _e = default_bool(); _o->default_bool = _e; } + { auto _e = just_enum(); _o->just_enum = _e; } + { auto _e = default_enum(); _o->default_enum = _e; } +} + +inline flatbuffers::Offset ScalarStuff::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ScalarStuffT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateScalarStuff(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateScalarStuff(flatbuffers::FlatBufferBuilder &_fbb, const ScalarStuffT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ScalarStuffT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _just_i8 = _o->just_i8; + auto _maybe_i8 = _o->maybe_i8; + auto _default_i8 = _o->default_i8; + auto _just_u8 = _o->just_u8; + auto _maybe_u8 = _o->maybe_u8; + auto _default_u8 = _o->default_u8; + auto _just_i16 = _o->just_i16; + auto _maybe_i16 = _o->maybe_i16; + auto _default_i16 = _o->default_i16; + auto _just_u16 = _o->just_u16; + auto _maybe_u16 = _o->maybe_u16; + auto _default_u16 = _o->default_u16; + auto _just_i32 = _o->just_i32; + auto _maybe_i32 = _o->maybe_i32; + auto _default_i32 = _o->default_i32; + auto _just_u32 = _o->just_u32; + auto _maybe_u32 = _o->maybe_u32; + auto _default_u32 = _o->default_u32; + auto _just_i64 = _o->just_i64; + auto _maybe_i64 = _o->maybe_i64; + auto _default_i64 = _o->default_i64; + auto _just_u64 = _o->just_u64; + auto _maybe_u64 = _o->maybe_u64; + auto _default_u64 = _o->default_u64; + auto _just_f32 = _o->just_f32; + auto _maybe_f32 = _o->maybe_f32; + auto _default_f32 = _o->default_f32; + auto _just_f64 = _o->just_f64; + auto _maybe_f64 = _o->maybe_f64; + auto _default_f64 = _o->default_f64; + auto _just_bool = _o->just_bool; + auto _maybe_bool = _o->maybe_bool; + auto _default_bool = _o->default_bool; + auto _just_enum = _o->just_enum; + auto _default_enum = _o->default_enum; + return optional_scalars::CreateScalarStuff( + _fbb, + _just_i8, + _maybe_i8, + _default_i8, + _just_u8, + _maybe_u8, + _default_u8, + _just_i16, + _maybe_i16, + _default_i16, + _just_u16, + _maybe_u16, + _default_u16, + _just_i32, + _maybe_i32, + _default_i32, + _just_u32, + _maybe_u32, + _default_u32, + _just_i64, + _maybe_i64, + _default_i64, + _just_u64, + _maybe_u64, + _default_u64, + _just_f32, + _maybe_f32, + _default_f32, + _just_f64, + _maybe_f64, + _default_f64, + _just_bool, + _maybe_bool, + _default_bool, + _just_enum, + _default_enum); +} + +inline const flatbuffers::TypeTable *OptionalByteTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_CHAR, 0, 0 }, + { flatbuffers::ET_CHAR, 0, 0 } + }; + static const flatbuffers::TypeFunction type_refs[] = { + optional_scalars::OptionalByteTypeTable + }; + static const char * const names[] = { + "None", + "One" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_ENUM, 2, type_codes, type_refs, nullptr, names + }; + return &tt; +} + +inline const flatbuffers::TypeTable *ScalarStuffTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_CHAR, 0, -1 }, + { flatbuffers::ET_CHAR, 0, -1 }, + { flatbuffers::ET_CHAR, 0, -1 }, + { flatbuffers::ET_UCHAR, 0, -1 }, + { flatbuffers::ET_UCHAR, 0, -1 }, + { flatbuffers::ET_UCHAR, 0, -1 }, + { flatbuffers::ET_SHORT, 0, -1 }, + { flatbuffers::ET_SHORT, 0, -1 }, + { flatbuffers::ET_SHORT, 0, -1 }, + { flatbuffers::ET_USHORT, 0, -1 }, + { flatbuffers::ET_USHORT, 0, -1 }, + { flatbuffers::ET_USHORT, 0, -1 }, + { flatbuffers::ET_INT, 0, -1 }, + { flatbuffers::ET_INT, 0, -1 }, + { flatbuffers::ET_INT, 0, -1 }, + { flatbuffers::ET_UINT, 0, -1 }, + { flatbuffers::ET_UINT, 0, -1 }, + { flatbuffers::ET_UINT, 0, -1 }, + { flatbuffers::ET_LONG, 0, -1 }, + { flatbuffers::ET_LONG, 0, -1 }, + { flatbuffers::ET_LONG, 0, -1 }, + { flatbuffers::ET_ULONG, 0, -1 }, + { flatbuffers::ET_ULONG, 0, -1 }, + { flatbuffers::ET_ULONG, 0, -1 }, + { flatbuffers::ET_FLOAT, 0, -1 }, + { flatbuffers::ET_FLOAT, 0, -1 }, + { flatbuffers::ET_FLOAT, 0, -1 }, + { flatbuffers::ET_DOUBLE, 0, -1 }, + { flatbuffers::ET_DOUBLE, 0, -1 }, + { flatbuffers::ET_DOUBLE, 0, -1 }, + { flatbuffers::ET_BOOL, 0, -1 }, + { flatbuffers::ET_BOOL, 0, -1 }, + { flatbuffers::ET_BOOL, 0, -1 }, + { flatbuffers::ET_CHAR, 0, 0 }, + { flatbuffers::ET_CHAR, 0, 0 } + }; + static const flatbuffers::TypeFunction type_refs[] = { + optional_scalars::OptionalByteTypeTable + }; + static const char * const names[] = { + "just_i8", + "maybe_i8", + "default_i8", + "just_u8", + "maybe_u8", + "default_u8", + "just_i16", + "maybe_i16", + "default_i16", + "just_u16", + "maybe_u16", + "default_u16", + "just_i32", + "maybe_i32", + "default_i32", + "just_u32", + "maybe_u32", + "default_u32", + "just_i64", + "maybe_i64", + "default_i64", + "just_u64", + "maybe_u64", + "default_u64", + "just_f32", + "maybe_f32", + "default_f32", + "just_f64", + "maybe_f64", + "default_f64", + "just_bool", + "maybe_bool", + "default_bool", + "just_enum", + "default_enum" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_TABLE, 35, type_codes, type_refs, nullptr, names + }; + return &tt; +} + +inline const optional_scalars::ScalarStuff *GetScalarStuff(const void *buf) { + return flatbuffers::GetRoot(buf); +} + +inline const optional_scalars::ScalarStuff *GetSizePrefixedScalarStuff(const void *buf) { + return flatbuffers::GetSizePrefixedRoot(buf); +} + +inline ScalarStuff *GetMutableScalarStuff(void *buf) { + return flatbuffers::GetMutableRoot(buf); +} + +inline const char *ScalarStuffIdentifier() { + return "NULL"; +} + +inline bool ScalarStuffBufferHasIdentifier(const void *buf) { + return flatbuffers::BufferHasIdentifier( + buf, ScalarStuffIdentifier()); +} + +inline bool VerifyScalarStuffBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer(ScalarStuffIdentifier()); +} + +inline bool VerifySizePrefixedScalarStuffBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer(ScalarStuffIdentifier()); +} + +inline const char *ScalarStuffExtension() { + return "mon"; +} + +inline void FinishScalarStuffBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.Finish(root, ScalarStuffIdentifier()); +} + +inline void FinishSizePrefixedScalarStuffBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root, ScalarStuffIdentifier()); +} + +inline std::unique_ptr UnPackScalarStuff( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr(GetScalarStuff(buf)->UnPack(res)); +} + +inline std::unique_ptr UnPackSizePrefixedScalarStuff( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr(GetSizePrefixedScalarStuff(buf)->UnPack(res)); +} + +} // namespace optional_scalars + +#endif // FLATBUFFERS_GENERATED_OPTIONALSCALARS_OPTIONAL_SCALARS_H_ diff --git a/tests/cpp17/test_cpp17.cpp b/tests/cpp17/test_cpp17.cpp index 91390bda9..9b47c10a7 100644 --- a/tests/cpp17/test_cpp17.cpp +++ b/tests/cpp17/test_cpp17.cpp @@ -30,10 +30,12 @@ // Embed generated code into an isolated namespace. namespace cpp17 { #include "generated_cpp17/monster_test_generated.h" +#include "generated_cpp17/optional_scalars_generated.h" } // namespace cpp17 namespace cpp11 { #include "../monster_test_generated.h" +#include "../optional_scalars_generated.h" } // namespace cpp11 void CreateTableByTypeTest() { @@ -59,8 +61,50 @@ void CreateTableByTypeTest() { TEST_EQ(stat->count(), 7); } +void OptionalScalarsTest() { + static_assert(std::is_same, std::optional>::value); + static_assert(std::is_same::value); + + // test C++ nullable + flatbuffers::FlatBufferBuilder fbb; + FinishScalarStuffBuffer(fbb, cpp17::optional_scalars::CreateScalarStuff( + fbb, 1, static_cast(2))); + auto opts = + cpp17::optional_scalars::GetMutableScalarStuff(fbb.GetBufferPointer()); + TEST_ASSERT(!opts->maybe_bool()); + TEST_ASSERT(!opts->maybe_f32().has_value()); + TEST_ASSERT(opts->maybe_i8().has_value()); + TEST_EQ(opts->maybe_i8().value(), 2); + TEST_ASSERT(opts->mutate_maybe_i8(3)); + TEST_ASSERT(opts->maybe_i8().has_value()); + TEST_EQ(opts->maybe_i8().value(), 3); + TEST_ASSERT(!opts->mutate_maybe_i16(-10)); + + cpp17::optional_scalars::ScalarStuffT obj; + opts->UnPackTo(&obj); + TEST_ASSERT(!obj.maybe_bool); + TEST_ASSERT(!obj.maybe_f32.has_value()); + TEST_ASSERT(obj.maybe_i8.has_value() && obj.maybe_i8.value() == 3); + TEST_ASSERT(obj.maybe_i8 && *obj.maybe_i8 == 3); + obj.maybe_i32 = -1; + + fbb.Clear(); + FinishScalarStuffBuffer( + fbb, cpp17::optional_scalars::ScalarStuff::Pack(fbb, &obj)); + opts = cpp17::optional_scalars::GetMutableScalarStuff(fbb.GetBufferPointer()); + TEST_ASSERT(opts->maybe_i8().has_value()); + TEST_EQ(opts->maybe_i8().value(), 3); + TEST_ASSERT(opts->maybe_i32().has_value()); + TEST_EQ(opts->maybe_i32().value(), -1); + + TEST_EQ(std::optional(opts->maybe_i32()).value(), -1); + TEST_EQ(std::optional(opts->maybe_i32()).value(), -1); + TEST_ASSERT(opts->maybe_i32() == std::optional(-1)); +} + int FlatBufferCpp17Tests() { CreateTableByTypeTest(); + OptionalScalarsTest(); return 0; } diff --git a/tests/generate_code.bat b/tests/generate_code.bat index e9518c389..33e71680e 100644 --- a/tests/generate_code.bat +++ b/tests/generate_code.bat @@ -56,6 +56,7 @@ set TEST_NOINCL_FLAGS=%TEST_BASE_FLAGS% --no-includes --no-fb-import @rem Generate the optional scalar code for tests. ..\%buildtype%\flatc.exe --rust --lobster optional_scalars.fbs || goto FAIL +..\%buildtype%\flatc.exe %TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% --cpp optional_scalars.fbs || goto FAIL @rem Generate the schema evolution tests ..\%buildtype%\flatc.exe --cpp --scoped-enums %TEST_CPP_FLAGS% -o evolution_test ./evolution_test/evolution_v1.fbs ./evolution_test/evolution_v2.fbs || goto FAIL @@ -72,6 +73,7 @@ set TEST_CPP17_FLAGS=--cpp --cpp-std c++17 -o ./cpp17/generated_cpp17 %TEST_NOIN if NOT "%MONSTER_EXTRA%"=="skip" ( @rem Flag c++17 requires Clang6, GCC7, MSVC2017 (_MSC_VER >= 1914) or higher. ..\%buildtype%\flatc.exe %TEST_CPP17_FLAGS% -I include_test monster_test.fbs || goto FAIL + ..\%buildtype%\flatc.exe %TEST_CPP17_FLAGS% optional_scalars.fbs || goto FAIL @rem..\%buildtype%\flatc.exe %TEST_CPP17_FLAGS% arrays_test.fbs || goto FAIL @rem..\%buildtype%\flatc.exe %TEST_CPP17_FLAGS% native_type_test.fbs || goto FAIL @rem..\%buildtype%\flatc.exe %TEST_CPP17_FLAGS% monster_extra.fbs || goto FAIL diff --git a/tests/generate_code.sh b/tests/generate_code.sh index c0a08330a..4dbf7aa21 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -54,6 +54,7 @@ $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS $TEST_JS_TS_FLAGS -o namespace # Generate optional scalar code for tests. ../flatc --kotlin --rust --lobster optional_scalars.fbs +../flatc $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS --cpp optional_scalars.fbs # Generate the schema evolution tests ../flatc --cpp --scoped-enums $TEST_CPP_FLAGS -o evolution_test ./evolution_test/evolution_v*.fbs @@ -84,6 +85,7 @@ fi # Flag c++17 requires Clang6, GCC7, MSVC2017 (_MSC_VER >= 1914) or higher. TEST_CPP17_FLAGS="--cpp --cpp-std c++17 -o ./cpp17/generated_cpp17 $TEST_NOINCL_FLAGS" ../flatc $TEST_CPP17_FLAGS -I include_test monster_test.fbs +../flatc $TEST_CPP17_FLAGS optional_scalars.fbs cd ../samples ../flatc --cpp --lobster $TEST_BASE_FLAGS $TEST_CPP_FLAGS monster.fbs diff --git a/tests/optional_scalars.fbs b/tests/optional_scalars.fbs index 051bae317..abea3202b 100644 --- a/tests/optional_scalars.fbs +++ b/tests/optional_scalars.fbs @@ -1,5 +1,10 @@ namespace optional_scalars; +enum OptionalByte: byte { + None = 0, + One = 1, +} + // This table tests optional scalars in tables. It should be integrated with // the main monster test once most languages support optional scalars. table ScalarStuff { @@ -41,4 +46,14 @@ table ScalarStuff { just_bool: bool; maybe_bool: bool = null; default_bool: bool = true; + + just_enum: OptionalByte; + // Rust code generator failed with optional + //maybe_enum: OptionalByte = null; + default_enum: OptionalByte = One; } + +root_type ScalarStuff; + +file_identifier "NULL"; +file_extension "mon"; diff --git a/tests/optional_scalars_generated.h b/tests/optional_scalars_generated.h new file mode 100644 index 000000000..95e51d3b0 --- /dev/null +++ b/tests/optional_scalars_generated.h @@ -0,0 +1,956 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_OPTIONALSCALARS_OPTIONAL_SCALARS_H_ +#define FLATBUFFERS_GENERATED_OPTIONALSCALARS_OPTIONAL_SCALARS_H_ + +#include "flatbuffers/flatbuffers.h" + +namespace optional_scalars { + +struct ScalarStuff; +struct ScalarStuffBuilder; +struct ScalarStuffT; + +bool operator==(const ScalarStuffT &lhs, const ScalarStuffT &rhs); +bool operator!=(const ScalarStuffT &lhs, const ScalarStuffT &rhs); + +inline const flatbuffers::TypeTable *ScalarStuffTypeTable(); + +enum OptionalByte { + OptionalByte_None = 0, + OptionalByte_One = 1, + OptionalByte_MIN = OptionalByte_None, + OptionalByte_MAX = OptionalByte_One +}; + +inline const OptionalByte (&EnumValuesOptionalByte())[2] { + static const OptionalByte values[] = { + OptionalByte_None, + OptionalByte_One + }; + return values; +} + +inline const char * const *EnumNamesOptionalByte() { + static const char * const names[3] = { + "None", + "One", + nullptr + }; + return names; +} + +inline const char *EnumNameOptionalByte(OptionalByte e) { + if (flatbuffers::IsOutRange(e, OptionalByte_None, OptionalByte_One)) return ""; + const size_t index = static_cast(e); + return EnumNamesOptionalByte()[index]; +} + +struct ScalarStuffT : public flatbuffers::NativeTable { + typedef ScalarStuff TableType; + int8_t just_i8; + flatbuffers::Optional maybe_i8; + int8_t default_i8; + uint8_t just_u8; + flatbuffers::Optional maybe_u8; + uint8_t default_u8; + int16_t just_i16; + flatbuffers::Optional maybe_i16; + int16_t default_i16; + uint16_t just_u16; + flatbuffers::Optional maybe_u16; + uint16_t default_u16; + int32_t just_i32; + flatbuffers::Optional maybe_i32; + int32_t default_i32; + uint32_t just_u32; + flatbuffers::Optional maybe_u32; + uint32_t default_u32; + int64_t just_i64; + flatbuffers::Optional maybe_i64; + int64_t default_i64; + uint64_t just_u64; + flatbuffers::Optional maybe_u64; + uint64_t default_u64; + float just_f32; + flatbuffers::Optional maybe_f32; + float default_f32; + double just_f64; + flatbuffers::Optional maybe_f64; + double default_f64; + bool just_bool; + flatbuffers::Optional maybe_bool; + bool default_bool; + optional_scalars::OptionalByte just_enum; + optional_scalars::OptionalByte default_enum; + ScalarStuffT() + : just_i8(0), + maybe_i8(flatbuffers::nullopt), + default_i8(42), + just_u8(0), + maybe_u8(flatbuffers::nullopt), + default_u8(42), + just_i16(0), + maybe_i16(flatbuffers::nullopt), + default_i16(42), + just_u16(0), + maybe_u16(flatbuffers::nullopt), + default_u16(42), + just_i32(0), + maybe_i32(flatbuffers::nullopt), + default_i32(42), + just_u32(0), + maybe_u32(flatbuffers::nullopt), + default_u32(42), + just_i64(0), + maybe_i64(flatbuffers::nullopt), + default_i64(42LL), + just_u64(0), + maybe_u64(flatbuffers::nullopt), + default_u64(42ULL), + just_f32(0.0f), + maybe_f32(flatbuffers::nullopt), + default_f32(42.0f), + just_f64(0.0), + maybe_f64(flatbuffers::nullopt), + default_f64(42.0), + just_bool(false), + maybe_bool(true), + default_bool(true), + just_enum(optional_scalars::OptionalByte_None), + default_enum(optional_scalars::OptionalByte_One) { + } +}; + +inline bool operator==(const ScalarStuffT &lhs, const ScalarStuffT &rhs) { + return + (lhs.just_i8 == rhs.just_i8) && + (lhs.maybe_i8 == rhs.maybe_i8) && + (lhs.default_i8 == rhs.default_i8) && + (lhs.just_u8 == rhs.just_u8) && + (lhs.maybe_u8 == rhs.maybe_u8) && + (lhs.default_u8 == rhs.default_u8) && + (lhs.just_i16 == rhs.just_i16) && + (lhs.maybe_i16 == rhs.maybe_i16) && + (lhs.default_i16 == rhs.default_i16) && + (lhs.just_u16 == rhs.just_u16) && + (lhs.maybe_u16 == rhs.maybe_u16) && + (lhs.default_u16 == rhs.default_u16) && + (lhs.just_i32 == rhs.just_i32) && + (lhs.maybe_i32 == rhs.maybe_i32) && + (lhs.default_i32 == rhs.default_i32) && + (lhs.just_u32 == rhs.just_u32) && + (lhs.maybe_u32 == rhs.maybe_u32) && + (lhs.default_u32 == rhs.default_u32) && + (lhs.just_i64 == rhs.just_i64) && + (lhs.maybe_i64 == rhs.maybe_i64) && + (lhs.default_i64 == rhs.default_i64) && + (lhs.just_u64 == rhs.just_u64) && + (lhs.maybe_u64 == rhs.maybe_u64) && + (lhs.default_u64 == rhs.default_u64) && + (lhs.just_f32 == rhs.just_f32) && + (lhs.maybe_f32 == rhs.maybe_f32) && + (lhs.default_f32 == rhs.default_f32) && + (lhs.just_f64 == rhs.just_f64) && + (lhs.maybe_f64 == rhs.maybe_f64) && + (lhs.default_f64 == rhs.default_f64) && + (lhs.just_bool == rhs.just_bool) && + (lhs.maybe_bool == rhs.maybe_bool) && + (lhs.default_bool == rhs.default_bool) && + (lhs.just_enum == rhs.just_enum) && + (lhs.default_enum == rhs.default_enum); +} + +inline bool operator!=(const ScalarStuffT &lhs, const ScalarStuffT &rhs) { + return !(lhs == rhs); +} + + +struct ScalarStuff FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ScalarStuffT NativeTableType; + typedef ScalarStuffBuilder Builder; + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return ScalarStuffTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_JUST_I8 = 4, + VT_MAYBE_I8 = 6, + VT_DEFAULT_I8 = 8, + VT_JUST_U8 = 10, + VT_MAYBE_U8 = 12, + VT_DEFAULT_U8 = 14, + VT_JUST_I16 = 16, + VT_MAYBE_I16 = 18, + VT_DEFAULT_I16 = 20, + VT_JUST_U16 = 22, + VT_MAYBE_U16 = 24, + VT_DEFAULT_U16 = 26, + VT_JUST_I32 = 28, + VT_MAYBE_I32 = 30, + VT_DEFAULT_I32 = 32, + VT_JUST_U32 = 34, + VT_MAYBE_U32 = 36, + VT_DEFAULT_U32 = 38, + VT_JUST_I64 = 40, + VT_MAYBE_I64 = 42, + VT_DEFAULT_I64 = 44, + VT_JUST_U64 = 46, + VT_MAYBE_U64 = 48, + VT_DEFAULT_U64 = 50, + VT_JUST_F32 = 52, + VT_MAYBE_F32 = 54, + VT_DEFAULT_F32 = 56, + VT_JUST_F64 = 58, + VT_MAYBE_F64 = 60, + VT_DEFAULT_F64 = 62, + VT_JUST_BOOL = 64, + VT_MAYBE_BOOL = 66, + VT_DEFAULT_BOOL = 68, + VT_JUST_ENUM = 70, + VT_DEFAULT_ENUM = 72 + }; + int8_t just_i8() const { + return GetField(VT_JUST_I8, 0); + } + bool mutate_just_i8(int8_t _just_i8) { + return SetField(VT_JUST_I8, _just_i8, 0); + } + flatbuffers::Optional maybe_i8() const { + return GetOptional(VT_MAYBE_I8); + } + bool mutate_maybe_i8(int8_t _maybe_i8) { + return SetField(VT_MAYBE_I8, _maybe_i8); + } + int8_t default_i8() const { + return GetField(VT_DEFAULT_I8, 42); + } + bool mutate_default_i8(int8_t _default_i8) { + return SetField(VT_DEFAULT_I8, _default_i8, 42); + } + uint8_t just_u8() const { + return GetField(VT_JUST_U8, 0); + } + bool mutate_just_u8(uint8_t _just_u8) { + return SetField(VT_JUST_U8, _just_u8, 0); + } + flatbuffers::Optional maybe_u8() const { + return GetOptional(VT_MAYBE_U8); + } + bool mutate_maybe_u8(uint8_t _maybe_u8) { + return SetField(VT_MAYBE_U8, _maybe_u8); + } + uint8_t default_u8() const { + return GetField(VT_DEFAULT_U8, 42); + } + bool mutate_default_u8(uint8_t _default_u8) { + return SetField(VT_DEFAULT_U8, _default_u8, 42); + } + int16_t just_i16() const { + return GetField(VT_JUST_I16, 0); + } + bool mutate_just_i16(int16_t _just_i16) { + return SetField(VT_JUST_I16, _just_i16, 0); + } + flatbuffers::Optional maybe_i16() const { + return GetOptional(VT_MAYBE_I16); + } + bool mutate_maybe_i16(int16_t _maybe_i16) { + return SetField(VT_MAYBE_I16, _maybe_i16); + } + int16_t default_i16() const { + return GetField(VT_DEFAULT_I16, 42); + } + bool mutate_default_i16(int16_t _default_i16) { + return SetField(VT_DEFAULT_I16, _default_i16, 42); + } + uint16_t just_u16() const { + return GetField(VT_JUST_U16, 0); + } + bool mutate_just_u16(uint16_t _just_u16) { + return SetField(VT_JUST_U16, _just_u16, 0); + } + flatbuffers::Optional maybe_u16() const { + return GetOptional(VT_MAYBE_U16); + } + bool mutate_maybe_u16(uint16_t _maybe_u16) { + return SetField(VT_MAYBE_U16, _maybe_u16); + } + uint16_t default_u16() const { + return GetField(VT_DEFAULT_U16, 42); + } + bool mutate_default_u16(uint16_t _default_u16) { + return SetField(VT_DEFAULT_U16, _default_u16, 42); + } + int32_t just_i32() const { + return GetField(VT_JUST_I32, 0); + } + bool mutate_just_i32(int32_t _just_i32) { + return SetField(VT_JUST_I32, _just_i32, 0); + } + flatbuffers::Optional maybe_i32() const { + return GetOptional(VT_MAYBE_I32); + } + bool mutate_maybe_i32(int32_t _maybe_i32) { + return SetField(VT_MAYBE_I32, _maybe_i32); + } + int32_t default_i32() const { + return GetField(VT_DEFAULT_I32, 42); + } + bool mutate_default_i32(int32_t _default_i32) { + return SetField(VT_DEFAULT_I32, _default_i32, 42); + } + uint32_t just_u32() const { + return GetField(VT_JUST_U32, 0); + } + bool mutate_just_u32(uint32_t _just_u32) { + return SetField(VT_JUST_U32, _just_u32, 0); + } + flatbuffers::Optional maybe_u32() const { + return GetOptional(VT_MAYBE_U32); + } + bool mutate_maybe_u32(uint32_t _maybe_u32) { + return SetField(VT_MAYBE_U32, _maybe_u32); + } + uint32_t default_u32() const { + return GetField(VT_DEFAULT_U32, 42); + } + bool mutate_default_u32(uint32_t _default_u32) { + return SetField(VT_DEFAULT_U32, _default_u32, 42); + } + int64_t just_i64() const { + return GetField(VT_JUST_I64, 0); + } + bool mutate_just_i64(int64_t _just_i64) { + return SetField(VT_JUST_I64, _just_i64, 0); + } + flatbuffers::Optional maybe_i64() const { + return GetOptional(VT_MAYBE_I64); + } + bool mutate_maybe_i64(int64_t _maybe_i64) { + return SetField(VT_MAYBE_I64, _maybe_i64); + } + int64_t default_i64() const { + return GetField(VT_DEFAULT_I64, 42LL); + } + bool mutate_default_i64(int64_t _default_i64) { + return SetField(VT_DEFAULT_I64, _default_i64, 42LL); + } + uint64_t just_u64() const { + return GetField(VT_JUST_U64, 0); + } + bool mutate_just_u64(uint64_t _just_u64) { + return SetField(VT_JUST_U64, _just_u64, 0); + } + flatbuffers::Optional maybe_u64() const { + return GetOptional(VT_MAYBE_U64); + } + bool mutate_maybe_u64(uint64_t _maybe_u64) { + return SetField(VT_MAYBE_U64, _maybe_u64); + } + uint64_t default_u64() const { + return GetField(VT_DEFAULT_U64, 42ULL); + } + bool mutate_default_u64(uint64_t _default_u64) { + return SetField(VT_DEFAULT_U64, _default_u64, 42ULL); + } + float just_f32() const { + return GetField(VT_JUST_F32, 0.0f); + } + bool mutate_just_f32(float _just_f32) { + return SetField(VT_JUST_F32, _just_f32, 0.0f); + } + flatbuffers::Optional maybe_f32() const { + return GetOptional(VT_MAYBE_F32); + } + bool mutate_maybe_f32(float _maybe_f32) { + return SetField(VT_MAYBE_F32, _maybe_f32); + } + float default_f32() const { + return GetField(VT_DEFAULT_F32, 42.0f); + } + bool mutate_default_f32(float _default_f32) { + return SetField(VT_DEFAULT_F32, _default_f32, 42.0f); + } + double just_f64() const { + return GetField(VT_JUST_F64, 0.0); + } + bool mutate_just_f64(double _just_f64) { + return SetField(VT_JUST_F64, _just_f64, 0.0); + } + flatbuffers::Optional maybe_f64() const { + return GetOptional(VT_MAYBE_F64); + } + bool mutate_maybe_f64(double _maybe_f64) { + return SetField(VT_MAYBE_F64, _maybe_f64); + } + double default_f64() const { + return GetField(VT_DEFAULT_F64, 42.0); + } + bool mutate_default_f64(double _default_f64) { + return SetField(VT_DEFAULT_F64, _default_f64, 42.0); + } + bool just_bool() const { + return GetField(VT_JUST_BOOL, 0) != 0; + } + bool mutate_just_bool(bool _just_bool) { + return SetField(VT_JUST_BOOL, static_cast(_just_bool), 0); + } + flatbuffers::Optional maybe_bool() const { + return GetOptional(VT_MAYBE_BOOL); + } + bool mutate_maybe_bool(bool _maybe_bool) { + return SetField(VT_MAYBE_BOOL, static_cast(_maybe_bool)); + } + bool default_bool() const { + return GetField(VT_DEFAULT_BOOL, 1) != 0; + } + bool mutate_default_bool(bool _default_bool) { + return SetField(VT_DEFAULT_BOOL, static_cast(_default_bool), 1); + } + optional_scalars::OptionalByte just_enum() const { + return static_cast(GetField(VT_JUST_ENUM, 0)); + } + bool mutate_just_enum(optional_scalars::OptionalByte _just_enum) { + return SetField(VT_JUST_ENUM, static_cast(_just_enum), 0); + } + optional_scalars::OptionalByte default_enum() const { + return static_cast(GetField(VT_DEFAULT_ENUM, 1)); + } + bool mutate_default_enum(optional_scalars::OptionalByte _default_enum) { + return SetField(VT_DEFAULT_ENUM, static_cast(_default_enum), 1); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_JUST_I8) && + VerifyField(verifier, VT_MAYBE_I8) && + VerifyField(verifier, VT_DEFAULT_I8) && + VerifyField(verifier, VT_JUST_U8) && + VerifyField(verifier, VT_MAYBE_U8) && + VerifyField(verifier, VT_DEFAULT_U8) && + VerifyField(verifier, VT_JUST_I16) && + VerifyField(verifier, VT_MAYBE_I16) && + VerifyField(verifier, VT_DEFAULT_I16) && + VerifyField(verifier, VT_JUST_U16) && + VerifyField(verifier, VT_MAYBE_U16) && + VerifyField(verifier, VT_DEFAULT_U16) && + VerifyField(verifier, VT_JUST_I32) && + VerifyField(verifier, VT_MAYBE_I32) && + VerifyField(verifier, VT_DEFAULT_I32) && + VerifyField(verifier, VT_JUST_U32) && + VerifyField(verifier, VT_MAYBE_U32) && + VerifyField(verifier, VT_DEFAULT_U32) && + VerifyField(verifier, VT_JUST_I64) && + VerifyField(verifier, VT_MAYBE_I64) && + VerifyField(verifier, VT_DEFAULT_I64) && + VerifyField(verifier, VT_JUST_U64) && + VerifyField(verifier, VT_MAYBE_U64) && + VerifyField(verifier, VT_DEFAULT_U64) && + VerifyField(verifier, VT_JUST_F32) && + VerifyField(verifier, VT_MAYBE_F32) && + VerifyField(verifier, VT_DEFAULT_F32) && + VerifyField(verifier, VT_JUST_F64) && + VerifyField(verifier, VT_MAYBE_F64) && + VerifyField(verifier, VT_DEFAULT_F64) && + VerifyField(verifier, VT_JUST_BOOL) && + VerifyField(verifier, VT_MAYBE_BOOL) && + VerifyField(verifier, VT_DEFAULT_BOOL) && + VerifyField(verifier, VT_JUST_ENUM) && + VerifyField(verifier, VT_DEFAULT_ENUM) && + verifier.EndTable(); + } + ScalarStuffT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ScalarStuffT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ScalarStuffT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ScalarStuffBuilder { + typedef ScalarStuff Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_just_i8(int8_t just_i8) { + fbb_.AddElement(ScalarStuff::VT_JUST_I8, just_i8, 0); + } + void add_maybe_i8(int8_t maybe_i8) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_I8, maybe_i8); + } + void add_default_i8(int8_t default_i8) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_I8, default_i8, 42); + } + void add_just_u8(uint8_t just_u8) { + fbb_.AddElement(ScalarStuff::VT_JUST_U8, just_u8, 0); + } + void add_maybe_u8(uint8_t maybe_u8) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_U8, maybe_u8); + } + void add_default_u8(uint8_t default_u8) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_U8, default_u8, 42); + } + void add_just_i16(int16_t just_i16) { + fbb_.AddElement(ScalarStuff::VT_JUST_I16, just_i16, 0); + } + void add_maybe_i16(int16_t maybe_i16) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_I16, maybe_i16); + } + void add_default_i16(int16_t default_i16) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_I16, default_i16, 42); + } + void add_just_u16(uint16_t just_u16) { + fbb_.AddElement(ScalarStuff::VT_JUST_U16, just_u16, 0); + } + void add_maybe_u16(uint16_t maybe_u16) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_U16, maybe_u16); + } + void add_default_u16(uint16_t default_u16) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_U16, default_u16, 42); + } + void add_just_i32(int32_t just_i32) { + fbb_.AddElement(ScalarStuff::VT_JUST_I32, just_i32, 0); + } + void add_maybe_i32(int32_t maybe_i32) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_I32, maybe_i32); + } + void add_default_i32(int32_t default_i32) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_I32, default_i32, 42); + } + void add_just_u32(uint32_t just_u32) { + fbb_.AddElement(ScalarStuff::VT_JUST_U32, just_u32, 0); + } + void add_maybe_u32(uint32_t maybe_u32) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_U32, maybe_u32); + } + void add_default_u32(uint32_t default_u32) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_U32, default_u32, 42); + } + void add_just_i64(int64_t just_i64) { + fbb_.AddElement(ScalarStuff::VT_JUST_I64, just_i64, 0); + } + void add_maybe_i64(int64_t maybe_i64) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_I64, maybe_i64); + } + void add_default_i64(int64_t default_i64) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_I64, default_i64, 42LL); + } + void add_just_u64(uint64_t just_u64) { + fbb_.AddElement(ScalarStuff::VT_JUST_U64, just_u64, 0); + } + void add_maybe_u64(uint64_t maybe_u64) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_U64, maybe_u64); + } + void add_default_u64(uint64_t default_u64) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_U64, default_u64, 42ULL); + } + void add_just_f32(float just_f32) { + fbb_.AddElement(ScalarStuff::VT_JUST_F32, just_f32, 0.0f); + } + void add_maybe_f32(float maybe_f32) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_F32, maybe_f32); + } + void add_default_f32(float default_f32) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_F32, default_f32, 42.0f); + } + void add_just_f64(double just_f64) { + fbb_.AddElement(ScalarStuff::VT_JUST_F64, just_f64, 0.0); + } + void add_maybe_f64(double maybe_f64) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_F64, maybe_f64); + } + void add_default_f64(double default_f64) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_F64, default_f64, 42.0); + } + void add_just_bool(bool just_bool) { + fbb_.AddElement(ScalarStuff::VT_JUST_BOOL, static_cast(just_bool), 0); + } + void add_maybe_bool(bool maybe_bool) { + fbb_.AddElement(ScalarStuff::VT_MAYBE_BOOL, static_cast(maybe_bool)); + } + void add_default_bool(bool default_bool) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_BOOL, static_cast(default_bool), 1); + } + void add_just_enum(optional_scalars::OptionalByte just_enum) { + fbb_.AddElement(ScalarStuff::VT_JUST_ENUM, static_cast(just_enum), 0); + } + void add_default_enum(optional_scalars::OptionalByte default_enum) { + fbb_.AddElement(ScalarStuff::VT_DEFAULT_ENUM, static_cast(default_enum), 1); + } + explicit ScalarStuffBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateScalarStuff( + flatbuffers::FlatBufferBuilder &_fbb, + int8_t just_i8 = 0, + flatbuffers::Optionalmaybe_i8 = flatbuffers::nullopt, + int8_t default_i8 = 42, + uint8_t just_u8 = 0, + flatbuffers::Optionalmaybe_u8 = flatbuffers::nullopt, + uint8_t default_u8 = 42, + int16_t just_i16 = 0, + flatbuffers::Optionalmaybe_i16 = flatbuffers::nullopt, + int16_t default_i16 = 42, + uint16_t just_u16 = 0, + flatbuffers::Optionalmaybe_u16 = flatbuffers::nullopt, + uint16_t default_u16 = 42, + int32_t just_i32 = 0, + flatbuffers::Optionalmaybe_i32 = flatbuffers::nullopt, + int32_t default_i32 = 42, + uint32_t just_u32 = 0, + flatbuffers::Optionalmaybe_u32 = flatbuffers::nullopt, + uint32_t default_u32 = 42, + int64_t just_i64 = 0, + flatbuffers::Optionalmaybe_i64 = flatbuffers::nullopt, + int64_t default_i64 = 42LL, + uint64_t just_u64 = 0, + flatbuffers::Optionalmaybe_u64 = flatbuffers::nullopt, + uint64_t default_u64 = 42ULL, + float just_f32 = 0.0f, + flatbuffers::Optionalmaybe_f32 = flatbuffers::nullopt, + float default_f32 = 42.0f, + double just_f64 = 0.0, + flatbuffers::Optionalmaybe_f64 = flatbuffers::nullopt, + double default_f64 = 42.0, + bool just_bool = false, + flatbuffers::Optionalmaybe_bool = flatbuffers::nullopt, + bool default_bool = true, + optional_scalars::OptionalByte just_enum = optional_scalars::OptionalByte_None, + optional_scalars::OptionalByte default_enum = optional_scalars::OptionalByte_One) { + ScalarStuffBuilder builder_(_fbb); + builder_.add_default_f64(default_f64); + if(maybe_f64) { builder_.add_maybe_f64(*maybe_f64); } + builder_.add_just_f64(just_f64); + builder_.add_default_u64(default_u64); + if(maybe_u64) { builder_.add_maybe_u64(*maybe_u64); } + builder_.add_just_u64(just_u64); + builder_.add_default_i64(default_i64); + if(maybe_i64) { builder_.add_maybe_i64(*maybe_i64); } + builder_.add_just_i64(just_i64); + builder_.add_default_f32(default_f32); + if(maybe_f32) { builder_.add_maybe_f32(*maybe_f32); } + builder_.add_just_f32(just_f32); + builder_.add_default_u32(default_u32); + if(maybe_u32) { builder_.add_maybe_u32(*maybe_u32); } + builder_.add_just_u32(just_u32); + builder_.add_default_i32(default_i32); + if(maybe_i32) { builder_.add_maybe_i32(*maybe_i32); } + builder_.add_just_i32(just_i32); + builder_.add_default_u16(default_u16); + if(maybe_u16) { builder_.add_maybe_u16(*maybe_u16); } + builder_.add_just_u16(just_u16); + builder_.add_default_i16(default_i16); + if(maybe_i16) { builder_.add_maybe_i16(*maybe_i16); } + builder_.add_just_i16(just_i16); + builder_.add_default_enum(default_enum); + builder_.add_just_enum(just_enum); + builder_.add_default_bool(default_bool); + if(maybe_bool) { builder_.add_maybe_bool(*maybe_bool); } + builder_.add_just_bool(just_bool); + builder_.add_default_u8(default_u8); + if(maybe_u8) { builder_.add_maybe_u8(*maybe_u8); } + builder_.add_just_u8(just_u8); + builder_.add_default_i8(default_i8); + if(maybe_i8) { builder_.add_maybe_i8(*maybe_i8); } + builder_.add_just_i8(just_i8); + return builder_.Finish(); +} + +flatbuffers::Offset CreateScalarStuff(flatbuffers::FlatBufferBuilder &_fbb, const ScalarStuffT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +inline ScalarStuffT *ScalarStuff::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new ScalarStuffT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void ScalarStuff::UnPackTo(ScalarStuffT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = just_i8(); _o->just_i8 = _e; } + { auto _e = maybe_i8(); _o->maybe_i8 = _e; } + { auto _e = default_i8(); _o->default_i8 = _e; } + { auto _e = just_u8(); _o->just_u8 = _e; } + { auto _e = maybe_u8(); _o->maybe_u8 = _e; } + { auto _e = default_u8(); _o->default_u8 = _e; } + { auto _e = just_i16(); _o->just_i16 = _e; } + { auto _e = maybe_i16(); _o->maybe_i16 = _e; } + { auto _e = default_i16(); _o->default_i16 = _e; } + { auto _e = just_u16(); _o->just_u16 = _e; } + { auto _e = maybe_u16(); _o->maybe_u16 = _e; } + { auto _e = default_u16(); _o->default_u16 = _e; } + { auto _e = just_i32(); _o->just_i32 = _e; } + { auto _e = maybe_i32(); _o->maybe_i32 = _e; } + { auto _e = default_i32(); _o->default_i32 = _e; } + { auto _e = just_u32(); _o->just_u32 = _e; } + { auto _e = maybe_u32(); _o->maybe_u32 = _e; } + { auto _e = default_u32(); _o->default_u32 = _e; } + { auto _e = just_i64(); _o->just_i64 = _e; } + { auto _e = maybe_i64(); _o->maybe_i64 = _e; } + { auto _e = default_i64(); _o->default_i64 = _e; } + { auto _e = just_u64(); _o->just_u64 = _e; } + { auto _e = maybe_u64(); _o->maybe_u64 = _e; } + { auto _e = default_u64(); _o->default_u64 = _e; } + { auto _e = just_f32(); _o->just_f32 = _e; } + { auto _e = maybe_f32(); _o->maybe_f32 = _e; } + { auto _e = default_f32(); _o->default_f32 = _e; } + { auto _e = just_f64(); _o->just_f64 = _e; } + { auto _e = maybe_f64(); _o->maybe_f64 = _e; } + { auto _e = default_f64(); _o->default_f64 = _e; } + { auto _e = just_bool(); _o->just_bool = _e; } + { auto _e = maybe_bool(); _o->maybe_bool = _e; } + { auto _e = default_bool(); _o->default_bool = _e; } + { auto _e = just_enum(); _o->just_enum = _e; } + { auto _e = default_enum(); _o->default_enum = _e; } +} + +inline flatbuffers::Offset ScalarStuff::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ScalarStuffT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateScalarStuff(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateScalarStuff(flatbuffers::FlatBufferBuilder &_fbb, const ScalarStuffT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ScalarStuffT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _just_i8 = _o->just_i8; + auto _maybe_i8 = _o->maybe_i8; + auto _default_i8 = _o->default_i8; + auto _just_u8 = _o->just_u8; + auto _maybe_u8 = _o->maybe_u8; + auto _default_u8 = _o->default_u8; + auto _just_i16 = _o->just_i16; + auto _maybe_i16 = _o->maybe_i16; + auto _default_i16 = _o->default_i16; + auto _just_u16 = _o->just_u16; + auto _maybe_u16 = _o->maybe_u16; + auto _default_u16 = _o->default_u16; + auto _just_i32 = _o->just_i32; + auto _maybe_i32 = _o->maybe_i32; + auto _default_i32 = _o->default_i32; + auto _just_u32 = _o->just_u32; + auto _maybe_u32 = _o->maybe_u32; + auto _default_u32 = _o->default_u32; + auto _just_i64 = _o->just_i64; + auto _maybe_i64 = _o->maybe_i64; + auto _default_i64 = _o->default_i64; + auto _just_u64 = _o->just_u64; + auto _maybe_u64 = _o->maybe_u64; + auto _default_u64 = _o->default_u64; + auto _just_f32 = _o->just_f32; + auto _maybe_f32 = _o->maybe_f32; + auto _default_f32 = _o->default_f32; + auto _just_f64 = _o->just_f64; + auto _maybe_f64 = _o->maybe_f64; + auto _default_f64 = _o->default_f64; + auto _just_bool = _o->just_bool; + auto _maybe_bool = _o->maybe_bool; + auto _default_bool = _o->default_bool; + auto _just_enum = _o->just_enum; + auto _default_enum = _o->default_enum; + return optional_scalars::CreateScalarStuff( + _fbb, + _just_i8, + _maybe_i8, + _default_i8, + _just_u8, + _maybe_u8, + _default_u8, + _just_i16, + _maybe_i16, + _default_i16, + _just_u16, + _maybe_u16, + _default_u16, + _just_i32, + _maybe_i32, + _default_i32, + _just_u32, + _maybe_u32, + _default_u32, + _just_i64, + _maybe_i64, + _default_i64, + _just_u64, + _maybe_u64, + _default_u64, + _just_f32, + _maybe_f32, + _default_f32, + _just_f64, + _maybe_f64, + _default_f64, + _just_bool, + _maybe_bool, + _default_bool, + _just_enum, + _default_enum); +} + +inline const flatbuffers::TypeTable *OptionalByteTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_CHAR, 0, 0 }, + { flatbuffers::ET_CHAR, 0, 0 } + }; + static const flatbuffers::TypeFunction type_refs[] = { + optional_scalars::OptionalByteTypeTable + }; + static const char * const names[] = { + "None", + "One" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_ENUM, 2, type_codes, type_refs, nullptr, names + }; + return &tt; +} + +inline const flatbuffers::TypeTable *ScalarStuffTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_CHAR, 0, -1 }, + { flatbuffers::ET_CHAR, 0, -1 }, + { flatbuffers::ET_CHAR, 0, -1 }, + { flatbuffers::ET_UCHAR, 0, -1 }, + { flatbuffers::ET_UCHAR, 0, -1 }, + { flatbuffers::ET_UCHAR, 0, -1 }, + { flatbuffers::ET_SHORT, 0, -1 }, + { flatbuffers::ET_SHORT, 0, -1 }, + { flatbuffers::ET_SHORT, 0, -1 }, + { flatbuffers::ET_USHORT, 0, -1 }, + { flatbuffers::ET_USHORT, 0, -1 }, + { flatbuffers::ET_USHORT, 0, -1 }, + { flatbuffers::ET_INT, 0, -1 }, + { flatbuffers::ET_INT, 0, -1 }, + { flatbuffers::ET_INT, 0, -1 }, + { flatbuffers::ET_UINT, 0, -1 }, + { flatbuffers::ET_UINT, 0, -1 }, + { flatbuffers::ET_UINT, 0, -1 }, + { flatbuffers::ET_LONG, 0, -1 }, + { flatbuffers::ET_LONG, 0, -1 }, + { flatbuffers::ET_LONG, 0, -1 }, + { flatbuffers::ET_ULONG, 0, -1 }, + { flatbuffers::ET_ULONG, 0, -1 }, + { flatbuffers::ET_ULONG, 0, -1 }, + { flatbuffers::ET_FLOAT, 0, -1 }, + { flatbuffers::ET_FLOAT, 0, -1 }, + { flatbuffers::ET_FLOAT, 0, -1 }, + { flatbuffers::ET_DOUBLE, 0, -1 }, + { flatbuffers::ET_DOUBLE, 0, -1 }, + { flatbuffers::ET_DOUBLE, 0, -1 }, + { flatbuffers::ET_BOOL, 0, -1 }, + { flatbuffers::ET_BOOL, 0, -1 }, + { flatbuffers::ET_BOOL, 0, -1 }, + { flatbuffers::ET_CHAR, 0, 0 }, + { flatbuffers::ET_CHAR, 0, 0 } + }; + static const flatbuffers::TypeFunction type_refs[] = { + optional_scalars::OptionalByteTypeTable + }; + static const char * const names[] = { + "just_i8", + "maybe_i8", + "default_i8", + "just_u8", + "maybe_u8", + "default_u8", + "just_i16", + "maybe_i16", + "default_i16", + "just_u16", + "maybe_u16", + "default_u16", + "just_i32", + "maybe_i32", + "default_i32", + "just_u32", + "maybe_u32", + "default_u32", + "just_i64", + "maybe_i64", + "default_i64", + "just_u64", + "maybe_u64", + "default_u64", + "just_f32", + "maybe_f32", + "default_f32", + "just_f64", + "maybe_f64", + "default_f64", + "just_bool", + "maybe_bool", + "default_bool", + "just_enum", + "default_enum" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_TABLE, 35, type_codes, type_refs, nullptr, names + }; + return &tt; +} + +inline const optional_scalars::ScalarStuff *GetScalarStuff(const void *buf) { + return flatbuffers::GetRoot(buf); +} + +inline const optional_scalars::ScalarStuff *GetSizePrefixedScalarStuff(const void *buf) { + return flatbuffers::GetSizePrefixedRoot(buf); +} + +inline ScalarStuff *GetMutableScalarStuff(void *buf) { + return flatbuffers::GetMutableRoot(buf); +} + +inline const char *ScalarStuffIdentifier() { + return "NULL"; +} + +inline bool ScalarStuffBufferHasIdentifier(const void *buf) { + return flatbuffers::BufferHasIdentifier( + buf, ScalarStuffIdentifier()); +} + +inline bool VerifyScalarStuffBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer(ScalarStuffIdentifier()); +} + +inline bool VerifySizePrefixedScalarStuffBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer(ScalarStuffIdentifier()); +} + +inline const char *ScalarStuffExtension() { + return "mon"; +} + +inline void FinishScalarStuffBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.Finish(root, ScalarStuffIdentifier()); +} + +inline void FinishSizePrefixedScalarStuffBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root, ScalarStuffIdentifier()); +} + +inline flatbuffers::unique_ptr UnPackScalarStuff( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return flatbuffers::unique_ptr(GetScalarStuff(buf)->UnPack(res)); +} + +inline flatbuffers::unique_ptr UnPackSizePrefixedScalarStuff( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return flatbuffers::unique_ptr(GetSizePrefixedScalarStuff(buf)->UnPack(res)); +} + +} // namespace optional_scalars + +#endif // FLATBUFFERS_GENERATED_OPTIONALSCALARS_OPTIONAL_SCALARS_H_ diff --git a/tests/optional_scalars_generated.lobster b/tests/optional_scalars_generated.lobster index 0c4b928fd..3a9f0c533 100644 --- a/tests/optional_scalars_generated.lobster +++ b/tests/optional_scalars_generated.lobster @@ -3,6 +3,10 @@ import flatbuffers namespace optional_scalars +enum OptionalByte: + OptionalByte_None = 0 + OptionalByte_One = 1 + class ScalarStuff class ScalarStuff : flatbuffers_handle @@ -72,13 +76,17 @@ class ScalarStuff : flatbuffers_handle return buf_.flatbuffers_field_int8(pos_, 66, 0), buf_.flatbuffers_field_present(pos_, 66) def default_bool(): return buf_.flatbuffers_field_int8(pos_, 68, 1) + def just_enum(): + return OptionalByte(buf_.flatbuffers_field_int8(pos_, 70, 0)) + def default_enum(): + return OptionalByte(buf_.flatbuffers_field_int8(pos_, 72, 1)) def GetRootAsScalarStuff(buf:string): return ScalarStuff { buf, buf.flatbuffers_indirect(0) } struct ScalarStuffBuilder: b_:flatbuffers_builder def start(): - b_.StartObject(33) + b_.StartObject(35) return this def add_just_i8(just_i8:int): b_.PrependInt8Slot(0, just_i8, 0) @@ -179,6 +187,12 @@ struct ScalarStuffBuilder: def add_default_bool(default_bool:int): b_.PrependBoolSlot(32, default_bool, 1) return this + def add_just_enum(just_enum:OptionalByte): + b_.PrependInt8Slot(33, just_enum, 0) + return this + def add_default_enum(default_enum:OptionalByte): + b_.PrependInt8Slot(34, default_enum, 1) + return this def end(): return b_.EndObject() diff --git a/tests/optional_scalars_generated.rs b/tests/optional_scalars_generated.rs index 2cc413c44..39625a457 100644 --- a/tests/optional_scalars_generated.rs +++ b/tests/optional_scalars_generated.rs @@ -17,6 +17,66 @@ pub mod optional_scalars { extern crate flatbuffers; use self::flatbuffers::EndianScalar; +#[allow(non_camel_case_types)] +#[repr(i8)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum OptionalByte { + None = 0, + One = 1, + +} + +pub const ENUM_MIN_OPTIONAL_BYTE: i8 = 0; +pub const ENUM_MAX_OPTIONAL_BYTE: i8 = 1; + +impl<'a> flatbuffers::Follow<'a> for OptionalByte { + type Inner = Self; + #[inline] + fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + flatbuffers::read_scalar_at::(buf, loc) + } +} + +impl flatbuffers::EndianScalar for OptionalByte { + #[inline] + fn to_little_endian(self) -> Self { + let n = i8::to_le(self as i8); + let p = &n as *const i8 as *const OptionalByte; + unsafe { *p } + } + #[inline] + fn from_little_endian(self) -> Self { + let n = i8::from_le(self as i8); + let p = &n as *const i8 as *const OptionalByte; + unsafe { *p } + } +} + +impl flatbuffers::Push for OptionalByte { + type Output = OptionalByte; + #[inline] + fn push(&self, dst: &mut [u8], _rest: &[u8]) { + flatbuffers::emplace_scalar::(dst, *self); + } +} + +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_OPTIONAL_BYTE: [OptionalByte; 2] = [ + OptionalByte::None, + OptionalByte::One +]; + +#[allow(non_camel_case_types)] +pub const ENUM_NAMES_OPTIONAL_BYTE: [&str; 2] = [ + "None", + "One" +]; + +pub fn enum_name_optional_byte(e: OptionalByte) -> &'static str { + let index = e as i8; + ENUM_NAMES_OPTIONAL_BYTE[index as usize] +} + pub enum ScalarStuffOffset {} #[derive(Copy, Clone, Debug, PartialEq)] @@ -68,6 +128,8 @@ impl<'a> ScalarStuff<'a> { builder.add_default_i16(args.default_i16); if let Some(x) = args.maybe_i16 { builder.add_maybe_i16(x); } builder.add_just_i16(args.just_i16); + builder.add_default_enum(args.default_enum); + builder.add_just_enum(args.just_enum); builder.add_default_bool(args.default_bool); if let Some(x) = args.maybe_bool { builder.add_maybe_bool(x); } builder.add_just_bool(args.just_bool); @@ -113,6 +175,8 @@ impl<'a> ScalarStuff<'a> { pub const VT_JUST_BOOL: flatbuffers::VOffsetT = 64; pub const VT_MAYBE_BOOL: flatbuffers::VOffsetT = 66; pub const VT_DEFAULT_BOOL: flatbuffers::VOffsetT = 68; + pub const VT_JUST_ENUM: flatbuffers::VOffsetT = 70; + pub const VT_DEFAULT_ENUM: flatbuffers::VOffsetT = 72; #[inline] pub fn just_i8(&self) -> i8 { @@ -246,6 +310,14 @@ impl<'a> ScalarStuff<'a> { pub fn default_bool(&self) -> bool { self._tab.get::(ScalarStuff::VT_DEFAULT_BOOL, Some(true)).unwrap() } + #[inline] + pub fn just_enum(&self) -> OptionalByte { + self._tab.get::(ScalarStuff::VT_JUST_ENUM, Some(OptionalByte::None)).unwrap() + } + #[inline] + pub fn default_enum(&self) -> OptionalByte { + self._tab.get::(ScalarStuff::VT_DEFAULT_ENUM, Some(OptionalByte::One)).unwrap() + } } pub struct ScalarStuffArgs { @@ -282,6 +354,8 @@ pub struct ScalarStuffArgs { pub just_bool: bool, pub maybe_bool: Option, pub default_bool: bool, + pub just_enum: OptionalByte, + pub default_enum: OptionalByte, } impl<'a> Default for ScalarStuffArgs { #[inline] @@ -320,6 +394,8 @@ impl<'a> Default for ScalarStuffArgs { just_bool: false, maybe_bool: None, default_bool: true, + just_enum: OptionalByte::None, + default_enum: OptionalByte::One, } } } @@ -461,6 +537,14 @@ impl<'a: 'b, 'b> ScalarStuffBuilder<'a, 'b> { self.fbb_.push_slot::(ScalarStuff::VT_DEFAULT_BOOL, default_bool, true); } #[inline] + pub fn add_just_enum(&mut self, just_enum: OptionalByte) { + self.fbb_.push_slot::(ScalarStuff::VT_JUST_ENUM, just_enum, OptionalByte::None); + } + #[inline] + pub fn add_default_enum(&mut self, default_enum: OptionalByte) { + self.fbb_.push_slot::(ScalarStuff::VT_DEFAULT_ENUM, default_enum, OptionalByte::One); + } + #[inline] pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> ScalarStuffBuilder<'a, 'b> { let start = _fbb.start_table(); ScalarStuffBuilder { @@ -475,5 +559,40 @@ impl<'a: 'b, 'b> ScalarStuffBuilder<'a, 'b> { } } +#[inline] +pub fn get_root_as_scalar_stuff<'a>(buf: &'a [u8]) -> ScalarStuff<'a> { + flatbuffers::get_root::>(buf) +} + +#[inline] +pub fn get_size_prefixed_root_as_scalar_stuff<'a>(buf: &'a [u8]) -> ScalarStuff<'a> { + flatbuffers::get_size_prefixed_root::>(buf) +} + +pub const SCALAR_STUFF_IDENTIFIER: &str = "NULL"; + +#[inline] +pub fn scalar_stuff_buffer_has_identifier(buf: &[u8]) -> bool { + flatbuffers::buffer_has_identifier(buf, SCALAR_STUFF_IDENTIFIER, false) +} + +#[inline] +pub fn scalar_stuff_size_prefixed_buffer_has_identifier(buf: &[u8]) -> bool { + flatbuffers::buffer_has_identifier(buf, SCALAR_STUFF_IDENTIFIER, true) +} + +pub const SCALAR_STUFF_EXTENSION: &str = "mon"; + +#[inline] +pub fn finish_scalar_stuff_buffer<'a, 'b>( + fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, + root: flatbuffers::WIPOffset>) { + fbb.finish(root, Some(SCALAR_STUFF_IDENTIFIER)); +} + +#[inline] +pub fn finish_size_prefixed_scalar_stuff_buffer<'a, 'b>(fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, root: flatbuffers::WIPOffset>) { + fbb.finish_size_prefixed(root, Some(SCALAR_STUFF_IDENTIFIER)); +} } // pub mod optional_scalars diff --git a/tests/test.cpp b/tests/test.cpp index 7f3c7d34e..3f205603f 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -23,7 +23,6 @@ // clang-format off #ifdef FLATBUFFERS_CPP98_STL - #include "flatbuffers/stl_emulation.h" namespace std { using flatbuffers::unique_ptr; } @@ -35,6 +34,7 @@ #include "namespace_test/namespace_test2_generated.h" #include "union_vector/union_vector_generated.h" #include "monster_extra_generated.h" +#include "optional_scalars_generated.h" #if !defined(_MSC_VER) || _MSC_VER >= 1700 # include "arrays_test_generated.h" # include "evolution_test/evolution_v1_generated.h" @@ -3462,23 +3462,51 @@ void OptionalScalarsTest() { TEST_EQ(mana->optional, has_null); } - // Test if optional scalars are allowed for each language. - const int kNumLanguages = 17; - const auto supported = (flatbuffers::IDLOptions::kRust | - flatbuffers::IDLOptions::kSwift | - flatbuffers::IDLOptions::kKotlin | - flatbuffers::IDLOptions::kLobster); - for (int lang=0; langfind("null") != std::string::npos; flatbuffers::Parser parser(opts); - // Its not supported in any language yet so has_null means error. - TEST_EQ(parser.Parse(schema->c_str()), !has_null); + auto done = parser.Parse(schema->c_str()); + TEST_EQ_STR(parser.error_.c_str(), ""); + TEST_ASSERT(done); } } + + // test C++ nullable + flatbuffers::FlatBufferBuilder fbb; + FinishScalarStuffBuffer( + fbb, optional_scalars::CreateScalarStuff(fbb, 1, static_cast(2))); + auto opts = optional_scalars::GetMutableScalarStuff(fbb.GetBufferPointer()); + TEST_ASSERT(!opts->maybe_bool()); + TEST_ASSERT(!opts->maybe_f32().has_value()); + TEST_ASSERT(opts->maybe_i8().has_value()); + TEST_EQ(opts->maybe_i8().value(), 2); + TEST_ASSERT(opts->mutate_maybe_i8(3)); + TEST_ASSERT(opts->maybe_i8().has_value()); + TEST_EQ(opts->maybe_i8().value(), 3); + TEST_ASSERT(!opts->mutate_maybe_i16(-10)); + + optional_scalars::ScalarStuffT obj; + opts->UnPackTo(&obj); + TEST_ASSERT(!obj.maybe_bool); + TEST_ASSERT(!obj.maybe_f32.has_value()); + TEST_ASSERT(obj.maybe_i8.has_value() && obj.maybe_i8.value() == 3); + TEST_ASSERT(obj.maybe_i8 && *obj.maybe_i8 == 3); + obj.maybe_i32 = -1; + + fbb.Clear(); + FinishScalarStuffBuffer(fbb, optional_scalars::ScalarStuff::Pack(fbb, &obj)); + opts = optional_scalars::GetMutableScalarStuff(fbb.GetBufferPointer()); + TEST_ASSERT(opts->maybe_i8().has_value()); + TEST_EQ(opts->maybe_i8().value(), 3); + TEST_ASSERT(opts->maybe_i32().has_value()); + TEST_EQ(opts->maybe_i32().value(), -1); + TEST_ASSERT(opts->maybe_i32() == flatbuffers::Optional(-1)); } void ParseFlexbuffersFromJsonWithNullTest() {