diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-03-16 14:05:11 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-03-16 14:20:39 +0300 |
commit | 4e3ee6b12c3dacb5d556e9afad35dcd6efe58fa1 (patch) | |
tree | 7415c5c5bea98154299213abb536d01bcee6c8af | |
parent | d83e7ea91cbc5e5d4ea49195eeab84c364dba4bb (diff) | |
download | ydb-4e3ee6b12c3dacb5d556e9afad35dcd6efe58fa1.tar.gz |
Update contrib/libs/flatbuffers to 24.3.7
ba53b58280bb890a80379f491d436458add8f0ed
36 files changed, 1998 insertions, 183 deletions
diff --git a/build/conf/java.conf b/build/conf/java.conf index 6d4480b5c9..6e5c3bfe8f 100644 --- a/build/conf/java.conf +++ b/build/conf/java.conf @@ -781,7 +781,7 @@ macro JAVA_RESOURCE(JAR, SOURCES="") { } # tag:java-specific tag:fbs -JAVA_FLATBUFFERS_VERSION = 23.5.26 +JAVA_FLATBUFFERS_VERSION = 24.3.7 _KOTLIN_ALLOWED_VERSIONS = contrib/java/org/jetbrains/kotlin/kotlin-allopen/${_KOTLIN_VERSION} \ contrib/java/org/jetbrains/kotlin/kotlin-allopen-compiler-plugin/${_KOTLIN_VERSION} \ diff --git a/build/prebuilt/contrib/tools/flatc/resources.json b/build/prebuilt/contrib/tools/flatc/resources.json index e6fbd1a12c..24c205107d 100644 --- a/build/prebuilt/contrib/tools/flatc/resources.json +++ b/build/prebuilt/contrib/tools/flatc/resources.json @@ -1,19 +1,19 @@ { "by_platform": { "darwin": { - "uri": "sbr:5016255161" + "uri": "sbr:5983041213" }, "darwin-arm64": { - "uri": "sbr:5016250713" + "uri": "sbr:5983040151" }, "linux": { - "uri": "sbr:5016249124" + "uri": "sbr:5983042955" }, "linux-aarch64": { - "uri": "sbr:5016246978" + "uri": "sbr:5983042153" }, "win32-clang-cl": { - "uri": "sbr:5016265691" + "uri": "sbr:5983038870" } } } diff --git a/build/ymake.core.conf b/build/ymake.core.conf index 7db071847b..ecc43c8ecd 100644 --- a/build/ymake.core.conf +++ b/build/ymake.core.conf @@ -16,7 +16,7 @@ CLANG_TIDY_FAKEID=2023-06-06 CYTHON_FAKE_ID=10784829 JAVA_FAKEID=108490091 PROTO_FAKEID=0 -FBS_FAKEID=2023-09-01 +FBS_FAKEID=2024-03-13 # Change of this value will invalidate some parts of configure cache # but will not affect builds anyhow (except tests referring build/ directory) @@ -4457,7 +4457,7 @@ macro _DECL_IN_DIR_GLOB(var_prefix, pattern, rec_part, SRCDIR="", EXCLBASE="", E ### 6. Parameters of macro are somewhat validated and we may add extra checks in the fulture including protection over too broad match. ### macro DECLARE_IN_DIRS(var_prefix, PATTERN, SRCDIR="", RECURSIVE?"**/":"", EXCLUDES[], DIRS[]) { - _DECL_IN_DIR_GLOB($var_prefix $PATTERN $RECURSIVE ${pre=SRCDIR ;suf=/:SRCDIR} ${pre=EXCLBASE ${ARCADIA_ROOT}/**/ DUMMY :SRCDIR} EXCLUDES ${EXCLUDES} DIRS ${DIRS}) + _DECL_IN_DIR_GLOB($var_prefix $PATTERN $RECURSIVE ${pre=SRCDIR ;suf=/:SRCDIR} ${pre=EXCLBASE ${ARCADIA_ROOT}/**/ DUMMY :SRCDIR} EXCLUDES ${EXCLUDES} DIRS ${DIRS}) SET(${var_prefix}_FILES \$_${var_prefix}_FILES) SET(${var_prefix}_SRCDIR $SRCDIR) diff --git a/contrib/libs/flatbuffers/CHANGELOG.md b/contrib/libs/flatbuffers/CHANGELOG.md index 145c62b109..c7d1157f2f 100644 --- a/contrib/libs/flatbuffers/CHANGELOG.md +++ b/contrib/libs/flatbuffers/CHANGELOG.md @@ -4,6 +4,14 @@ All major or breaking changes will be documented in this file, as well as any new features that should be highlighted. Minor fixes or improvements are not necessarily listed. +## [24.3.7] (March 7 2024)(https://github.com/google/flatbuffers/releases/tag/v24.3.7) + +* Just to fix some of the CI build issues from the 24.3.6 release. + +## [24.3.6] (March 6 2024)(https://github.com/google/flatbuffers/releases/tag/v24.3.6) + +* Fix typescript object API to allow 0 values for null-default scalars (#7864) + ## [23.5.26 (May 26 2023)](https://github.com/google/flatbuffers/releases/tag/v23.5.26) * Mostly bug fixing for 64-bit support diff --git a/contrib/libs/flatbuffers/README.md b/contrib/libs/flatbuffers/README.md index 875c73bb9c..47d506720e 100644 --- a/contrib/libs/flatbuffers/README.md +++ b/contrib/libs/flatbuffers/README.md @@ -98,10 +98,7 @@ FlatBuffers does not follow traditional SemVer versioning (see [rationale](https ## Community -* [FlatBuffers Google Group][] to discuss FlatBuffers with other developers and users. * [Discord Server](https:///discord.gg/6qgKs3R) -* [Gitter](https://gitter.im/google/flatbuffers) - ## Security diff --git a/contrib/libs/flatbuffers/flatc/ya.make b/contrib/libs/flatbuffers/flatc/ya.make index 63f20cda2d..1b01423fab 100644 --- a/contrib/libs/flatbuffers/flatc/ya.make +++ b/contrib/libs/flatbuffers/flatc/ya.make @@ -52,6 +52,7 @@ SRCS( src/idl_gen_java.cpp src/idl_gen_json_schema.cpp src/idl_gen_kotlin.cpp + src/idl_gen_kotlin_kmp.cpp src/idl_gen_lobster.cpp src/idl_gen_php.cpp src/idl_gen_python.cpp diff --git a/contrib/libs/flatbuffers/include/flatbuffers/base.h b/contrib/libs/flatbuffers/include/flatbuffers/base.h index 506fd545d1..43cfae7fe5 100644 --- a/contrib/libs/flatbuffers/include/flatbuffers/base.h +++ b/contrib/libs/flatbuffers/include/flatbuffers/base.h @@ -139,9 +139,9 @@ #endif #endif // !defined(FLATBUFFERS_LITTLEENDIAN) -#define FLATBUFFERS_VERSION_MAJOR 23 -#define FLATBUFFERS_VERSION_MINOR 5 -#define FLATBUFFERS_VERSION_REVISION 26 +#define FLATBUFFERS_VERSION_MAJOR 24 +#define FLATBUFFERS_VERSION_MINOR 3 +#define FLATBUFFERS_VERSION_REVISION 7 #define FLATBUFFERS_STRING_EXPAND(X) #X #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) namespace flatbuffers { @@ -155,7 +155,7 @@ namespace flatbuffers { #define FLATBUFFERS_FINAL_CLASS final #define FLATBUFFERS_OVERRIDE override #define FLATBUFFERS_EXPLICIT_CPP11 explicit - #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t + #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : ::flatbuffers::voffset_t #else #define FLATBUFFERS_FINAL_CLASS #define FLATBUFFERS_OVERRIDE @@ -289,12 +289,12 @@ namespace flatbuffers { #define FLATBUFFERS_SUPPRESS_UBSAN(type) #endif -// This is constexpr function used for checking compile-time constants. -// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`. namespace flatbuffers { -template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) { - return !!t; -} + // This is constexpr function used for checking compile-time constants. + // Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`. + template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) { + return !!t; + } } // Enable C++ attribute [[]] if std:c++17 or higher. @@ -363,7 +363,6 @@ inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) { } #if defined(_MSC_VER) - #pragma warning(disable: 4351) // C4351: new behavior: elements of array ... will be default initialized #pragma warning(push) #pragma warning(disable: 4127) // C4127: conditional expression is constant #endif diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffer_builder.h b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffer_builder.h index f97daa4046..774b6bdba6 100644 --- a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffer_builder.h +++ b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffer_builder.h @@ -45,8 +45,9 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) { // Should correspond to what EndTable() below builds up. const voffset_t fixed_fields = 2 * sizeof(voffset_t); // Vtable size and Object Size. - return fixed_fields + field_id * sizeof(voffset_t); -} + size_t offset = fixed_fields + field_id * sizeof(voffset_t); + FLATBUFFERS_ASSERT(offset < std::numeric_limits<voffset_t>::max()); + return static_cast<voffset_t>(offset);} template<typename T, typename Alloc = std::allocator<T>> const T *data(const std::vector<T, Alloc> &v) { @@ -220,21 +221,13 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { /// @return Returns a `uint8_t` pointer to the unfinished buffer. uint8_t *GetCurrentBufferPointer() const { return buf_.data(); } - /// @brief Get the released pointer to the serialized buffer. - /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards! - /// @return A `FlatBuffer` that owns the buffer and its allocator and - /// behaves similar to a `unique_ptr` with a deleter. - FLATBUFFERS_ATTRIBUTE([[deprecated("use Release() instead")]]) - DetachedBuffer ReleaseBufferPointer() { - Finished(); - return buf_.release(); - } - /// @brief Get the released DetachedBuffer. /// @return A `DetachedBuffer` that owns the buffer and its allocator. DetachedBuffer Release() { Finished(); - return buf_.release(); + DetachedBuffer buffer = buf_.release(); + Clear(); + return buffer; } /// @brief Get the released pointer to the serialized buffer. @@ -245,10 +238,12 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { /// @return A raw pointer to the start of the memory block containing /// the serialized `FlatBuffer`. /// @remark If the allocator is owned, it gets deleted when the destructor is - /// called.. + /// called. uint8_t *ReleaseRaw(size_t &size, size_t &offset) { Finished(); - return buf_.release_raw(size, offset); + uint8_t* raw = buf_.release_raw(size, offset); + Clear(); + return raw; } /// @brief get the minimum alignment this buffer needs to be accessed @@ -566,7 +561,7 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { return CreateString<OffsetT>(str.c_str(), str.length()); } - // clang-format off +// clang-format off #ifdef FLATBUFFERS_HAS_STRING_VIEW /// @brief Store a string in the buffer, which can contain any binary data. /// @param[in] str A const string_view to copy in to the buffer. @@ -588,7 +583,7 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { /// @brief Store a string in the buffer, which can contain any binary data. /// @param[in] str A const reference to a std::string like type with support - /// of T::c_str() and T::length() to store in the buffer. + /// of T::data() and T::length() to store in the buffer. /// @return Returns the offset in the buffer where the string starts. template<template<typename> class OffsetT = Offset, // No need to explicitly declare the T type, let the compiler deduce @@ -698,12 +693,27 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { // normally dictate. // This is useful when storing a nested_flatbuffer in a vector of bytes, // or when storing SIMD floats, etc. - void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) { + void ForceVectorAlignment(const size_t len, const size_t elemsize, + const size_t alignment) { if (len == 0) return; FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment)); PreAlign(len * elemsize, alignment); } + template<bool is_64 = Is64Aware> + typename std::enable_if<is_64, void>::type ForceVectorAlignment64( + const size_t len, const size_t elemsize, const size_t alignment) { + // If you hit this assertion, you are trying to force alignment on a + // vector with offset64 after serializing a 32-bit offset. + FLATBUFFERS_ASSERT(GetSize() == length_of_64_bit_region_); + + // Call through. + ForceVectorAlignment(len, elemsize, alignment); + + // Update the 64 bit region. + length_of_64_bit_region_ = GetSize(); + } + // Similar to ForceVectorAlignment but for String fields. void ForceStringAlignment(size_t len, size_t alignment) { if (len == 0) return; @@ -733,7 +743,7 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { AssertScalarT<T>(); StartVector<T, OffsetT, LenT>(len); if (len > 0) { - // clang-format off +// clang-format off #if FLATBUFFERS_LITTLEENDIAN PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T)); #else @@ -864,7 +874,9 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { /// where the vector is stored. template<class It> Offset<Vector<Offset<String>>> CreateVectorOfStrings(It begin, It end) { - auto size = std::distance(begin, end); + auto distance = std::distance(begin, end); + FLATBUFFERS_ASSERT(distance >= 0); + auto size = static_cast<size_t>(distance); auto scratch_buffer_usage = size * sizeof(Offset<String>); // If there is not enough space to store the offsets, there definitely won't // be enough space to store all the strings. So ensuring space for the @@ -874,7 +886,7 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { buf_.scratch_push_small(CreateString(*it)); } StartVector<Offset<String>>(size); - for (auto i = 1; i <= size; i++) { + for (size_t i = 1; i <= size; i++) { // Note we re-evaluate the buf location each iteration to account for any // underlying buffer resizing that may occur. PushElement(*reinterpret_cast<Offset<String> *>( @@ -898,8 +910,7 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { typedef typename VectorT<T>::size_type LenT; typedef typename OffsetT<VectorT<const T *>>::offset_type offset_type; - StartVector<OffsetT, LenT>(len * sizeof(T) / AlignOf<T>(), sizeof(T), - AlignOf<T>()); + StartVector<OffsetT, LenT>(len, sizeof(T), AlignOf<T>()); if (len > 0) { PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len); } @@ -1244,6 +1255,9 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { FlatBufferBuilderImpl &operator=(const FlatBufferBuilderImpl &); void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) { + // A buffer can only be finished once. To reuse a builder use `clear()`. + FLATBUFFERS_ASSERT(!finished); + NotNested(); buf_.clear_scratch(); @@ -1369,8 +1383,7 @@ template<bool Is64Aware = false> class FlatBufferBuilderImpl { // Must be completed with EndVectorOfStructs(). template<typename T, template<typename> class OffsetT = Offset> T *StartVectorOfStructs(size_t vector_size) { - StartVector<OffsetT>(vector_size * sizeof(T) / AlignOf<T>(), sizeof(T), - AlignOf<T>()); + StartVector<OffsetT>(vector_size, sizeof(T), AlignOf<T>()); return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T))); } @@ -1456,7 +1469,7 @@ T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) { } template<typename T> -const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) { +const T *GetTemporaryPointer(const FlatBufferBuilder &fbb, Offset<T> offset) { return GetMutableTemporaryPointer<T>(fbb, offset); } diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h index 952ea3bcdf..1a81821b54 100644 --- a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h +++ b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h @@ -248,31 +248,31 @@ inline const char *flatbuffers_version_string() { // clang-format off #define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\ - inline E operator | (E lhs, E rhs){\ + inline FLATBUFFERS_CONSTEXPR_CPP11 E operator | (E lhs, E rhs){\ return E(T(lhs) | T(rhs));\ }\ - inline E operator & (E lhs, E rhs){\ + inline FLATBUFFERS_CONSTEXPR_CPP11 E operator & (E lhs, E rhs){\ return E(T(lhs) & T(rhs));\ }\ - inline E operator ^ (E lhs, E rhs){\ + inline FLATBUFFERS_CONSTEXPR_CPP11 E operator ^ (E lhs, E rhs){\ return E(T(lhs) ^ T(rhs));\ }\ - inline E operator ~ (E lhs){\ + inline FLATBUFFERS_CONSTEXPR_CPP11 E operator ~ (E lhs){\ return E(~T(lhs));\ }\ - inline E operator |= (E &lhs, E rhs){\ + inline FLATBUFFERS_CONSTEXPR_CPP11 E operator |= (E &lhs, E rhs){\ lhs = lhs | rhs;\ return lhs;\ }\ - inline E operator &= (E &lhs, E rhs){\ + inline FLATBUFFERS_CONSTEXPR_CPP11 E operator &= (E &lhs, E rhs){\ lhs = lhs & rhs;\ return lhs;\ }\ - inline E operator ^= (E &lhs, E rhs){\ + inline FLATBUFFERS_CONSTEXPR_CPP11 E operator ^= (E &lhs, E rhs){\ lhs = lhs ^ rhs;\ return lhs;\ }\ - inline bool operator !(E rhs) \ + inline FLATBUFFERS_CONSTEXPR_CPP11 bool operator !(E rhs) \ {\ return !bool(T(rhs)); \ } diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h b/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h index 1fdffb424e..7b5b20b701 100644 --- a/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h +++ b/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h @@ -360,16 +360,40 @@ class Map : public Vector { bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; } }; +inline void IndentString(std::string &s, int indent, + const char *indent_string) { + for (int i = 0; i < indent; i++) s += indent_string; +} + template<typename T> -void AppendToString(std::string &s, T &&v, bool keys_quoted) { - s += "[ "; +void AppendToString(std::string &s, T &&v, bool keys_quoted, bool indented, + int cur_indent, const char *indent_string) { + s += "["; + s += indented ? "\n" : " "; for (size_t i = 0; i < v.size(); i++) { - if (i) s += ", "; - v[i].ToString(true, keys_quoted, s); + if (i) { + s += ","; + s += indented ? "\n" : " "; + } + if (indented) IndentString(s, cur_indent, indent_string); + v[i].ToString(true, keys_quoted, s, indented, cur_indent, + indent_string); } - s += " ]"; + if (indented) { + s += "\n"; + IndentString(s, cur_indent - 1, indent_string); + } else { + s += " "; + } + s += "]"; } +template<typename T> +void AppendToString(std::string &s, T &&v, bool keys_quoted) { + AppendToString(s, v, keys_quoted); +} + + class Reference { public: Reference() @@ -542,8 +566,13 @@ class Reference { // Convert any type to a JSON-like string. strings_quoted determines if // string values at the top level receive "" quotes (inside other values // they always do). keys_quoted determines if keys are quoted, at any level. - // TODO(wvo): add further options to have indentation/newlines. void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const { + ToString(strings_quoted, keys_quoted, s, false, 0, ""); + } + + // This version additionally allow you to specify if you want indentation. + void ToString(bool strings_quoted, bool keys_quoted, std::string &s, + bool indented, int cur_indent, const char *indent_string) const { if (type_ == FBT_STRING) { String str(Indirect(), byte_width_); if (strings_quoted) { @@ -569,7 +598,8 @@ class Reference { } else if (IsBool()) { s += AsBool() ? "true" : "false"; } else if (IsMap()) { - s += "{ "; + s += "{"; + s += indented ? "\n" : " "; auto m = AsMap(); auto keys = m.Keys(); auto vals = m.Values(); @@ -590,18 +620,28 @@ class Reference { } } } + if (indented) IndentString(s, cur_indent + 1, indent_string); keys[i].ToString(true, kq, s); s += ": "; - vals[i].ToString(true, keys_quoted, s); - if (i < keys.size() - 1) s += ", "; + vals[i].ToString(true, keys_quoted, s, indented, cur_indent + 1, indent_string); + if (i < keys.size() - 1) { + s += ","; + if (!indented) s += " "; + } + if (indented) s += "\n"; } - s += " }"; + if (!indented) s += " "; + if (indented) IndentString(s, cur_indent, indent_string); + s += "}"; } else if (IsVector()) { - AppendToString<Vector>(s, AsVector(), keys_quoted); + AppendToString<Vector>(s, AsVector(), keys_quoted, indented, + cur_indent + 1, indent_string); } else if (IsTypedVector()) { - AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted); + AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted, indented, + cur_indent + 1, indent_string); } else if (IsFixedTypedVector()) { - AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted); + AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted, + indented, cur_indent + 1, indent_string); } else if (IsBlob()) { auto blob = AsBlob(); flatbuffers::EscapeString(reinterpret_cast<const char *>(blob.data()), @@ -1128,10 +1168,7 @@ class Builder FLATBUFFERS_FINAL_CLASS { size_t EndMap(size_t start) { // We should have interleaved keys and values on the stack. - // Make sure it is an even number: - auto len = stack_.size() - start; - FLATBUFFERS_ASSERT(!(len & 1)); - len /= 2; + auto len = MapElementCount(start); // Make sure keys are all strings: for (auto key = start; key < stack_.size(); key += 2) { FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY); @@ -1289,6 +1326,14 @@ class Builder FLATBUFFERS_FINAL_CLASS { EndMap(start); } + size_t MapElementCount(size_t start) { + // Make sure it is an even number: + auto len = stack_.size() - start; + FLATBUFFERS_ASSERT(!(len & 1)); + len /= 2; + return len; + } + // If you wish to share a value explicitly (a value not shared automatically // through one of the BUILDER_FLAG_SHARE_* flags) you can do so with these // functions. Or if you wish to turn those flags off for performance reasons @@ -1307,6 +1352,12 @@ class Builder FLATBUFFERS_FINAL_CLASS { ReuseValue(v); } + // Undo the last element serialized. Call once for a value and once for a + // key. + void Undo() { + stack_.pop_back(); + } + // Overloaded Add that tries to call the correct function above. void Add(int8_t i) { Int(i); } void Add(int16_t i) { Int(i); } @@ -1669,7 +1720,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS { max_vectors_(buf_len), check_alignment_(_check_alignment), reuse_tracker_(reuse_tracker) { - FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE); + FLATBUFFERS_ASSERT(static_cast<int32_t>(size_) < FLATBUFFERS_MAX_BUFFER_SIZE); if (reuse_tracker_) { reuse_tracker_->clear(); reuse_tracker_->resize(size_, PackedType(BIT_WIDTH_8, FBT_NULL)); diff --git a/contrib/libs/flatbuffers/include/flatbuffers/idl.h b/contrib/libs/flatbuffers/include/flatbuffers/idl.h index f65f18a9ab..9b9e98fcf4 100644 --- a/contrib/libs/flatbuffers/include/flatbuffers/idl.h +++ b/contrib/libs/flatbuffers/include/flatbuffers/idl.h @@ -342,7 +342,10 @@ struct FieldDef : public Definition { bool Deserialize(Parser &parser, const reflection::Field *field); bool IsScalarOptional() const { - return IsScalar(value.type.base_type) && IsOptional(); + return IsScalar() && IsOptional(); + } + bool IsScalar() const { + return ::flatbuffers::IsScalar(value.type.base_type); } bool IsOptional() const { return presence == kOptional; } bool IsRequired() const { return presence == kRequired; } @@ -673,6 +676,7 @@ struct IDLOptions { bool binary_schema_comments; bool binary_schema_builtins; bool binary_schema_gen_embed; + bool binary_schema_absolute_paths; std::string go_import; std::string go_namespace; std::string go_module_name; @@ -703,6 +707,7 @@ struct IDLOptions { bool keep_proto_id; bool python_no_type_prefix_suffix; bool python_typing; + bool ts_omit_entrypoint; ProtoIdGapAction proto_id_gap_action; // Possible options for the more general generator below. @@ -726,6 +731,7 @@ struct IDLOptions { kCppYandexMapsIter = 1 << 19, kNim = 1 << 17, kProto = 1 << 18, + kKotlinKmp = 1 << 19, kMAX }; @@ -792,6 +798,7 @@ struct IDLOptions { binary_schema_comments(false), binary_schema_builtins(false), binary_schema_gen_embed(false), + binary_schema_absolute_paths(false), protobuf_ascii_alike(false), size_prefixed(false), force_defaults(false), @@ -815,6 +822,7 @@ struct IDLOptions { keep_proto_id(false), python_no_type_prefix_suffix(false), python_typing(false), + ts_omit_entrypoint(false), proto_id_gap_action(ProtoIdGapAction::WARNING), mini_reflect(IDLOptions::kNone), require_explicit_ids(false), @@ -1215,6 +1223,16 @@ class Parser : public ParserState { // These functions return nullptr on success, or an error string, // which may happen if the flatbuffer cannot be encoded in JSON (e.g., // it contains non-UTF-8 byte arrays in String values). +extern bool GenerateTextFromTable(const Parser &parser, + const void *table, + const std::string &tablename, + std::string *text); +extern const char *GenerateText(const Parser &parser, const void *flatbuffer, + std::string *text); +extern const char *GenerateTextFile(const Parser &parser, + const std::string &path, + const std::string &file_name); + extern const char *GenTextFromTable(const Parser &parser, const void *table, const std::string &tablename, std::string *text); diff --git a/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h b/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h index 4690434db6..9f83dcb5d4 100644 --- a/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h +++ b/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h @@ -8,9 +8,9 @@ // Ensure the included flatbuffers.h is the same version as when this file was // generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && - FLATBUFFERS_VERSION_MINOR == 5 && - FLATBUFFERS_VERSION_REVISION == 26, +static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && + FLATBUFFERS_VERSION_MINOR == 3 && + FLATBUFFERS_VERSION_REVISION == 7, "Non-compatible flatbuffers version included"); namespace reflection { diff --git a/contrib/libs/flatbuffers/include/flatbuffers/stl_emulation.h b/contrib/libs/flatbuffers/include/flatbuffers/stl_emulation.h index c085952b60..6054f78fa6 100644 --- a/contrib/libs/flatbuffers/include/flatbuffers/stl_emulation.h +++ b/contrib/libs/flatbuffers/include/flatbuffers/stl_emulation.h @@ -45,7 +45,8 @@ // Testing __cpp_lib_span requires including either <version> or <span>, // both of which were added in C++20. // See: https://en.cppreference.com/w/cpp/utility/feature_test - #if defined(__cplusplus) && __cplusplus >= 202002L + #if defined(__cplusplus) && __cplusplus >= 202002L \ + || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) #define FLATBUFFERS_USE_STD_SPAN 1 #endif #endif // FLATBUFFERS_USE_STD_SPAN diff --git a/contrib/libs/flatbuffers/include/flatbuffers/string.h b/contrib/libs/flatbuffers/include/flatbuffers/string.h index e6b98f0c9f..d33fbfaa88 100644 --- a/contrib/libs/flatbuffers/include/flatbuffers/string.h +++ b/contrib/libs/flatbuffers/include/flatbuffers/string.h @@ -31,6 +31,11 @@ struct String : public Vector<char> { flatbuffers::string_view string_view() const { return flatbuffers::string_view(c_str(), size()); } + + /* implicit */ + operator flatbuffers::string_view() const { + return flatbuffers::string_view(c_str(), size()); + } #endif // FLATBUFFERS_HAS_STRING_VIEW // clang-format on diff --git a/contrib/libs/flatbuffers/include/flatbuffers/util.h b/contrib/libs/flatbuffers/include/flatbuffers/util.h index c781b7e233..6151f4e025 100644 --- a/contrib/libs/flatbuffers/include/flatbuffers/util.h +++ b/contrib/libs/flatbuffers/include/flatbuffers/util.h @@ -479,6 +479,11 @@ std::string PosixPath(const std::string &path); // creating dirs for any parts of the path that don't exist yet. void EnsureDirExists(const std::string &filepath); +// Obtains the relative or absolute path. +std::string FilePath(const std::string &project, + const std::string &filePath, + bool absolute); + // Obtains the absolute path from any other path. // Returns the input path if the absolute path couldn't be resolved. std::string AbsolutePath(const std::string &filepath); diff --git a/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp b/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp index a8f4ee0c74..25da044d1a 100644 --- a/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp +++ b/contrib/libs/flatbuffers/src/bfbs_gen_nim.cpp @@ -77,7 +77,6 @@ Namer::Config NimDefaultConfig() { /*filename_extension=*/".nim" }; } -const std::string Indent = " "; const std::string Export = "*"; const std::set<std::string> builtin_types = { "uint8", "uint8", "bool", "int8", "uint8", "int16", diff --git a/contrib/libs/flatbuffers/src/flatc.cpp b/contrib/libs/flatbuffers/src/flatc.cpp index 202c3d644a..f29d109264 100644 --- a/contrib/libs/flatbuffers/src/flatc.cpp +++ b/contrib/libs/flatbuffers/src/flatc.cpp @@ -187,6 +187,7 @@ const static FlatCOption flatc_options[] = { "relative to. The 'root' is denoted with `//`. E.g. if PATH=/a/b/c " "then /a/d/e.fbs will be serialized as //../d/e.fbs. (PATH defaults to the " "directory of the first provided schema file." }, + { "", "bfbs-absolute-paths", "", "Uses absolute paths instead of relative paths in the BFBS output." }, { "", "bfbs-comments", "", "Add doc comments to the binary schema files." }, { "", "bfbs-builtins", "", "Add builtin attributes to the binary schema files." }, @@ -253,6 +254,8 @@ const static FlatCOption flatc_options[] = { { "", "python-no-type-prefix-suffix", "", "Skip emission of Python functions that are prefixed with typenames" }, { "", "python-typing", "", "Generate Python type annotations" }, + { "", "ts-omit-entrypoint", "", + "Omit emission of namespace entrypoint file" }, { "", "file-names-only", "", "Print out generated file names without writing to the files" }, }; @@ -594,6 +597,8 @@ FlatCOptions FlatCompiler::ParseFromCommandLineArguments(int argc, opts.binary_schema_builtins = true; } else if (arg == "--bfbs-gen-embed") { opts.binary_schema_gen_embed = true; + } else if (arg == "--bfbs-absolute-paths") { + opts.binary_schema_absolute_paths = true; } else if (arg == "--reflect-types") { opts.mini_reflect = IDLOptions::kTypes; } else if (arg == "--reflect-names") { @@ -659,6 +664,8 @@ FlatCOptions FlatCompiler::ParseFromCommandLineArguments(int argc, opts.python_no_type_prefix_suffix = true; } else if (arg == "--python-typing") { opts.python_typing = true; + } else if (arg == "--ts-omit-entrypoint") { + opts.ts_omit_entrypoint = true; } else if (arg == "--annotate-sparse-vectors") { options.annotate_include_vector_contents = false; } else if (arg == "--annotate") { @@ -720,6 +727,11 @@ void FlatCompiler::ValidateOptions(const FlatCOptions &options) { flatbuffers::Parser FlatCompiler::GetConformParser( const FlatCOptions &options) { flatbuffers::Parser conform_parser; + + // conform parser should check advanced options, + // so, it have to have knowledge about languages: + conform_parser.opts.lang_to_generate = options.opts.lang_to_generate; + if (!options.conform_to_schema.empty()) { std::string contents; if (!flatbuffers::LoadFile(options.conform_to_schema.c_str(), true, diff --git a/contrib/libs/flatbuffers/src/flatc_main.cpp b/contrib/libs/flatbuffers/src/flatc_main.cpp index f2dde958d3..a65804f4d3 100644 --- a/contrib/libs/flatbuffers/src/flatc_main.cpp +++ b/contrib/libs/flatbuffers/src/flatc_main.cpp @@ -127,6 +127,11 @@ int main(int argc, const char *argv[]) { flatbuffers::NewKotlinCodeGenerator()); flatc.RegisterCodeGenerator( + flatbuffers::FlatCOption{ "", "kotlin-kmp", "", + "Generate Kotlin multiplatform classes for tables/structs" }, + flatbuffers::NewKotlinKMPCodeGenerator()); + + flatc.RegisterCodeGenerator( flatbuffers::FlatCOption{ "", "lobster", "", "Generate Lobster files for tables/structs" }, flatbuffers::NewLobsterCodeGenerator()); @@ -162,16 +167,16 @@ int main(int argc, const char *argv[]) { flatbuffers::NewTextCodeGenerator()); flatc.RegisterCodeGenerator( - flatbuffers::FlatCOption{ "", "swift", "", - "Generate Swift files for tables/structs" }, - flatbuffers::NewSwiftCodeGenerator()); - - flatc.RegisterCodeGenerator( flatbuffers::FlatCOption{ "", "yandex-maps-iter", "", "Generate C++ template headers for tables/structs" }, flatbuffers::NewCppYandexMapsIterCodeGenerator()); flatc.RegisterCodeGenerator( + flatbuffers::FlatCOption{ "", "swift", "", + "Generate Swift files for tables/structs" }, + flatbuffers::NewSwiftCodeGenerator()); + + flatc.RegisterCodeGenerator( flatbuffers::FlatCOption{ "T", "ts", "", "Generate TypeScript code for tables/structs" }, flatbuffers::NewTsCodeGenerator()); diff --git a/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp b/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp index 21a21b8370..47fd153347 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp @@ -777,10 +777,10 @@ class CppGenerator : public BaseGenerator { if (type.enum_def) return WrapInNameSpace(*type.enum_def); if (type.base_type == BASE_TYPE_BOOL) return "bool"; } - // Get real underlying type for union type + // Get real underlying type for union type auto base_type = type.base_type; if (type.base_type == BASE_TYPE_UTYPE && type.enum_def != nullptr) { - base_type = type.enum_def->underlying_type.base_type; + base_type = type.enum_def->underlying_type.base_type; } return StringOf(base_type); } @@ -1051,7 +1051,9 @@ class CppGenerator : public BaseGenerator { std::string UnionVectorVerifySignature(const EnumDef &enum_def) { const std::string name = Name(enum_def); - const std::string &type = opts_.scoped_enums ? name : GenTypeBasic(enum_def.underlying_type, false); + const std::string &type = + opts_.scoped_enums ? name + : GenTypeBasic(enum_def.underlying_type, false); return "bool Verify" + name + "Vector" + "(::flatbuffers::Verifier &verifier, " + "const ::flatbuffers::Vector<::flatbuffers::Offset<void>> " @@ -2930,8 +2932,10 @@ class CppGenerator : public BaseGenerator { const std::string &type = IsStruct(vtype) ? WrapInNameSpace(*vtype.struct_def) : GenTypeWire(vtype, "", false, field.offset64); - return "_fbb.ForceVectorAlignment(" + field_size + ", sizeof(" + type + - "), " + std::to_string(static_cast<long long>(align)) + ");"; + return std::string("_fbb.ForceVectorAlignment") + + (field.offset64 ? "64" : "") + "(" + field_size + ", sizeof(" + + type + "), " + std::to_string(static_cast<long long>(align)) + + ");"; } return ""; } @@ -3505,7 +3509,8 @@ class CppGenerator : public BaseGenerator { : underlying_type; auto enum_value = "__va->_" + value + "[i].type"; if (!opts_.scoped_enums) - enum_value = "static_cast<" + underlying_type + ">(" + enum_value + ")"; + enum_value = + "static_cast<" + underlying_type + ">(" + enum_value + ")"; code += "_fbb.CreateVector<" + type + ">(" + value + ".size(), [](size_t i, _VectorArgs *__va) { return " + diff --git a/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp b/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp index 369460d730..bc84ed6643 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp @@ -431,6 +431,10 @@ class CSharpGenerator : public BaseGenerator { if (opts.generate_object_based_api) { GenEnum_ObjectAPI(enum_def, code_ptr, opts); } + + if (enum_def.is_union) { + code += GenUnionVerify(enum_def.underlying_type); + } } bool HasUnionStringValue(const EnumDef &enum_def) const { @@ -846,7 +850,7 @@ class CSharpGenerator : public BaseGenerator { // Force compile time error if not using the same version runtime. code += " public static void ValidateVersion() {"; code += " FlatBufferConstants."; - code += "FLATBUFFERS_23_5_26(); "; + code += "FLATBUFFERS_24_3_7(); "; code += "}\n"; // Generate a special accessor for the table that when used as the root @@ -1755,8 +1759,6 @@ class CSharpGenerator : public BaseGenerator { code += " }\n"; code += "}\n\n"; - code += GenUnionVerify(enum_def.underlying_type); - // JsonConverter if (opts.cs_gen_json_serializer) { if (enum_def.attributes.Lookup("private")) { diff --git a/contrib/libs/flatbuffers/src/idl_gen_go.cpp b/contrib/libs/flatbuffers/src/idl_gen_go.cpp index e1e84a0e58..6bbc5dc892 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_go.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_go.cpp @@ -102,6 +102,25 @@ class GoGenerator : public BaseGenerator { bool generate() { std::string one_file_code; + + if (!generateEnums(&one_file_code)) return false; + if (!generateStructs(&one_file_code)) return false; + + if (parser_.opts.one_file) { + std::string code = ""; + const bool is_enum = !parser_.enums_.vec.empty(); + BeginFile(LastNamespacePart(go_namespace_), true, is_enum, &code); + code += one_file_code; + const std::string filename = + GeneratedFileName(path_, file_name_, parser_.opts); + return SaveFile(filename.c_str(), code, false); + } + + return true; + } + + private: + bool generateEnums(std::string *one_file_code) { bool needs_imports = false; for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); ++it) { @@ -109,47 +128,46 @@ class GoGenerator : public BaseGenerator { needs_imports = false; ResetImports(); } + auto &enum_def = **it; std::string enumcode; - GenEnum(**it, &enumcode); - if ((*it)->is_union && parser_.opts.generate_object_based_api) { - GenNativeUnion(**it, &enumcode); - GenNativeUnionPack(**it, &enumcode); - GenNativeUnionUnPack(**it, &enumcode); + GenEnum(enum_def, &enumcode); + if (enum_def.is_union && parser_.opts.generate_object_based_api) { + GenNativeUnionCreator(enum_def, &enumcode); needs_imports = true; } if (parser_.opts.one_file) { - one_file_code += enumcode; + *one_file_code += enumcode; } else { - if (!SaveType(**it, enumcode, needs_imports, true)) return false; + if (!SaveType(enum_def, enumcode, needs_imports, true)) return false; } } + return true; + } + + void GenNativeUnionCreator(const EnumDef &enum_def, std::string *code_ptr) { + if (enum_def.generated) return; + GenNativeUnion(enum_def, code_ptr); + GenNativeUnionPack(enum_def, code_ptr); + GenNativeUnionUnPack(enum_def, code_ptr); + } + + bool generateStructs(std::string *one_file_code) { for (auto it = parser_.structs_.vec.begin(); it != parser_.structs_.vec.end(); ++it) { if (!parser_.opts.one_file) { ResetImports(); } std::string declcode; - GenStruct(**it, &declcode); + auto &struct_def = **it; + GenStruct(struct_def, &declcode); if (parser_.opts.one_file) { - one_file_code += declcode; + *one_file_code += declcode; } else { - if (!SaveType(**it, declcode, true, false)) return false; + if (!SaveType(struct_def, declcode, true, false)) return false; } } - - if (parser_.opts.one_file) { - std::string code = ""; - const bool is_enum = !parser_.enums_.vec.empty(); - BeginFile(LastNamespacePart(go_namespace_), true, is_enum, &code); - code += one_file_code; - const std::string filename = - GeneratedFileName(path_, file_name_, parser_.opts); - return SaveFile(filename.c_str(), code, false); - } - return true; } - private: Namespace go_namespace_; Namespace *cur_name_space_; const IdlNamer namer_; @@ -176,7 +194,8 @@ class GoGenerator : public BaseGenerator { code += "type " + namer_.Type(struct_def) + " struct {\n\t"; - // _ is reserved in flatbuffers field names, so no chance of name conflict: + // _ is reserved in flatbuffers field names, so no chance of name + // conflict: code += "_tab "; code += struct_def.fixed ? "flatbuffers.Struct" : "flatbuffers.Table"; code += "\n}\n\n"; @@ -1012,6 +1031,8 @@ class GoGenerator : public BaseGenerator { } void GenNativeUnion(const EnumDef &enum_def, std::string *code_ptr) { + if (enum_def.generated) return; + std::string &code = *code_ptr; code += "type " + NativeName(enum_def) + " struct {\n"; code += "\tType " + namer_.Type(enum_def) + "\n"; @@ -1020,6 +1041,8 @@ class GoGenerator : public BaseGenerator { } void GenNativeUnionPack(const EnumDef &enum_def, std::string *code_ptr) { + if (enum_def.generated) return; + std::string &code = *code_ptr; code += "func (t *" + NativeName(enum_def) + ") Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {\n"; @@ -1040,6 +1063,8 @@ class GoGenerator : public BaseGenerator { } void GenNativeUnionUnPack(const EnumDef &enum_def, std::string *code_ptr) { + if (enum_def.generated) return; + std::string &code = *code_ptr; code += "func (rcv " + namer_.Type(enum_def) + diff --git a/contrib/libs/flatbuffers/src/idl_gen_java.cpp b/contrib/libs/flatbuffers/src/idl_gen_java.cpp index 252c60f6d9..331d945984 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_java.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_java.cpp @@ -701,7 +701,7 @@ class JavaGenerator : public BaseGenerator { // Force compile time error if not using the same version runtime. code += " public static void ValidateVersion() {"; code += " Constants."; - code += "FLATBUFFERS_23_5_26(); "; + code += "FLATBUFFERS_24_3_7(); "; code += "}\n"; // Generate a special accessor for the table that when used as the root diff --git a/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp b/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp index ecea21edc9..ab1433ae33 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp @@ -524,7 +524,7 @@ class KotlinGenerator : public BaseGenerator { // runtime. GenerateFunOneLine( writer, "validateVersion", "", "", - [&]() { writer += "Constants.FLATBUFFERS_23_5_26()"; }, + [&]() { writer += "Constants.FLATBUFFERS_24_3_7()"; }, options.gen_jvmstatic); GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options); diff --git a/contrib/libs/flatbuffers/src/idl_gen_kotlin.h b/contrib/libs/flatbuffers/src/idl_gen_kotlin.h index 22d8ff6ca3..c3861a2c16 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_kotlin.h +++ b/contrib/libs/flatbuffers/src/idl_gen_kotlin.h @@ -24,6 +24,8 @@ namespace flatbuffers { // Constructs a new Kotlin code generator. std::unique_ptr<CodeGenerator> NewKotlinCodeGenerator(); +// Constructs a new Kotlin code generator. +std::unique_ptr<CodeGenerator> NewKotlinKMPCodeGenerator(); } // namespace flatbuffers #endif // FLATBUFFERS_IDL_GEN_KOTLIN_H_ diff --git a/contrib/libs/flatbuffers/src/idl_gen_kotlin_kmp.cpp b/contrib/libs/flatbuffers/src/idl_gen_kotlin_kmp.cpp new file mode 100644 index 0000000000..2dba494256 --- /dev/null +++ b/contrib/libs/flatbuffers/src/idl_gen_kotlin_kmp.cpp @@ -0,0 +1,1619 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// independent from idl_parser, since this code is not needed for most clients + +#include <functional> +#include <unordered_set> + +#include "flatbuffers/code_generators.h" +#include "flatbuffers/idl.h" +#include "flatbuffers/util.h" +#include "idl_gen_kotlin.h" +#include "idl_namer.h" + +namespace flatbuffers { + +namespace kotlin { + +namespace { + +typedef std::map<std::string, std::pair<std::string, std::string> > FbbParamMap; +static TypedFloatConstantGenerator KotlinFloatGen("Double.", "Float.", "NaN", + "POSITIVE_INFINITY", + "NEGATIVE_INFINITY"); + +static const CommentConfig comment_config = { "/**", " *", " */" }; +static const std::string ident_pad = " "; +static std::set<std::string> KotlinKeywords() { + return { "package", "as", "typealias", "class", "this", "super", + "val", "var", "fun", "for", "null", "true", + "false", "is", "in", "throw", "return", "break", + "continue", "object", "if", "try", "else", "while", + "do", "when", "interface", "typeof", "Any", "Character" }; +} + +static Namer::Config KotlinDefaultConfig() { + return { /*types=*/Case::kKeep, + /*constants=*/Case::kUpperCamel, + /*methods=*/Case::kLowerCamel, + /*functions=*/Case::kKeep, + /*fields=*/Case::kLowerCamel, + /*variables=*/Case::kLowerCamel, + /*variants=*/Case::kUpperCamel, + /*enum_variant_seperator=*/"", // I.e. Concatenate. + /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase, + /*namespaces=*/Case::kLowerCamel, + /*namespace_seperator=*/".", + /*object_prefix=*/"", + /*object_suffix=*/"T", + /*keyword_prefix=*/"", + /*keyword_suffix=*/"E", + /*filenames=*/Case::kUpperCamel, + /*directories=*/Case::kLowerCamel, + /*output_path=*/"", + /*filename_suffix=*/"", + /*filename_extension=*/".kt" }; +} +} // namespace + +class KotlinKMPGenerator : public BaseGenerator { + public: + KotlinKMPGenerator(const Parser &parser, const std::string &path, + const std::string &file_name) + : BaseGenerator(parser, path, file_name, "", ".", "kt"), + namer_(WithFlagOptions(KotlinDefaultConfig(), parser.opts, path), + KotlinKeywords()) {} + + KotlinKMPGenerator &operator=(const KotlinKMPGenerator &); + bool generate() FLATBUFFERS_OVERRIDE { + std::string one_file_code; + + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + CodeWriter enumWriter(ident_pad); + auto &enum_def = **it; + + GenEnum(enum_def, enumWriter); + enumWriter += ""; + GenEnumOffsetAlias(enum_def, enumWriter); + + if (parser_.opts.one_file) { + one_file_code += enumWriter.ToString(); + } else { + if (!SaveType(namer_.EscapeKeyword(enum_def.name), + *enum_def.defined_namespace, enumWriter.ToString(), true)) + return false; + } + } + + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + CodeWriter structWriter(ident_pad); + auto &struct_def = **it; + + GenStruct(struct_def, structWriter, parser_.opts); + structWriter += ""; + GenStructOffsetAlias(struct_def, structWriter); + + if (parser_.opts.one_file) { + one_file_code += structWriter.ToString(); + } else { + if (!SaveType(namer_.EscapeKeyword(struct_def.name), + *struct_def.defined_namespace, structWriter.ToString(), + true)) + return false; + } + } + + if (parser_.opts.one_file) { + return SaveType(file_name_, *parser_.current_namespace_, one_file_code, + true); + } + return true; + } + + std::string TypeInNameSpace(const Namespace *ns, + const std::string &name = "") const { + auto qualified = namer_.Namespace(*ns); + return qualified.empty() ? name : qualified + qualifying_separator_ + name; + } + + std::string TypeInNameSpace(const Definition &def, + const std::string &suffix = "") const { + return TypeInNameSpace(def.defined_namespace, def.name + suffix); + } + + // Save out the generated code for a single class while adding + // declaration boilerplate. + bool SaveType(const std::string &defname, const Namespace &ns, + const std::string &classcode, bool needs_includes) const { + if (!classcode.length()) return true; + + std::string code = + "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n"; + auto qualified = ns.GetFullyQualifiedName(""); + std::string namespace_name = namer_.Namespace(ns); + if (!namespace_name.empty()) { + code += "package " + namespace_name; + code += "\n\n"; + } + if (needs_includes) { code += "import com.google.flatbuffers.kotlin.*\n"; } + code += "import kotlin.jvm.JvmInline\n"; + code += classcode; + const std::string dirs = + namer_.Directories(ns, SkipDir::None, Case::kUnknown); + EnsureDirExists(dirs); + const std::string filename = + dirs + namer_.File(defname, /*skips=*/SkipFile::Suffix); + return SaveFile(filename.c_str(), code, false); + } + + static bool IsEnum(const Type &type) { + return type.enum_def != nullptr && IsInteger(type.base_type); + } + + std::string GenerateKotlinPrimiteArray(const Type &type) const { + if (IsScalar(type.base_type) && !IsEnum(type)) { return GenType(type); } + + if (IsEnum(type) || type.base_type == BASE_TYPE_UTYPE) { + return TypeInNameSpace(type.enum_def->defined_namespace, + namer_.Type(*type.enum_def)); + } + switch (type.base_type) { + case BASE_TYPE_STRUCT: + return "Offset<" + TypeInNameSpace(*type.struct_def) + ">"; + case BASE_TYPE_UNION: return "UnionOffset"; + case BASE_TYPE_STRING: return "Offset<String>"; + case BASE_TYPE_UTYPE: return "Offset<UByte>"; + default: return "Offset<" + GenTypeBasic(type.element) + ">"; + } + } + + std::string GenerateKotlinOffsetArray(const Type &type) const { + if (IsScalar(type.base_type) && !IsEnum(type)) { + return GenType(type) + "Array"; + } + + if (IsEnum(type) || type.base_type == BASE_TYPE_UTYPE) { + return TypeInNameSpace(type.enum_def->defined_namespace, + namer_.Type(*type.enum_def) + "Array"); + } + switch (type.base_type) { + case BASE_TYPE_STRUCT: + return TypeInNameSpace(*type.struct_def) + "OffsetArray"; + case BASE_TYPE_UNION: return "UnionOffsetArray"; + case BASE_TYPE_STRING: return "StringOffsetArray"; + case BASE_TYPE_UTYPE: return "UByteArray"; + default: return GenTypeBasic(type.element) + "OffsetArray"; + } + } + + std::string GenTypeBasic(const BaseType &type) const { + switch (type) { + case BASE_TYPE_NONE: + case BASE_TYPE_UTYPE: return "UByte"; + case BASE_TYPE_BOOL: return "Boolean"; + case BASE_TYPE_CHAR: return "Byte"; + case BASE_TYPE_UCHAR: return "UByte"; + case BASE_TYPE_SHORT: return "Short"; + case BASE_TYPE_USHORT: return "UShort"; + case BASE_TYPE_INT: return "Int"; + case BASE_TYPE_UINT: return "UInt"; + case BASE_TYPE_LONG: return "Long"; + case BASE_TYPE_ULONG: return "ULong"; + case BASE_TYPE_FLOAT: return "Float"; + case BASE_TYPE_DOUBLE: return "Double"; + case BASE_TYPE_STRING: + case BASE_TYPE_STRUCT: return "Offset"; + case BASE_TYPE_UNION: return "UnionOffset"; + case BASE_TYPE_VECTOR: + case BASE_TYPE_ARRAY: return "VectorOffset"; + // VECTOR64 not supported + case BASE_TYPE_VECTOR64: FLATBUFFERS_ASSERT(0); + } + return "Int"; + } + + std::string GenType(const Type &type) const { + auto base_type = GenTypeBasic(type.base_type); + + if (IsEnum(type) || type.base_type == BASE_TYPE_UTYPE) { + return TypeInNameSpace(type.enum_def->defined_namespace, + namer_.Type(*type.enum_def)); + } + switch (type.base_type) { + case BASE_TYPE_ARRAY: + case BASE_TYPE_VECTOR: { + switch (type.element) { + case BASE_TYPE_STRUCT: + return base_type + "<" + TypeInNameSpace(*type.struct_def) + ">"; + case BASE_TYPE_UNION: + return base_type + "<" + GenTypeBasic(type.element) + ">"; + case BASE_TYPE_STRING: return base_type + "<String>"; + case BASE_TYPE_UTYPE: return base_type + "<UByte>"; + default: return base_type + "<" + GenTypeBasic(type.element) + ">"; + } + } + case BASE_TYPE_STRUCT: + return base_type + "<" + TypeInNameSpace(*type.struct_def) + ">"; + case BASE_TYPE_STRING: return base_type + "<String>"; + case BASE_TYPE_UNION: return base_type; + default: return base_type; + } + // clang-format on + } + + std::string GenTypePointer(const Type &type) const { + switch (type.base_type) { + case BASE_TYPE_STRING: return "String"; + case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType()); + case BASE_TYPE_STRUCT: return TypeInNameSpace(*type.struct_def); + default: return "Table"; + } + } + + // with the addition of optional scalar types, + // we are adding the nullable '?' operator to return type of a field. + std::string GetterReturnType(const FieldDef &field) const { + auto base_type = field.value.type.base_type; + + auto r_type = GenTypeGet(field.value.type); + if (field.IsScalarOptional() || + // string, structs and unions + (base_type == BASE_TYPE_STRING || base_type == BASE_TYPE_STRUCT || + base_type == BASE_TYPE_UNION) || + // vector of anything not scalar + (base_type == BASE_TYPE_VECTOR && + !IsScalar(field.value.type.VectorType().base_type))) { + r_type += "?"; + } + return r_type; + } + + std::string GenTypeGet(const Type &type) const { + return IsScalar(type.base_type) ? GenType(type) : GenTypePointer(type); + } + + std::string GenEnumDefaultValue(const FieldDef &field) const { + auto &value = field.value; + FLATBUFFERS_ASSERT(value.type.enum_def); + auto &enum_def = *value.type.enum_def; + auto enum_val = enum_def.FindByValue(value.constant); + return enum_val ? (TypeInNameSpace(enum_def) + "." + enum_val->name) + : value.constant; + } + + // differently from GenDefaultValue, the default values are meant + // to be inserted in the buffer as the object is building. + std::string GenDefaultBufferValue(const FieldDef &field) const { + auto &value = field.value; + auto base_type = value.type.base_type; + auto field_name = field.name; + std::string suffix = IsScalar(base_type) ? LiteralSuffix(value.type) : ""; + if (field.IsScalarOptional()) { return "null"; } + if (IsFloat(base_type)) { + auto val = KotlinFloatGen.GenFloatConstant(field); + if (base_type == BASE_TYPE_DOUBLE && val.back() == 'f') { + val.pop_back(); + } + return val; + } + + if (base_type == BASE_TYPE_BOOL) { + return value.constant == "0" ? "false" : "true"; + } + + if (IsEnum(field.value.type)) { + return value.constant + suffix; + } else if ((IsVector(field.value.type) && + field.value.type.element == BASE_TYPE_UTYPE) || + (IsVector(field.value.type) && + field.value.type.VectorType().base_type == BASE_TYPE_UNION)) { + return value.constant; + } else { + return value.constant + suffix; + } + } + + std::string GenDefaultValue(const FieldDef &field) const { + auto &value = field.value; + auto base_type = value.type.base_type; + auto field_name = field.name; + std::string suffix = LiteralSuffix(value.type); + if (field.IsScalarOptional()) { return "null"; } + if (IsFloat(base_type)) { + auto val = KotlinFloatGen.GenFloatConstant(field); + if (base_type == BASE_TYPE_DOUBLE && val.back() == 'f') { + val.pop_back(); + } + return val; + } + + if (base_type == BASE_TYPE_BOOL) { + return value.constant == "0" ? "false" : "true"; + } + + if (IsEnum(field.value.type) || + (IsVector(field.value.type) && IsEnum(field.value.type.VectorType()))) { + return WrapEnumValue(field.value.type, value.constant + suffix); + } + + if (IsVector(field.value.type) && + (field.value.type.VectorType().base_type == BASE_TYPE_UNION || + field.value.type.VectorType().base_type == BASE_TYPE_STRUCT || + field.value.type.VectorType().base_type == BASE_TYPE_STRING)) { + return "null"; + } + if (IsVector(field.value.type)) { + switch (field.value.type.element) { + case BASE_TYPE_UTYPE: + return namer_.Type(*field.value.type.enum_def) + "(" + + value.constant + suffix + ")"; + case BASE_TYPE_UNION: + case BASE_TYPE_STRUCT: + case BASE_TYPE_STRING: return "null"; + case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true"; + case BASE_TYPE_FLOAT: return value.constant + "f"; + case BASE_TYPE_DOUBLE: { + return value.constant + ".toDouble()"; + } + default: return value.constant + suffix; + } + } + return value.constant + suffix; + } + + void GenEnum(EnumDef &enum_def, CodeWriter &writer) const { + if (enum_def.generated) return; + + GenerateComment(enum_def.doc_comment, writer, &comment_config); + auto enum_type = namer_.Type(enum_def); + auto field_type = GenTypeBasic(enum_def.underlying_type.base_type); + writer += "@Suppress(\"unused\")"; + writer += "@JvmInline"; + writer += "value class " + enum_type + " (val value: " + field_type + ") {"; + writer.IncrementIdentLevel(); + + GenerateCompanionObject(writer, [&]() { + // Write all properties + auto vals = enum_def.Vals(); + + for (auto it = vals.begin(); it != vals.end(); ++it) { + auto &ev = **it; + auto val = enum_def.ToString(ev); + auto suffix = LiteralSuffix(enum_def.underlying_type); + writer.SetValue("name", namer_.Variant(ev)); + writer.SetValue("type", enum_type); + writer.SetValue("val", val + suffix); + GenerateComment(ev.doc_comment, writer, &comment_config); + writer += "val {{name}} = {{type}}({{val}})"; + } + + // Generate a generate string table for enum values. + // Problem is, if values are very sparse that could generate really + // big tables. Ideally in that case we generate a map lookup + // instead, but for the moment we simply don't output a table at all. + auto range = enum_def.Distance(); + // Average distance between values above which we consider a table + // "too sparse". Change at will. + static const uint64_t kMaxSparseness = 5; + if (range / static_cast<uint64_t>(enum_def.size()) < kMaxSparseness) { + GeneratePropertyOneLine(writer, "names", "Array<String>", [&]() { + writer += "arrayOf(\\"; + auto val = enum_def.Vals().front(); + for (auto it = vals.begin(); it != vals.end(); ++it) { + auto ev = *it; + for (auto k = enum_def.Distance(val, ev); k > 1; --k) + writer += "\"\", \\"; + val = ev; + writer += "\"" + (*it)->name + "\"\\"; + if (it + 1 != vals.end()) { writer += ", \\"; } + } + writer += ")"; + }); + std::string e_param = "e: " + enum_type; + GenerateFunOneLine( + writer, "name", e_param, "String", + [&]() { + writer += "names[e.value.toInt()\\"; + if (enum_def.MinValue()->IsNonZero()) + writer += " - " + namer_.Variant(*enum_def.MinValue()) + + ".value.toInt()\\"; + writer += "]"; + }, + parser_.opts.gen_jvmstatic); + } + }); + writer.DecrementIdentLevel(); + writer += "}"; + } + + // Returns the function name that is able to read a value of the given type. + std::string ByteBufferGetter(const Type &type, + std::string bb_var_name) const { + switch (type.base_type) { + case BASE_TYPE_STRING: return "string"; + case BASE_TYPE_STRUCT: return "__struct"; + case BASE_TYPE_UNION: return "union"; + case BASE_TYPE_VECTOR: + return ByteBufferGetter(type.VectorType(), bb_var_name); + case BASE_TYPE_INT: return bb_var_name + ".getInt"; + case BASE_TYPE_UINT: return bb_var_name + ".getUInt"; + case BASE_TYPE_SHORT: return bb_var_name + ".getShort"; + case BASE_TYPE_USHORT: return bb_var_name + ".getUShort"; + case BASE_TYPE_ULONG: return bb_var_name + ".getULong"; + case BASE_TYPE_LONG: return bb_var_name + ".getLong"; + case BASE_TYPE_FLOAT: return bb_var_name + ".getFloat"; + case BASE_TYPE_DOUBLE: return bb_var_name + ".getDouble"; + case BASE_TYPE_UTYPE: + case BASE_TYPE_UCHAR: return bb_var_name + ".getUByte"; + case BASE_TYPE_CHAR: + case BASE_TYPE_NONE: return bb_var_name + ".get"; + case BASE_TYPE_BOOL: return "0.toByte() != " + bb_var_name + ".get"; + default: return bb_var_name + "." + namer_.Method("get", GenType(type)); + } + } + + // Returns the function name that is able to read a value of the given type. + std::string GenLookupByKey(flatbuffers::FieldDef *key_field, + const std::string &bb_var_name, + const char *num = nullptr) const { + auto type = key_field->value.type; + return ByteBufferGetter(type, bb_var_name) + "(" + + GenOffsetGetter(key_field, num) + ")"; + } + + // Returns the method name for use with add/put calls. + static std::string GenMethod(const Type &type) { + return IsStruct(type) ? "Struct" : ""; + } + + // Recursively generate arguments for a constructor, to deal with nested + // structs. + void GenStructArgs(const StructDef &struct_def, CodeWriter &writer, + const char *nameprefix) const { + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (IsStruct(field.value.type)) { + // Generate arguments for a struct inside a struct. To ensure + // names don't clash, and to make it obvious these arguments are + // constructing a nested struct, prefix the name with the field + // name. + GenStructArgs(*field.value.type.struct_def, writer, + (nameprefix + (field.name + "_")).c_str()); + } else { + writer += std::string(", ") + nameprefix + "\\"; + writer += namer_.Field(field) + ": \\"; + writer += GenType(field.value.type) + "\\"; + } + } + } + + // Recusively generate struct construction statements of the form: + // builder.putType(name); + // and insert manual padding. + void GenStructBody(const StructDef &struct_def, CodeWriter &writer, + const char *nameprefix) const { + writer.SetValue("align", NumToString(struct_def.minalign)); + writer.SetValue("size", NumToString(struct_def.bytesize)); + writer += "builder.prep({{align}}, {{size}})"; + auto fields_vec = struct_def.fields.vec; + for (auto it = fields_vec.rbegin(); it != fields_vec.rend(); ++it) { + auto &field = **it; + + if (field.padding) { + writer.SetValue("pad", NumToString(field.padding)); + writer += "builder.pad({{pad}})"; + } + if (IsStruct(field.value.type)) { + GenStructBody(*field.value.type.struct_def, writer, + (nameprefix + (field.name + "_")).c_str()); + } else { + auto suffix = IsEnum(field.value.type) ? ".value" : ""; + writer.SetValue("type", GenMethod(field.value.type)); + writer.SetValue("argname", + nameprefix + namer_.Variable(field) + suffix); + writer += "builder.put{{type}}({{argname}})"; + } + } + } + + std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, + const char *num = nullptr) const { + std::string key_offset = + "offset(" + NumToString(key_field->value.offset) + ", "; + if (num) { + key_offset += num; + key_offset += ", buffer)"; + } else { + key_offset += "(bb.capacity - tableOffset).toOffset<Int>(), bb)"; + } + return key_offset; + } + + bool StructHasUnsignedField(StructDef &struct_def) { + auto vec = struct_def.fields.vec; + for (auto it = vec.begin(); it != vec.end(); ++it) { + auto &field = **it; + if (IsUnsigned(field.value.type.base_type)) { return true; } + } + return false; + } + + // This method generate alias types for offset arrays. We need it + // to avoid unboxing/boxing of offsets when put into an array. + // e.g: + // Array<Offset<Monster>> generates boxing. + // So we creates a new type to avoid it: + // typealias MonterOffsetArray = IntArray + void GenStructOffsetAlias(StructDef &struct_def, CodeWriter &writer) const { + if (struct_def.generated) return; + auto name = namer_.Type(struct_def); + // This assumes offset as Ints always. + writer += "typealias " + name + "OffsetArray = OffsetArray<" + name + ">"; + + // public inline fun <T> MonsterOffsetArray(size: Int, crossinline call: + // (Int) -> Offset<T>): OffsetArray<T> { + // return OffsetArray(IntArray(size) { call(it).value }) + // } + writer += ""; + writer += "inline fun " + name + + "OffsetArray(size: Int, crossinline call: (Int) -> Offset<" + + name + ">): " + name + "OffsetArray ="; + writer.IncrementIdentLevel(); + writer += name + "OffsetArray(IntArray(size) { call(it).value })"; + } + + // This method generate alias types for offset arrays. We need it + // to avoid unboxing/boxing of offsets when put into an array. + // e.g: + // Array<Offset<Monster>> generates boxing. + // So we creates a new type to avoid it: + // typealias MonterOffsetArray = IntArray + void GenEnumOffsetAlias(EnumDef &enum_def, CodeWriter &writer) const { + if (enum_def.generated) return; + // This assumes offset as Ints always. + writer += "typealias " + namer_.Type(enum_def) + + "Array = " + GenTypeBasic(enum_def.underlying_type.base_type) + + "Array"; + } + + void GenStruct(StructDef &struct_def, CodeWriter &writer, + IDLOptions options) const { + if (struct_def.generated) return; + + GenerateComment(struct_def.doc_comment, writer, &comment_config); + auto fixed = struct_def.fixed; + + writer.SetValue("struct_name", namer_.Type(struct_def)); + writer.SetValue("superclass", fixed ? "Struct" : "Table"); + + writer += "@Suppress(\"unused\")"; + writer += "class {{struct_name}} : {{superclass}}() {\n"; + + writer.IncrementIdentLevel(); + + { + auto esc_type = namer_.EscapeKeyword(struct_def.name); + // Generate the init() method that sets the field in a pre-existing + // accessor object. This is to allow object reuse. + GenerateFunOneLine(writer, "init", "i: Int, buffer: ReadWriteBuffer", + esc_type, [&]() { writer += "reset(i, buffer)"; }); + writer += ""; // line break + + // Generate all getters + GenerateStructGetters(struct_def, writer); + + // Generate Static Fields + GenerateCompanionObject(writer, [&]() { + if (!struct_def.fixed) { + FieldDef *key_field = nullptr; + + // Generate version check method. + // Force compile time error if not using the same version + // runtime. + GenerateFunOneLine( + writer, "validateVersion", "", "", + [&]() { writer += "VERSION_2_0_8"; }, options.gen_jvmstatic); + + writer += ""; + GenerateGetRootAsAccessors(namer_.Type(struct_def), writer, options); + + writer += ""; + GenerateBufferHasIdentifier(struct_def, writer, options); + + writer += ""; + GenerateTableCreator(struct_def, writer, options); + + GenerateStartStructMethod(struct_def, writer, options); + + // Static Add for fields + auto fields = struct_def.fields.vec; + int field_pos = -1; + for (auto it = fields.begin(); it != fields.end(); ++it) { + auto &field = **it; + field_pos++; + if (field.deprecated) continue; + if (field.key) key_field = &field; + writer += ""; + GenerateAddField(NumToString(field_pos), field, writer, options); + if (IsVector(field.value.type)) { + auto vector_type = field.value.type.VectorType(); + if (!IsStruct(vector_type)) { + writer += ""; + GenerateCreateVectorField(field, writer, options); + } + writer += ""; + GenerateStartVectorField(field, writer, options); + } + } + + writer += ""; + GenerateEndStructMethod(struct_def, writer, options); + auto file_identifier = parser_.file_identifier_; + if (parser_.root_struct_def_ == &struct_def) { + writer += ""; + GenerateFinishStructBuffer(struct_def, file_identifier, writer, + options); + writer += ""; + GenerateFinishSizePrefixed(struct_def, file_identifier, writer, + options); + } + + if (struct_def.has_key) { + writer += ""; + GenerateLookupByKey(key_field, struct_def, writer, options); + } + } else { + writer += ""; + GenerateStaticConstructor(struct_def, writer, options); + } + }); + } + + // class closing + writer.DecrementIdentLevel(); + writer += "}"; + } + + // TODO: move key_field to reference instead of pointer + void GenerateLookupByKey(FieldDef *key_field, StructDef &struct_def, + CodeWriter &writer, const IDLOptions options) const { + std::stringstream params; + params << "obj: " << namer_.Type(struct_def) << "?" + << ", "; + params << "vectorLocation: Int, "; + params << "key: " << GenTypeGet(key_field->value.type) << ", "; + params << "bb: ReadWriteBuffer"; + + auto statements = [&]() { + auto base_type = key_field->value.type.base_type; + writer.SetValue("struct_name", namer_.Type(struct_def)); + if (base_type == BASE_TYPE_STRING) { + writer += "val byteKey = key.encodeToByteArray()"; + } + writer += "var span = bb.getInt(vectorLocation - 4)"; + writer += "var start = 0"; + writer += "while (span != 0) {"; + writer.IncrementIdentLevel(); + writer += "var middle = span / 2"; + writer += + "val tableOffset = indirect(vector" + "Location + 4 * (start + middle), bb)"; + if (IsString(key_field->value.type)) { + writer += "val comp = compareStrings(\\"; + writer += GenOffsetGetter(key_field) + "\\"; + writer += ", byteKey, bb)"; + } else { + auto get_val = GenLookupByKey(key_field, "bb"); + writer += "val value = " + get_val; + writer += "val comp = value.compareTo(key)"; + } + writer += "when {"; + writer.IncrementIdentLevel(); + writer += "comp > 0 -> span = middle"; + writer += "comp < 0 -> {"; + writer.IncrementIdentLevel(); + writer += "middle++"; + writer += "start += middle"; + writer += "span -= middle"; + writer.DecrementIdentLevel(); + writer += "}"; // end comp < 0 + writer += "else -> {"; + writer.IncrementIdentLevel(); + writer += "return (obj ?: {{struct_name}}()).init(tableOffset, bb)"; + writer.DecrementIdentLevel(); + writer += "}"; // end else + writer.DecrementIdentLevel(); + writer += "}"; // end when + writer.DecrementIdentLevel(); + writer += "}"; // end while + writer += "return null"; + }; + GenerateFun(writer, "lookupByKey", params.str(), + namer_.Type(struct_def) + "?", statements, + options.gen_jvmstatic); + } + + void GenerateFinishSizePrefixed(StructDef &struct_def, + const std::string &identifier, + CodeWriter &writer, + const IDLOptions options) const { + auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : ""; + auto gen_type = "Offset<" + namer_.Type(struct_def.name) + ">"; + auto params = "builder: FlatBufferBuilder, offset: " + gen_type; + auto method_name = + namer_.LegacyJavaMethod2("finishSizePrefixed", struct_def, "Buffer"); + GenerateFunOneLine( + writer, method_name, params, "", + [&]() { writer += "builder.finishSizePrefixed(offset" + id + ")"; }, + options.gen_jvmstatic); + } + void GenerateFinishStructBuffer(StructDef &struct_def, + const std::string &identifier, + CodeWriter &writer, + const IDLOptions options) const { + auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : ""; + auto gen_type = "Offset<" + namer_.Type(struct_def.name) + ">"; + auto params = "builder: FlatBufferBuilder, offset: " + gen_type; + auto method_name = + namer_.LegacyKotlinMethod("finish", struct_def, "Buffer"); + GenerateFunOneLine( + writer, method_name, params, "", + [&]() { writer += "builder.finish(offset" + id + ")"; }, + options.gen_jvmstatic); + } + + void GenerateEndStructMethod(StructDef &struct_def, CodeWriter &writer, + const IDLOptions options) const { + // Generate end{{TableName}}(builder: FlatBufferBuilder) method + auto name = namer_.Method("end", struct_def.name); + auto params = "builder: FlatBufferBuilder"; + auto returns = "Offset<" + namer_.Type(struct_def) + '>'; + auto field_vec = struct_def.fields.vec; + + GenerateFun( + writer, name, params, returns, + [&]() { + writer += "val o: " + returns + " = builder.endTable()"; + writer.IncrementIdentLevel(); + for (auto it = field_vec.begin(); it != field_vec.end(); ++it) { + auto &field = **it; + if (field.deprecated || !field.IsRequired()) { continue; } + writer.SetValue("offset", NumToString(field.value.offset)); + writer.SetValue("field_name", field.name); + writer += "builder.required(o, {{offset}}, \"{{field_name}}\")"; + } + writer.DecrementIdentLevel(); + writer += "return o"; + }, + options.gen_jvmstatic); + } + + // Generate a method to create a vector from a Kotlin array. + void GenerateCreateVectorField(FieldDef &field, CodeWriter &writer, + const IDLOptions options) const { + auto vector_type = field.value.type.VectorType(); + auto method_name = namer_.Method("create", field, "vector"); + auto array_param = GenerateKotlinOffsetArray(vector_type); + auto params = "builder: FlatBufferBuilder, vector:" + array_param; + auto return_type = GenType(field.value.type); + writer.SetValue("size", NumToString(InlineSize(vector_type))); + writer.SetValue("align", NumToString(InlineAlignment(vector_type))); + writer.SetValue("root", GenMethod(vector_type)); + + GenerateFun( + writer, method_name, params, return_type, + [&]() { + writer += "builder.startVector({{size}}, vector.size, {{align}})"; + writer += "for (i in vector.size - 1 downTo 0) {"; + writer.IncrementIdentLevel(); + writer += "builder.add{{root}}(vector[i])"; + writer.DecrementIdentLevel(); + writer += "}"; + writer += "return builder.endVector()"; + }, + options.gen_jvmstatic); + } + + void GenerateStartVectorField(FieldDef &field, CodeWriter &writer, + const IDLOptions options) const { + // Generate a method to start a vector, data to be added manually + // after. + auto vector_type = field.value.type.VectorType(); + auto params = "builder: FlatBufferBuilder, numElems: Int"; + writer.SetValue("size", NumToString(InlineSize(vector_type))); + writer.SetValue("align", NumToString(InlineAlignment(vector_type))); + + GenerateFunOneLine( + writer, namer_.Method("start", field, "Vector"), params, "", + [&]() { + writer += "builder.startVector({{size}}, numElems, {{align}})"; + }, + options.gen_jvmstatic); + } + + void GenerateAddField(std::string field_pos, FieldDef &field, + CodeWriter &writer, const IDLOptions options) const { + auto field_type = GenType(field.value.type); + auto secondArg = namer_.Variable(field.name) + ": " + field_type; + + auto content = [&]() { + auto method = GenMethod(field.value.type); + auto default_value = GenDefaultBufferValue(field); + auto field_param = namer_.Field(field); + if (IsEnum(field.value.type) || IsStruct(field.value.type)) { + field_param += ".value"; + } + + writer.SetValue("field_name", namer_.Field(field)); + writer.SetValue("field_param", field_param); + writer.SetValue("method_name", method); + writer.SetValue("pos", field_pos); + writer.SetValue("default", default_value); + + if (field.key) { + // field has key attribute, so always need to exist + // even if its value is equal to default. + // Generated code will bypass default checking + // resulting in { builder.addShort(name); slot(id); } + writer += "builder.add{{method_name}}({{field_name}})"; + writer += "builder.slot({{pos}})"; + } else { + writer += "builder.add{{method_name}}({{pos}}, \\"; + writer += "{{field_param}}, {{default}})"; + } + }; + auto signature = namer_.LegacyKotlinMethod("add", field, ""); + auto params = "builder: FlatBufferBuilder, " + secondArg; + if (field.key) { + GenerateFun(writer, signature, params, "", content, + options.gen_jvmstatic); + } else { + GenerateFunOneLine(writer, signature, params, "", content, + options.gen_jvmstatic); + } + } + + // fun startMonster(builder: FlatBufferBuilder) = builder.startTable(11) + void GenerateStartStructMethod(StructDef &struct_def, CodeWriter &code, + const IDLOptions options) const { + GenerateFunOneLine( + code, namer_.LegacyJavaMethod2("start", struct_def, ""), + "builder: FlatBufferBuilder", "", + [&]() { + code += "builder.startTable(" + + NumToString(struct_def.fields.vec.size()) + ")"; + }, + options.gen_jvmstatic); + } + + void GenerateTableCreator(StructDef &struct_def, CodeWriter &writer, + const IDLOptions options) const { + // Generate a method that creates a table in one go. This is only possible + // when the table has no struct fields, since those have to be created + // inline, and there's no way to do so in Java. + bool has_no_struct_fields = true; + int num_fields = 0; + auto fields_vec = struct_def.fields.vec; + + for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (IsStruct(field.value.type)) { + has_no_struct_fields = false; + } else { + num_fields++; + } + } + // JVM specifications restrict default constructor params to be < 255. + // Longs and doubles take up 2 units, so we set the limit to be < 127. + if (has_no_struct_fields && num_fields && num_fields < 127) { + // Generate a table constructor of the form: + // public static int createName(FlatBufferBuilder builder, args...) + + auto name = namer_.LegacyJavaMethod2("create", struct_def, ""); + std::stringstream params; + params << "builder: FlatBufferBuilder"; + for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + params << ", " << namer_.Variable(field); + if (!IsScalar(field.value.type.base_type)) { + params << "Offset: "; + } else { + params << ": "; + } + auto optional = field.IsScalarOptional() ? "?" : ""; + params << GenType(field.value.type) << optional; + } + + GenerateFun( + writer, name, params.str(), "Offset<" + namer_.Type(struct_def) + '>', + [&]() { + writer.SetValue("vec_size", NumToString(fields_vec.size())); + writer.SetValue("end_method", + namer_.Method("end", struct_def.name)); + writer += "builder.startTable({{vec_size}})"; + + auto sortbysize = struct_def.sortbysize; + auto largest = sortbysize ? sizeof(largest_scalar_t) : 1; + for (size_t size = largest; size; size /= 2) { + for (auto it = fields_vec.rbegin(); it != fields_vec.rend(); + ++it) { + auto &field = **it; + auto base_type_size = SizeOf(field.value.type.base_type); + if (!field.deprecated && + (!sortbysize || size == base_type_size)) { + writer.SetValue("field_name", namer_.Field(field)); + + // we wrap on null check for scalar optionals + writer += field.IsScalarOptional() + ? "{{field_name}}?.run { \\" + : "\\"; + + writer += namer_.LegacyKotlinMethod("add", field, "") + + "(builder, {{field_name}}\\"; + if (!IsScalar(field.value.type.base_type)) { + writer += "Offset\\"; + } + // we wrap on null check for scalar optionals + writer += field.IsScalarOptional() ? ") }" : ")"; + } + } + } + writer += "return {{end_method}}(builder)"; + }, + options.gen_jvmstatic); + } + } + void GenerateBufferHasIdentifier(StructDef &struct_def, CodeWriter &writer, + IDLOptions options) const { + auto file_identifier = parser_.file_identifier_; + // Check if a buffer has the identifier. + if (parser_.root_struct_def_ != &struct_def || !file_identifier.length()) + return; + auto name = namer_.Function(struct_def); + GenerateFunOneLine( + writer, name + "BufferHasIdentifier", "buffer: ReadWriteBuffer", + "Boolean", + [&]() { + writer += "hasIdentifier(buffer, \"" + file_identifier + "\")"; + }, + options.gen_jvmstatic); + } + + void GenerateStructGetters(StructDef &struct_def, CodeWriter &writer) const { + auto fields_vec = struct_def.fields.vec; + FieldDef *key_field = nullptr; + for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (field.key) key_field = &field; + + GenerateComment(field.doc_comment, writer, &comment_config); + + auto field_name = namer_.Field(field); + auto field_type = GenTypeGet(field.value.type); + auto field_default_value = GenDefaultValue(field); + auto return_type = GetterReturnType(field); + auto bbgetter = ByteBufferGetter(field.value.type, "bb"); + auto offset_val = NumToString(field.value.offset); + auto offset_prefix = + "val o = offset(" + offset_val + "); return o != 0 ? "; + auto value_base_type = field.value.type.base_type; + // Most field accessors need to retrieve and test the field offset + // first, this is the offset value for that: + writer.SetValue("offset", NumToString(field.value.offset)); + writer.SetValue("return_type", return_type); + writer.SetValue("field_type", field_type); + writer.SetValue("field_name", field_name); + writer.SetValue("field_default", field_default_value); + writer.SetValue("bbgetter", bbgetter); + // Generate the accessors that don't do object reuse. + if (value_base_type == BASE_TYPE_STRUCT) { + // Calls the accessor that takes an accessor object with a + // new object. + // val pos + // get() = pos(Vec3()) + GenerateGetterOneLine(writer, field_name, return_type, [&]() { + writer += "{{field_name}}({{field_type}}())"; + }); + } else if (value_base_type == BASE_TYPE_VECTOR && + field.value.type.element == BASE_TYPE_STRUCT) { + // Accessors for vectors of structs also take accessor objects, + // this generates a variant without that argument. + // ex: fun weapons(j: Int) = weapons(Weapon(), j) + GenerateFunOneLine(writer, field_name, "j: Int", return_type, [&]() { + writer += "{{field_name}}({{field_type}}(), j)"; + }); + } + + if (IsScalar(value_base_type)) { + if (struct_def.fixed) { + GenerateGetterOneLine(writer, field_name, return_type, [&]() { + std::string found = "{{bbgetter}}(bufferPos + {{offset}})"; + writer += WrapEnumValue(field.value.type, found); + }); + } else { + GenerateGetterOneLine(writer, field_name, return_type, [&]() { + std::string found = "{{bbgetter}}(it + bufferPos)"; + writer += LookupFieldOneLine(offset_val, + WrapEnumValue(field.value.type, found), + "{{field_default}}"); + }); + } + } else { + switch (value_base_type) { + case BASE_TYPE_STRUCT: + if (struct_def.fixed) { + // create getter with object reuse + // ex: + // fun pos(obj: Vec3) : Vec3? = obj.init(bufferPos + 4, bb) + // ? adds nullability annotation + GenerateFunOneLine( + writer, field_name, "obj: " + field_type, return_type, [&]() { + writer += "obj.init(bufferPos + {{offset}}, bb)"; + }); + } else { + // create getter with object reuse + // ex: + // fun pos(obj: Vec3) : Vec3? { + // val o = offset(4) + // return if(o != 0) { + // obj.init(o + bufferPos, bb) + // else { + // null + // } + // } + // ? adds nullability annotation + GenerateFunOneLine( + writer, field_name, "obj: " + field_type, return_type, [&]() { + auto fixed = field.value.type.struct_def->fixed; + + writer.SetValue("seek", Indirect("it + bufferPos", fixed)); + writer += LookupFieldOneLine( + offset_val, "obj.init({{seek}}, bb)", "null"); + }); + } + break; + case BASE_TYPE_STRING: + // create string getter + // e.g. + // val Name : String? + // get() = { + // val o = offset(10) + // return if (o != 0) string(o + bufferPos) else null + // } + // ? adds nullability annotation + GenerateGetterOneLine(writer, field_name, return_type, [&]() { + writer += LookupFieldOneLine(offset_val, "string(it + bufferPos)", + "null"); + }); + break; + case BASE_TYPE_VECTOR: { + // e.g. + // fun inventory(j: Int) : UByte { + // val o = offset(14) + // return if (o != 0) { + // bb.get(vector(it) + j * 1).toUByte() + // } else { + // 0 + // } + // } + + auto vectortype = field.value.type.VectorType(); + std::string params = "j: Int"; + + if (vectortype.base_type == BASE_TYPE_STRUCT || + vectortype.base_type == BASE_TYPE_UNION) { + params = "obj: " + field_type + ", j: Int"; + } + + GenerateFunOneLine(writer, field_name, params, return_type, [&]() { + auto inline_size = NumToString(InlineSize(vectortype)); + auto index = "vector(it) + j * " + inline_size; + std::string found = ""; + writer.SetValue("index", index); + + if (IsEnum(vectortype)) { + found = "{{field_type}}({{bbgetter}}({{index}}))"; + } else { + switch (vectortype.base_type) { + case BASE_TYPE_STRUCT: { + bool fixed = vectortype.struct_def->fixed; + writer.SetValue("index", Indirect(index, fixed)); + found = "obj.init({{index}}, bb)"; + break; + } + case BASE_TYPE_UNION: + found = "{{bbgetter}}(obj, {{index}})"; + break; + case BASE_TYPE_UTYPE: + found = "{{field_type}}({{bbgetter}}({{index}}))"; + break; + default: found = "{{bbgetter}}({{index}})"; + } + } + writer += + LookupFieldOneLine(offset_val, found, "{{field_default}}"); + }); + break; + } + case BASE_TYPE_UNION: + GenerateFunOneLine( + writer, field_name, "obj: " + field_type, return_type, [&]() { + writer += LookupFieldOneLine( + offset_val, bbgetter + "(obj, it + bufferPos)", "null"); + }); + break; + default: FLATBUFFERS_ASSERT(0); + } + } + + if (value_base_type == BASE_TYPE_VECTOR) { + // Generate Lenght functions for vectors + GenerateGetterOneLine(writer, field_name + "Length", "Int", [&]() { + writer += LookupFieldOneLine(offset_val, "vectorLength(it)", "0"); + }); + + // See if we should generate a by-key accessor. + if (field.value.type.element == BASE_TYPE_STRUCT && + !field.value.type.struct_def->fixed) { + auto &sd = *field.value.type.struct_def; + auto &fields = sd.fields.vec; + for (auto kit = fields.begin(); kit != fields.end(); ++kit) { + auto &kfield = **kit; + if (kfield.key) { + auto qualified_name = TypeInNameSpace(sd); + auto name = namer_.Method(field, "ByKey"); + auto params = "key: " + GenTypeGet(kfield.value.type); + auto rtype = qualified_name + "?"; + GenerateFunOneLine(writer, name, params, rtype, [&]() { + writer += LookupFieldOneLine( + offset_val, + qualified_name + ".lookupByKey(null, vector(it), key, bb)", + "null"); + }); + + auto param2 = "obj: " + qualified_name + + ", key: " + GenTypeGet(kfield.value.type); + GenerateFunOneLine(writer, name, param2, rtype, [&]() { + writer += LookupFieldOneLine( + offset_val, + qualified_name + ".lookupByKey(obj, vector(it), key, bb)", + "null"); + }); + + break; + } + } + } + } + + if ((value_base_type == BASE_TYPE_VECTOR && + IsScalar(field.value.type.VectorType().base_type)) || + value_base_type == BASE_TYPE_STRING) { + auto end_idx = + NumToString(value_base_type == BASE_TYPE_STRING + ? 1 + : InlineSize(field.value.type.VectorType())); + + // Generate a ByteBuffer accessor for strings & vectors of scalars. + // e.g. + // fun inventoryInByteBuffer(buffer: Bytebuffer): + // ByteBuffer = vectorAsBuffer(buffer, 14, 1) + GenerateFunOneLine( + writer, field_name + "AsBuffer", "", "ReadBuffer", [&]() { + writer.SetValue("end", end_idx); + writer += "vectorAsBuffer(bb, {{offset}}, {{end}})"; + }); + } + + // generate object accessors if is nested_flatbuffer + // fun testnestedflatbufferAsMonster() : Monster? + //{ return testnestedflatbufferAsMonster(new Monster()); } + + if (field.nested_flatbuffer) { + auto nested_type_name = TypeInNameSpace(*field.nested_flatbuffer); + auto nested_method_name = + field_name + "As" + field.nested_flatbuffer->name; + + GenerateGetterOneLine( + writer, nested_method_name, nested_type_name + "?", [&]() { + writer += nested_method_name + "(" + nested_type_name + "())"; + }); + + GenerateFunOneLine( + writer, nested_method_name, "obj: " + nested_type_name, + nested_type_name + "?", [&]() { + writer += LookupFieldOneLine( + offset_val, "obj.init(indirect(vector(it)), bb)", "null"); + }); + } + + writer += ""; // Initial line break between fields + } + if (struct_def.has_key && !struct_def.fixed) { + // Key Comparison method + GenerateOverrideFun( + writer, "keysCompare", + "o1: Offset<*>, o2: Offset<*>, buffer: ReadWriteBuffer", "Int", + [&]() { + if (IsString(key_field->value.type)) { + writer.SetValue("offset", NumToString(key_field->value.offset)); + writer += + " return compareStrings(offset({{offset}}, o1, " + "buffer), offset({{offset}}, o2, buffer), buffer)"; + + } else { + auto getter1 = GenLookupByKey(key_field, "buffer", "o1"); + auto getter2 = GenLookupByKey(key_field, "buffer", "o2"); + writer += "val a = " + getter1; + writer += "val b = " + getter2; + writer += "return (a - b).toInt().sign()"; + } + }); + } + } + + static std::string LiteralSuffix(const Type &type) { + auto base = IsVector(type) ? type.element : type.base_type; + switch (base) { + case BASE_TYPE_UINT: + case BASE_TYPE_UCHAR: + case BASE_TYPE_UTYPE: + case BASE_TYPE_USHORT: return "u"; + case BASE_TYPE_ULONG: return "UL"; + case BASE_TYPE_LONG: return "L"; + default: return ""; + } + } + + std::string WrapEnumValue(const Type &type, const std::string value) const { + if (IsEnum(type)) { return GenType(type) + "(" + value + ")"; } + if (IsVector(type) && IsEnum(type.VectorType())) { + return GenType(type.VectorType()) + "(" + value + ")"; + } + return value; + } + + void GenerateCompanionObject(CodeWriter &code, + const std::function<void()> &callback) const { + code += "companion object {"; + code.IncrementIdentLevel(); + callback(); + code.DecrementIdentLevel(); + code += "}"; + } + + // Generate a documentation comment, if available. + void GenerateComment(const std::vector<std::string> &dc, CodeWriter &writer, + const CommentConfig *config) const { + if (dc.begin() == dc.end()) { + // Don't output empty comment blocks with 0 lines of comment content. + return; + } + + if (config != nullptr && config->first_line != nullptr) { + writer += std::string(config->first_line); + } + std::string line_prefix = + ((config != nullptr && config->content_line_prefix != nullptr) + ? config->content_line_prefix + : "///"); + for (auto it = dc.begin(); it != dc.end(); ++it) { + writer += line_prefix + *it; + } + if (config != nullptr && config->last_line != nullptr) { + writer += std::string(config->last_line); + } + } + + void GenerateGetRootAsAccessors(const std::string &struct_name, + CodeWriter &writer, + IDLOptions options) const { + // Generate a special accessor for the table that when used as the root + // ex: fun getRootAsMonster(buffer: ByteBuffer): Monster {...} + writer.SetValue("gr_name", struct_name); + + // create convenience method that doesn't require an existing object + GenerateJvmStaticAnnotation(writer, options.gen_jvmstatic); + GenerateFunOneLine(writer, "asRoot", "buffer: ReadWriteBuffer", struct_name, + [&]() { writer += "asRoot(buffer, {{gr_name}}())"; }); + + // create method that allows object reuse + // ex: fun Monster getRootAsMonster(buffer: ByteBuffer, obj: Monster) {...} + GenerateJvmStaticAnnotation(writer, options.gen_jvmstatic); + GenerateFunOneLine( + writer, "asRoot", "buffer: ReadWriteBuffer, obj: {{gr_name}}", + struct_name, [&]() { + writer += + "obj.init(buffer.getInt(buffer.limit) + buffer.limit, buffer)"; + }); + } + + void GenerateStaticConstructor(const StructDef &struct_def, CodeWriter &code, + const IDLOptions options) const { + // create a struct constructor function + auto params = StructConstructorParams(struct_def); + GenerateFun( + code, namer_.LegacyJavaMethod2("create", struct_def, ""), params, + "Offset<" + namer_.Type(struct_def) + '>', + [&]() { + GenStructBody(struct_def, code, ""); + code += "return Offset(builder.offset())"; + }, + options.gen_jvmstatic); + } + + std::string StructConstructorParams(const StructDef &struct_def, + const std::string &prefix = "") const { + // builder: FlatBufferBuilder + std::stringstream out; + auto field_vec = struct_def.fields.vec; + if (prefix.empty()) { out << "builder: FlatBufferBuilder"; } + for (auto it = field_vec.begin(); it != field_vec.end(); ++it) { + auto &field = **it; + if (IsStruct(field.value.type)) { + // Generate arguments for a struct inside a struct. To ensure + // names don't clash, and to make it obvious these arguments are + // constructing a nested struct, prefix the name with the field + // name. + out << StructConstructorParams(*field.value.type.struct_def, + prefix + (namer_.Variable(field) + "_")); + } else { + out << ", " << prefix << namer_.Variable(field) << ": " + << GenType(field.value.type); + } + } + return out.str(); + } + + static void GenerateVarGetterSetterOneLine(CodeWriter &writer, + const std::string &name, + const std::string &type, + const std::string &getter, + const std::string &setter) { + // Generates Kotlin getter for properties + // e.g.: + // val prop: Mytype + // get() = { + // return x + // } + writer.SetValue("name", name); + writer.SetValue("type", type); + writer += "var {{name}} : {{type}}"; + writer.IncrementIdentLevel(); + writer += "get() = " + getter; + writer += "set(value) = " + setter; + writer.DecrementIdentLevel(); + } + + static void GeneratePropertyOneLine(CodeWriter &writer, + const std::string &name, + const std::string &type, + const std::function<void()> &body) { + // Generates Kotlin getter for properties + // e.g.: + // val prop: Mytype = x + writer.SetValue("_name", name); + writer.SetValue("_type", type); + writer += "val {{_name}} : {{_type}} = \\"; + body(); + } + static void GenerateGetterOneLine(CodeWriter &writer, const std::string &name, + const std::string &type, + const std::function<void()> &body) { + // Generates Kotlin getter for properties + // e.g.: + // val prop: Mytype get() = x + writer.SetValue("_name", name); + writer.SetValue("_type", type); + writer += "val {{_name}} : {{_type}} get() = \\"; + body(); + } + + static void GenerateGetter(CodeWriter &writer, const std::string &name, + const std::string &type, + const std::function<void()> &body) { + // Generates Kotlin getter for properties + // e.g.: + // val prop: Mytype + // get() = { + // return x + // } + writer.SetValue("name", name); + writer.SetValue("type", type); + writer += "val {{name}} : {{type}}"; + writer.IncrementIdentLevel(); + writer += "get() {"; + writer.IncrementIdentLevel(); + body(); + writer.DecrementIdentLevel(); + writer += "}"; + writer.DecrementIdentLevel(); + } + + static void GenerateFun(CodeWriter &writer, const std::string &name, + const std::string ¶ms, + const std::string &returnType, + const std::function<void()> &body, + bool gen_jvmstatic = false) { + // Generates Kotlin function + // e.g.: + // fun path(j: Int): Vec3 { + // return path(Vec3(), j) + // } + auto noreturn = returnType.empty(); + writer.SetValue("name", name); + writer.SetValue("params", params); + writer.SetValue("return_type", noreturn ? "" : ": " + returnType); + GenerateJvmStaticAnnotation(writer, gen_jvmstatic); + writer += "fun {{name}}({{params}}) {{return_type}} {"; + writer.IncrementIdentLevel(); + body(); + writer.DecrementIdentLevel(); + writer += "}"; + } + + static void GenerateFunOneLine(CodeWriter &writer, const std::string &name, + const std::string ¶ms, + const std::string &returnType, + const std::function<void()> &body, + bool gen_jvmstatic = false) { + // Generates Kotlin function + // e.g.: + // fun path(j: Int): Vec3 = return path(Vec3(), j) + auto ret = returnType.empty() ? "" : " : " + returnType; + GenerateJvmStaticAnnotation(writer, gen_jvmstatic); + writer += "fun " + name + "(" + params + ")" + ret + " = \\"; + body(); + } + + static void GenerateOverrideFun(CodeWriter &writer, const std::string &name, + const std::string ¶ms, + const std::string &returnType, + const std::function<void()> &body) { + // Generates Kotlin function + // e.g.: + // override fun path(j: Int): Vec3 = return path(Vec3(), j) + writer += "override \\"; + GenerateFun(writer, name, params, returnType, body); + } + + static void GenerateOverrideFunOneLine(CodeWriter &writer, + const std::string &name, + const std::string ¶ms, + const std::string &returnType, + const std::string &statement) { + // Generates Kotlin function + // e.g.: + // override fun path(j: Int): Vec3 = return path(Vec3(), j) + writer.SetValue("name", name); + writer.SetValue("params", params); + writer.SetValue("return_type", + returnType.empty() ? "" : " : " + returnType); + writer += "override fun {{name}}({{params}}){{return_type}} = \\"; + writer += statement; + } + + static std::string LookupFieldOneLine(const std::string &offset, + const std::string &found, + const std::string ¬_found) { + return "lookupField(" + offset + ", " + not_found + " ) { " + found + " }"; + } + + static std::string Indirect(const std::string &index, bool fixed) { + // We apply indirect() and struct is not fixed. + if (!fixed) return "indirect(" + index + ")"; + return index; + } + + static std::string NotFoundReturn(BaseType el) { + switch (el) { + case BASE_TYPE_FLOAT: return "0.0f"; + case BASE_TYPE_DOUBLE: return "0.0"; + case BASE_TYPE_BOOL: return "false"; + case BASE_TYPE_LONG: + case BASE_TYPE_INT: + case BASE_TYPE_CHAR: + case BASE_TYPE_SHORT: return "0"; + case BASE_TYPE_UINT: + case BASE_TYPE_UCHAR: + case BASE_TYPE_USHORT: + case BASE_TYPE_UTYPE: return "0u"; + case BASE_TYPE_ULONG: return "0uL"; + default: return "null"; + } + } + + // Prepend @JvmStatic to methods in companion object. + static void GenerateJvmStaticAnnotation(CodeWriter &code, + bool gen_jvmstatic) { + if (gen_jvmstatic) { code += "@JvmStatic"; } + } + + const IdlNamer namer_; +}; +} // namespace kotlin + +static bool GenerateKotlinKMP(const Parser &parser, const std::string &path, + const std::string &file_name) { + kotlin::KotlinKMPGenerator generator(parser, path, file_name); + return generator.generate(); +} + +namespace { + +class KotlinKMPCodeGenerator : public CodeGenerator { + public: + Status GenerateCode(const Parser &parser, const std::string &path, + const std::string &filename) override { + if (!GenerateKotlinKMP(parser, path, filename)) { return Status::ERROR; } + return Status::OK; + } + + Status GenerateCode(const uint8_t *, int64_t, + const CodeGenOptions &) override { + return Status::NOT_IMPLEMENTED; + } + + Status GenerateMakeRule(const Parser &parser, const std::string &path, + const std::string &filename, + std::string &output) override { + (void)parser; + (void)path; + (void)filename; + (void)output; + return Status::NOT_IMPLEMENTED; + } + + Status GenerateGrpcCode(const Parser &parser, const std::string &path, + const std::string &filename) override { + (void)parser; + (void)path; + (void)filename; + return Status::NOT_IMPLEMENTED; + } + + Status GenerateRootFile(const Parser &parser, + const std::string &path) override { + (void)parser; + (void)path; + return Status::NOT_IMPLEMENTED; + } + bool IsSchemaOnly() const override { return true; } + + bool SupportsBfbsGeneration() const override { return false; } + + bool SupportsRootFileGeneration() const override { return false; } + + IDLOptions::Language Language() const override { + return IDLOptions::kKotlinKmp; + } + + std::string LanguageName() const override { return "Kotlin"; } +}; +} // namespace + +std::unique_ptr<CodeGenerator> NewKotlinKMPCodeGenerator() { + return std::unique_ptr<KotlinKMPCodeGenerator>(new KotlinKMPCodeGenerator()); +} + +} // namespace flatbuffers diff --git a/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp b/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp index 37c95e9600..c89e7bb461 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp @@ -31,7 +31,7 @@ class LobsterGenerator : public BaseGenerator { public: LobsterGenerator(const Parser &parser, const std::string &path, const std::string &file_name) - : BaseGenerator(parser, path, file_name, "" /* not used */, "_", + : BaseGenerator(parser, path, file_name, "" /* not used */, ".", "lobster") { static const char *const keywords[] = { "nil", "true", "false", "return", "struct", "class", @@ -79,7 +79,7 @@ class LobsterGenerator : public BaseGenerator { if (IsBool(type.base_type)) return "bool"; if (IsScalar(type.base_type) && type.enum_def) return NormalizedName(*type.enum_def); - if (!IsScalar(type.base_type)) return "flatbuffers_offset"; + if (!IsScalar(type.base_type)) return "flatbuffers.offset"; if (IsString(type)) return "string"; return "int"; } @@ -119,15 +119,17 @@ class LobsterGenerator : public BaseGenerator { offsets + ")"; } else { - auto defval = field.IsOptional() ? "0" : field.value.constant; - acc = "buf_.flatbuffers_field_" + GenTypeName(field.value.type) + - "(pos_, " + offsets + ", " + defval + ")"; + auto defval = field.IsOptional() + ? (IsFloat(field.value.type.base_type) ? "0.0" : "0") + : field.value.constant; + acc = "flatbuffers.field_" + GenTypeName(field.value.type) + + "(buf_, pos_, " + offsets + ", " + defval + ")"; if (IsBool(field.value.type.base_type)) acc = "bool(" + acc + ")"; } if (field.value.type.enum_def) acc = NormalizedName(*field.value.type.enum_def) + "(" + acc + ")"; if (field.IsOptional()) { - acc += ", buf_.flatbuffers_field_present(pos_, " + offsets + ")"; + acc += ", flatbuffers.field_present(buf_, pos_, " + offsets + ")"; code += def + "() -> " + LobsterType(field.value.type) + ", bool:\n return " + acc + "\n"; } else { @@ -144,9 +146,9 @@ class LobsterGenerator : public BaseGenerator { code += "return " + name + "{ buf_, pos_ + " + offsets + " }\n"; } else { code += def + "() -> " + name + "?:\n "; - code += std::string("let o = buf_.flatbuffers_field_") + + code += std::string("let o = flatbuffers.field_") + (field.value.type.struct_def->fixed ? "struct" : "table") + - "(pos_, " + offsets + ")\n return if o: " + name + + "(buf_, pos_, " + offsets + ")\n return if o: " + name + " { buf_, o } else: nil\n"; } break; @@ -154,16 +156,16 @@ class LobsterGenerator : public BaseGenerator { case BASE_TYPE_STRING: code += def + "() -> string:\n return " - "buf_.flatbuffers_field_string(pos_, " + + "flatbuffers.field_string(buf_, pos_, " + offsets + ")\n"; break; case BASE_TYPE_VECTOR: { auto vectortype = field.value.type.VectorType(); if (vectortype.base_type == BASE_TYPE_STRUCT) { - auto start = "buf_.flatbuffers_field_vector(pos_, " + offsets + + auto start = "flatbuffers.field_vector(buf_, pos_, " + offsets + ") + i * " + NumToString(InlineSize(vectortype)); if (!(vectortype.struct_def->fixed)) { - start = "buf_.flatbuffers_indirect(" + start + ")"; + start = "flatbuffers.indirect(buf_, " + start + ")"; } code += def + "(i:int) -> " + NamespacedName(*field.value.type.struct_def) + @@ -173,13 +175,13 @@ class LobsterGenerator : public BaseGenerator { } else { if (IsString(vectortype)) { code += def + "(i:int) -> string:\n return "; - code += "buf_.flatbuffers_string"; + code += "flatbuffers.string"; } else { code += def + "(i:int) -> " + LobsterType(vectortype) + ":\n return "; - code += "buf_.read_" + GenTypeName(vectortype) + "_le"; + code += "read_" + GenTypeName(vectortype) + "_le"; } - code += "(buf_.flatbuffers_field_vector(pos_, " + offsets + + code += "(buf_, buf_.flatbuffers.field_vector(pos_, " + offsets + ") + i * " + NumToString(InlineSize(vectortype)) + ")\n"; } break; @@ -191,7 +193,7 @@ class LobsterGenerator : public BaseGenerator { if (ev.IsNonZero()) { code += def + "_as_" + ev.name + "():\n return " + NamespacedName(*ev.union_type.struct_def) + - " { buf_, buf_.flatbuffers_field_table(pos_, " + offsets + + " { buf_, flatbuffers.field_table(buf_, pos_, " + offsets + ") }\n"; } } @@ -202,7 +204,7 @@ class LobsterGenerator : public BaseGenerator { if (IsVector(field.value.type)) { code += def + "_length() -> int:\n return " - "buf_.flatbuffers_field_vector_len(pos_, " + + "flatbuffers.field_vector_len(buf_, pos_, " + offsets + ")\n"; } } @@ -211,7 +213,7 @@ class LobsterGenerator : public BaseGenerator { void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; code += "struct " + NormalizedName(struct_def) + - "Builder:\n b_:flatbuffers_builder\n"; + "Builder:\n b_:flatbuffers.builder\n"; code += " def start():\n b_.StartObject(" + NumToString(struct_def.fields.vec.size()) + ")\n return this\n"; @@ -236,7 +238,7 @@ class LobsterGenerator : public BaseGenerator { if (IsVector(field.value.type)) { code += "def " + NormalizedName(struct_def) + "Start" + ConvertCase(NormalizedName(field), Case::kUpperCamel) + - "Vector(b_:flatbuffers_builder, n_:int):\n b_.StartVector("; + "Vector(b_:flatbuffers.builder, n_:int):\n b_.StartVector("; auto vector_type = field.value.type.VectorType(); auto alignment = InlineAlignment(vector_type); auto elem_size = InlineSize(vector_type); @@ -246,7 +248,7 @@ class LobsterGenerator : public BaseGenerator { !vector_type.struct_def->fixed) { code += "def " + NormalizedName(struct_def) + "Create" + ConvertCase(NormalizedName(field), Case::kUpperCamel) + - "Vector(b_:flatbuffers_builder, v_:[" + + "Vector(b_:flatbuffers.builder, v_:[" + LobsterType(vector_type) + "]):\n b_.StartVector(" + NumToString(elem_size) + ", v_.length, " + NumToString(alignment) + ")\n reverse(v_) e_: b_.Prepend" + @@ -271,7 +273,7 @@ class LobsterGenerator : public BaseGenerator { std::string &code = *code_ptr; CheckNameSpace(struct_def, &code); GenComment(struct_def.doc_comment, code_ptr, nullptr, ""); - code += "class " + NormalizedName(struct_def) + " : flatbuffers_handle\n"; + code += "class " + NormalizedName(struct_def) + " : flatbuffers.handle\n"; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { auto &field = **it; @@ -284,7 +286,7 @@ class LobsterGenerator : public BaseGenerator { // the root type. code += "def GetRootAs" + NormalizedName(struct_def) + "(buf:string): return " + NormalizedName(struct_def) + - " { buf, buf.flatbuffers_indirect(0) }\n\n"; + " { buf, flatbuffers.indirect(buf, 0) }\n\n"; } if (struct_def.fixed) { // create a struct constructor function @@ -360,7 +362,7 @@ class LobsterGenerator : public BaseGenerator { void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; code += - "def Create" + NormalizedName(struct_def) + "(b_:flatbuffers_builder"; + "def Create" + NormalizedName(struct_def) + "(b_:flatbuffers.builder"; StructBuilderArgs(struct_def, "", code_ptr); code += "):\n"; StructBuilderBody(struct_def, "", code_ptr); diff --git a/contrib/libs/flatbuffers/src/idl_gen_python.cpp b/contrib/libs/flatbuffers/src/idl_gen_python.cpp index ff535d1574..9e1627592e 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_python.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_python.cpp @@ -815,8 +815,12 @@ class PythonGenerator : public BaseGenerator { if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) { // Generate method without struct name. - code += "def Start" + field_method + - "Vector(builder, numElems: int) -> int:\n"; + if (parser_.opts.python_typing) { + code += "def Start" + field_method + + "Vector(builder, numElems: int) -> int:\n"; + } else { + code += "def Start" + field_method + "Vector(builder, numElems):\n"; + } code += Indent + "return " + struct_type + "Start"; code += field_method + "Vector(builder, numElems)\n\n"; } diff --git a/contrib/libs/flatbuffers/src/idl_gen_rust.cpp b/contrib/libs/flatbuffers/src/idl_gen_rust.cpp index 95fa39bdd6..a85a7812dc 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_rust.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_rust.cpp @@ -989,7 +989,8 @@ class RustGenerator : public BaseGenerator { code_ += " }"; // Pack flatbuffers union value code_ += - " pub fn pack(&self, fbb: &mut flatbuffers::FlatBufferBuilder)" + " pub fn pack<'b, A: flatbuffers::Allocator + 'b>(&self, fbb: &mut " + "flatbuffers::FlatBufferBuilder<'b, A>)" " -> Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>>" " {"; code_ += " match self {"; @@ -1717,8 +1718,11 @@ class RustGenerator : public BaseGenerator { code_.SetValue("MAYBE_LT", TableBuilderArgsNeedsLifetime(struct_def) ? "<'args>" : ""); code_ += " #[allow(unused_mut)]"; - code_ += " pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>("; - code_ += " _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,"; + code_ += + " pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: " + "flatbuffers::Allocator + 'bldr>("; + code_ += + " _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>,"; code_ += " {{MAYBE_US}}args: &'args {{STRUCT_TY}}Args{{MAYBE_LT}}"; code_ += " ) -> flatbuffers::WIPOffset<{{STRUCT_TY}}<'bldr>> {"; @@ -2117,15 +2121,20 @@ class RustGenerator : public BaseGenerator { } // Generate a builder struct: - code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}Builder<'a: 'b, 'b> {"; - code_ += " fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,"; + code_ += + "{{ACCESS_TYPE}} struct {{STRUCT_TY}}Builder<'a: 'b, 'b, A: " + "flatbuffers::Allocator + 'a> {"; + code_ += " fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>,"; code_ += " start_: flatbuffers::WIPOffset<" "flatbuffers::TableUnfinishedWIPOffset>,"; code_ += "}"; // Generate builder functions: - code_ += "impl<'a: 'b, 'b> {{STRUCT_TY}}Builder<'a, 'b> {"; + code_ += + "impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> " + "{{STRUCT_TY}}Builder<'a, " + "'b, A> {"; ForAllTableFields(struct_def, [&](const FieldDef &field) { const bool is_scalar = IsScalar(field.value.type.base_type); std::string offset = namer_.LegacyRustFieldOffsetName(field); @@ -2160,8 +2169,8 @@ class RustGenerator : public BaseGenerator { // Struct initializer (all fields required); code_ += " #[inline]"; code_ += - " pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> " - "{{STRUCT_TY}}Builder<'a, 'b> {"; + " pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> " + "{{STRUCT_TY}}Builder<'a, 'b, A> {"; code_.SetValue("NUM_FIELDS", NumToString(struct_def.fields.vec.size())); code_ += " let start = _fbb.start_table();"; code_ += " {{STRUCT_TY}}Builder {"; @@ -2264,9 +2273,9 @@ class RustGenerator : public BaseGenerator { // Generate pack function. code_ += "impl {{STRUCT_OTY}} {"; - code_ += " pub fn pack<'b>("; + code_ += " pub fn pack<'b, A: flatbuffers::Allocator + 'b>("; code_ += " &self,"; - code_ += " _fbb: &mut flatbuffers::FlatBufferBuilder<'b>"; + code_ += " _fbb: &mut flatbuffers::FlatBufferBuilder<'b, A>"; code_ += " ) -> flatbuffers::WIPOffset<{{STRUCT_TY}}<'b>> {"; // First we generate variables for each field and then later assemble them // using "StructArgs" to more easily manage ownership of the builder. @@ -2551,8 +2560,10 @@ class RustGenerator : public BaseGenerator { // Finish a buffer with a given root object: code_ += "#[inline]"; - code_ += "pub fn finish_{{STRUCT_FN}}_buffer<'a, 'b>("; - code_ += " fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,"; + code_ += + "pub fn finish_{{STRUCT_FN}}_buffer<'a, 'b, A: " + "flatbuffers::Allocator + 'a>("; + code_ += " fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>,"; code_ += " root: flatbuffers::WIPOffset<{{STRUCT_TY}}<'a>>) {"; if (parser_.file_identifier_.length()) { code_ += " fbb.finish(root, Some({{STRUCT_CONST}}_IDENTIFIER));"; @@ -2564,8 +2575,8 @@ class RustGenerator : public BaseGenerator { code_ += "#[inline]"; code_ += "pub fn finish_size_prefixed_{{STRUCT_FN}}_buffer" - "<'a, 'b>(" - "fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, " + "<'a, 'b, A: flatbuffers::Allocator + 'a>(" + "fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, " "root: flatbuffers::WIPOffset<{{STRUCT_TY}}<'a>>) {"; if (parser_.file_identifier_.length()) { code_ += diff --git a/contrib/libs/flatbuffers/src/idl_gen_swift.cpp b/contrib/libs/flatbuffers/src/idl_gen_swift.cpp index 17f3bf5fa4..6cd1b478ec 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_swift.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_swift.cpp @@ -1845,7 +1845,7 @@ class SwiftGenerator : public BaseGenerator { } std::string ValidateFunc() { - return "static func validateVersion() { FlatBuffersVersion_23_5_26() }"; + return "static func validateVersion() { FlatBuffersVersion_24_3_7() }"; } std::string GenType(const Type &type, diff --git a/contrib/libs/flatbuffers/src/idl_gen_text.cpp b/contrib/libs/flatbuffers/src/idl_gen_text.cpp index a34667c4b6..895367e9a7 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_text.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_text.cpp @@ -384,6 +384,14 @@ static const char *GenerateTextImpl(const Parser &parser, const Table *table, } // Generate a text representation of a flatbuffer in JSON format. +// Deprecated: please use `GenTextFromTable` +bool GenerateTextFromTable(const Parser &parser, const void *table, + const std::string &table_name, + std::string *_text) { + return GenTextFromTable(parser, table, table_name, _text) != nullptr; +} + +// Generate a text representation of a flatbuffer in JSON format. const char *GenTextFromTable(const Parser &parser, const void *table, const std::string &table_name, std::string *_text) { auto struct_def = parser.LookupStruct(table_name); @@ -392,6 +400,12 @@ const char *GenTextFromTable(const Parser &parser, const void *table, return GenerateTextImpl(parser, root, *struct_def, _text); } +// Deprecated: please use `GenText` +const char *GenerateText(const Parser &parser, const void *flatbuffer, + std::string *_text) { + return GenText(parser, flatbuffer, _text); +} + // Generate a text representation of a flatbuffer in JSON format. const char *GenText(const Parser &parser, const void *flatbuffer, std::string *_text) { @@ -406,6 +420,12 @@ static std::string TextFileName(const std::string &path, return path + file_name + ".json"; } +// Deprecated: please use `GenTextFile` +const char *GenerateTextFile(const Parser &parser, const std::string &path, + const std::string &file_name) { + return GenTextFile(parser, path, file_name); +} + const char *GenTextFile(const Parser &parser, const std::string &path, const std::string &file_name) { if (parser.opts.use_flexbuffers) { diff --git a/contrib/libs/flatbuffers/src/idl_gen_ts.cpp b/contrib/libs/flatbuffers/src/idl_gen_ts.cpp index acd2a4febe..41c05e3b88 100644 --- a/contrib/libs/flatbuffers/src/idl_gen_ts.cpp +++ b/contrib/libs/flatbuffers/src/idl_gen_ts.cpp @@ -113,7 +113,7 @@ class TsGenerator : public BaseGenerator { bool generate() { generateEnums(); generateStructs(); - generateEntry(); + if (!parser_.opts.ts_omit_entrypoint) { generateEntry(); } if (!generateBundle()) return false; return true; } @@ -149,7 +149,8 @@ class TsGenerator : public BaseGenerator { std::string code; - code += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n"; + code += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n" + + "/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */\n\n"; for (auto it = bare_imports.begin(); it != bare_imports.end(); it++) { code += it->second.import_statement + "\n"; @@ -254,7 +255,9 @@ class TsGenerator : public BaseGenerator { } for (const auto &it : ns_defs_) { - code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n"; + code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n" + + "/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */\n\n"; + // export all definitions in ns entry point module int export_counter = 0; for (const auto &def : it.second.definitions) { @@ -1997,11 +2000,7 @@ class TsGenerator : public BaseGenerator { if (!IsScalar(field.value.type.base_type)) { code += "0"; } else if (HasNullDefault(field)) { - if (IsLong(field.value.type.base_type)) { - code += "BigInt(0)"; - } else { - code += "0"; - } + code += "null"; } else { if (field.value.type.base_type == BASE_TYPE_BOOL) { code += "+"; } code += GenDefaultValue(field, imports); diff --git a/contrib/libs/flatbuffers/src/idl_namer.h b/contrib/libs/flatbuffers/src/idl_namer.h index 337ac920b5..9a7fdb8e36 100644 --- a/contrib/libs/flatbuffers/src/idl_namer.h +++ b/contrib/libs/flatbuffers/src/idl_namer.h @@ -88,8 +88,9 @@ class IdlNamer : public Namer { } std::string Directories(const struct Namespace &ns, - SkipDir skips = SkipDir::None) const { - return Directories(ns.components, skips); + SkipDir skips = SkipDir::None, + Case input_case = Case::kUpperCamel) const { + return Directories(ns.components, skips, input_case); } // Legacy fields do not really follow the usual config and should be diff --git a/contrib/libs/flatbuffers/src/idl_parser.cpp b/contrib/libs/flatbuffers/src/idl_parser.cpp index 8b4f116854..d01e18ef76 100644 --- a/contrib/libs/flatbuffers/src/idl_parser.cpp +++ b/contrib/libs/flatbuffers/src/idl_parser.cpp @@ -2118,7 +2118,7 @@ CheckedError Parser::ParseSingleValue(const std::string *name, Value &e, auto match = false; #define IF_ECHECK_(force, dtoken, check, req) \ - if (!match && ((dtoken) == token_) && ((check) || IsConstTrue(force))) \ + if (!match && ((dtoken) == token_) && ((check) || flatbuffers::IsConstTrue(force))) \ ECHECK(TryTypedValue(name, dtoken, check, e, req, &match)) #define TRY_ECHECK(dtoken, check, req) IF_ECHECK_(false, dtoken, check, req) #define FORCE_ECHECK(dtoken, check, req) IF_ECHECK_(true, dtoken, check, req) @@ -2483,7 +2483,7 @@ CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest, ECHECK(StartEnum(enum_name, is_union, &enum_def)); if (filename != nullptr && !opts.project_root.empty()) { enum_def->declaration_file = - &GetPooledString(RelativeToRootPath(opts.project_root, filename)); + &GetPooledString(FilePath(opts.project_root, filename, opts.binary_schema_absolute_paths)); } enum_def->doc_comment = enum_comment; if (!opts.proto_mode) { @@ -2679,9 +2679,10 @@ std::vector<IncludedFile> Parser::GetIncludedFiles() const { bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts) { static FLATBUFFERS_CONSTEXPR unsigned long supported_langs = IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster | - IDLOptions::kKotlin | IDLOptions::kCpp | IDLOptions::kJava | - IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kBinary | - IDLOptions::kGo | IDLOptions::kPython | IDLOptions::kJson | + IDLOptions::kKotlin | IDLOptions::kKotlinKmp | IDLOptions::kCpp | + IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kTs | + IDLOptions::kBinary | IDLOptions::kGo | IDLOptions::kPython | + IDLOptions::kJson | IDLOptions::kNim; unsigned long langs = opts.lang_to_generate; return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs); @@ -2702,7 +2703,7 @@ bool Parser::SupportsAdvancedUnionFeatures() const { ~(IDLOptions::kCpp | IDLOptions::kTs | IDLOptions::kPhp | IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kKotlin | IDLOptions::kBinary | IDLOptions::kSwift | IDLOptions::kNim | - IDLOptions::kJson)) == 0; + IDLOptions::kJson | IDLOptions::kKotlinKmp)) == 0; } bool Parser::SupportsAdvancedArrayFeatures() const { @@ -2718,7 +2719,8 @@ bool Parser::Supports64BitOffsets() const { } bool Parser::SupportsUnionUnderlyingType() const { - return (opts.lang_to_generate & ~(IDLOptions::kCpp | IDLOptions::kTs)) == 0; + return (opts.lang_to_generate & ~(IDLOptions::kCpp | IDLOptions::kTs | + IDLOptions::kBinary)) == 0; } Namespace *Parser::UniqueNamespace(Namespace *ns) { @@ -2760,7 +2762,7 @@ CheckedError Parser::ParseDecl(const char *filename) { struct_def->fixed = fixed; if (filename && !opts.project_root.empty()) { struct_def->declaration_file = - &GetPooledString(RelativeToRootPath(opts.project_root, filename)); + &GetPooledString(FilePath(opts.project_root, filename, opts.binary_schema_absolute_paths)); } ECHECK(ParseMetaData(&struct_def->attributes)); struct_def->sortbysize = @@ -2854,7 +2856,7 @@ CheckedError Parser::ParseService(const char *filename) { service_def.defined_namespace = current_namespace_; if (filename != nullptr && !opts.project_root.empty()) { service_def.declaration_file = - &GetPooledString(RelativeToRootPath(opts.project_root, filename)); + &GetPooledString(FilePath(opts.project_root, filename, opts.binary_schema_absolute_paths)); } if (services_.Add(current_namespace_->GetFullyQualifiedName(service_name), &service_def)) @@ -3935,11 +3937,12 @@ void Parser::Serialize() { std::vector<Offset<flatbuffers::String>> included_files; for (auto f = files_included_per_file_.begin(); f != files_included_per_file_.end(); f++) { - const auto filename__ = builder_.CreateSharedString( - RelativeToRootPath(opts.project_root, f->first)); + + const auto filename__ = builder_.CreateSharedString(FilePath( + opts.project_root, f->first, opts.binary_schema_absolute_paths)); for (auto i = f->second.begin(); i != f->second.end(); i++) { included_files.push_back(builder_.CreateSharedString( - RelativeToRootPath(opts.project_root, i->filename))); + FilePath(opts.project_root, i->filename, opts.binary_schema_absolute_paths))); } const auto included_files__ = builder_.CreateVector(included_files); included_files.clear(); diff --git a/contrib/libs/flatbuffers/src/namer.h b/contrib/libs/flatbuffers/src/namer.h index 6a7fadcd14..097d4490bc 100644 --- a/contrib/libs/flatbuffers/src/namer.h +++ b/contrib/libs/flatbuffers/src/namer.h @@ -185,15 +185,19 @@ class Namer { // right seperator. Output path prefixing and the trailing separator may be // skiped using `skips`. // Callers may want to use `EnsureDirExists` with the result. + // input_case is used to tell how to modify namespace. e.g. kUpperCamel will + // add a underscode between case changes, so MyGame turns into My_Game + // (depending also on the output_case). virtual std::string Directories(const std::vector<std::string> &directories, - SkipDir skips = SkipDir::None) const { + SkipDir skips = SkipDir::None, + Case input_case = Case::kUpperCamel) const { const bool skip_output_path = (skips & SkipDir::OutputPath) != SkipDir::None; const bool skip_trailing_seperator = (skips & SkipDir::TrailingPathSeperator) != SkipDir::None; std::string result = skip_output_path ? "" : config_.output_path; for (auto d = directories.begin(); d != directories.end(); d++) { - result += ConvertCase(*d, config_.directories, Case::kUpperCamel); + result += ConvertCase(*d, config_.directories, input_case); result.push_back(kPathSeparator); } if (skip_trailing_seperator && !result.empty()) result.pop_back(); diff --git a/contrib/libs/flatbuffers/src/util.cpp b/contrib/libs/flatbuffers/src/util.cpp index b201246fd7..2d45ee7a0d 100644 --- a/contrib/libs/flatbuffers/src/util.cpp +++ b/contrib/libs/flatbuffers/src/util.cpp @@ -336,6 +336,10 @@ void EnsureDirExists(const std::string &filepath) { // clang-format on } +std::string FilePath(const std::string& project, const std::string& filePath, bool absolute) { + return (absolute) ? AbsolutePath(filePath) : RelativeToRootPath(project, filePath); +} + std::string AbsolutePath(const std::string &filepath) { // clang-format off diff --git a/contrib/libs/flatbuffers/ya.make b/contrib/libs/flatbuffers/ya.make index 094f7325e5..f4effd0477 100644 --- a/contrib/libs/flatbuffers/ya.make +++ b/contrib/libs/flatbuffers/ya.make @@ -6,9 +6,9 @@ LICENSE(Apache-2.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(23.5.26) +VERSION(24.3.7) -ORIGINAL_SOURCE(https://github.com/google/flatbuffers/archive/v23.5.26.tar.gz) +ORIGINAL_SOURCE(https://github.com/google/flatbuffers/archive/v24.3.7.tar.gz) PEERDIR( contrib/restricted/abseil-cpp/absl/base |