aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs
diff options
context:
space:
mode:
authorreshilkin <reshilkin@yandex-team.com>2023-08-02 13:42:42 +0300
committerreshilkin <reshilkin@yandex-team.com>2023-08-02 13:42:42 +0300
commit9355caf367a5fa8b2658dc09120a181e17e88646 (patch)
treeedb8bd5125d918304808f1161f8f9a58acd623e8 /contrib/libs
parent65d926376d67e796c234da615753ab7c16021560 (diff)
downloadydb-9355caf367a5fa8b2658dc09120a181e17e88646.tar.gz
Auto code-generation for .fbs.h in arrow
Diffstat (limited to 'contrib/libs')
-rw-r--r--contrib/libs/CMakeLists.darwin-x86_64.txt1
-rw-r--r--contrib/libs/CMakeLists.linux-aarch64.txt1
-rw-r--r--contrib/libs/CMakeLists.linux-x86_64.txt1
-rw-r--r--contrib/libs/CMakeLists.windows-x86_64.txt1
-rw-r--r--contrib/libs/apache/arrow/CMakeLists.darwin-x86_64.txt92
-rw-r--r--contrib/libs/apache/arrow/CMakeLists.linux-aarch64.txt92
-rw-r--r--contrib/libs/apache/arrow/CMakeLists.linux-x86_64.txt92
-rw-r--r--contrib/libs/apache/arrow/CMakeLists.windows-x86_64.txt92
-rw-r--r--contrib/libs/apache/arrow/cpp/src/arrow/ipc/feather.cc6
-rw-r--r--contrib/libs/apache/arrow/cpp/src/arrow/ipc/message.cc2
-rw-r--r--contrib/libs/apache/arrow/cpp/src/arrow/ipc/metadata_internal.cc12
-rw-r--r--contrib/libs/apache/arrow/cpp/src/arrow/ipc/metadata_internal.h6
-rw-r--r--contrib/libs/apache/arrow/cpp/src/arrow/ipc/reader.cc8
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/File.fbs52
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/File_generated.h200
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/Message.fbs140
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/Message_generated.h659
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs430
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/Schema_generated.h2265
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs228
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/SparseTensor_generated.h913
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs54
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/Tensor_generated.h387
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/feather.fbs156
-rw-r--r--contrib/libs/apache/arrow/cpp/src/generated/feather_generated.h863
-rw-r--r--contrib/libs/apache/arrow/ya.make9
-rw-r--r--contrib/libs/flatbuffers/CMakeLists.darwin-x86_64.txt27
-rw-r--r--contrib/libs/flatbuffers/CMakeLists.linux-aarch64.txt28
-rw-r--r--contrib/libs/flatbuffers/CMakeLists.linux-x86_64.txt28
-rw-r--r--contrib/libs/flatbuffers/CMakeLists.txt17
-rw-r--r--contrib/libs/flatbuffers/CMakeLists.windows-x86_64.txt27
-rw-r--r--contrib/libs/flatbuffers/CONTRIBUTING.md42
-rw-r--r--contrib/libs/flatbuffers/LICENSE.txt202
-rw-r--r--contrib/libs/flatbuffers/flatc/CMakeLists.darwin-x86_64.txt52
-rw-r--r--contrib/libs/flatbuffers/flatc/CMakeLists.linux-aarch64.txt53
-rw-r--r--contrib/libs/flatbuffers/flatc/CMakeLists.linux-x86_64.txt53
-rw-r--r--contrib/libs/flatbuffers/flatc/CMakeLists.txt17
-rw-r--r--contrib/libs/flatbuffers/flatc/CMakeLists.windows-x86_64.txt52
-rw-r--r--contrib/libs/flatbuffers/flatc/ya.make56
-rw-r--r--contrib/libs/flatbuffers/grpc/README.md43
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/config.h40
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc1780
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h138
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc501
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/go_generator.h64
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc1135
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/java_generator.h85
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc149
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h33
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h120
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc438
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h55
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc523
-rw-r--r--contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h61
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/code_generators.h235
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h640
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/flatc.h100
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h1636
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/hash.h127
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/idl.h1208
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/reflection.h502
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h1278
-rw-r--r--contrib/libs/flatbuffers/include/flatbuffers/util.h698
-rw-r--r--contrib/libs/flatbuffers/samples/monster.fbs33
-rw-r--r--contrib/libs/flatbuffers/samples/sample_binary.cpp104
-rw-r--r--contrib/libs/flatbuffers/samples/ya.make18
-rw-r--r--contrib/libs/flatbuffers/src/code_generators.cpp395
-rw-r--r--contrib/libs/flatbuffers/src/flatc.cpp554
-rw-r--r--contrib/libs/flatbuffers/src/flatc_main.cpp121
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_cpp.cpp3514
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp731
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_csharp.cpp2100
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_dart.cpp955
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_fbs.cpp154
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_go.cpp1374
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_grpc.cpp557
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_java.cpp1244
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp292
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp1527
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_lobster.cpp391
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_lua.cpp745
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_php.cpp939
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_python.cpp1782
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_rust.cpp2817
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_swift.cpp1575
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_text.cpp414
-rw-r--r--contrib/libs/flatbuffers/src/idl_gen_ts.cpp1583
-rw-r--r--contrib/libs/flatbuffers/src/idl_parser.cpp3986
-rw-r--r--contrib/libs/flatbuffers/src/reflection.cpp713
-rw-r--r--contrib/libs/flatbuffers/src/util.cpp287
-rw-r--r--contrib/libs/flatbuffers/ya.make40
91 files changed, 42646 insertions, 5304 deletions
diff --git a/contrib/libs/CMakeLists.darwin-x86_64.txt b/contrib/libs/CMakeLists.darwin-x86_64.txt
index c0a9e6ecad..7c38598e03 100644
--- a/contrib/libs/CMakeLists.darwin-x86_64.txt
+++ b/contrib/libs/CMakeLists.darwin-x86_64.txt
@@ -21,6 +21,7 @@ add_subdirectory(double-conversion)
add_subdirectory(expat)
add_subdirectory(farmhash)
add_subdirectory(fastlz)
+add_subdirectory(flatbuffers)
add_subdirectory(fmt)
add_subdirectory(googleapis-common-protos)
add_subdirectory(grpc)
diff --git a/contrib/libs/CMakeLists.linux-aarch64.txt b/contrib/libs/CMakeLists.linux-aarch64.txt
index 824ae3431f..af54fc4f93 100644
--- a/contrib/libs/CMakeLists.linux-aarch64.txt
+++ b/contrib/libs/CMakeLists.linux-aarch64.txt
@@ -20,6 +20,7 @@ add_subdirectory(double-conversion)
add_subdirectory(expat)
add_subdirectory(farmhash)
add_subdirectory(fastlz)
+add_subdirectory(flatbuffers)
add_subdirectory(fmt)
add_subdirectory(googleapis-common-protos)
add_subdirectory(grpc)
diff --git a/contrib/libs/CMakeLists.linux-x86_64.txt b/contrib/libs/CMakeLists.linux-x86_64.txt
index e1a97af442..ddfc9ed05a 100644
--- a/contrib/libs/CMakeLists.linux-x86_64.txt
+++ b/contrib/libs/CMakeLists.linux-x86_64.txt
@@ -20,6 +20,7 @@ add_subdirectory(double-conversion)
add_subdirectory(expat)
add_subdirectory(farmhash)
add_subdirectory(fastlz)
+add_subdirectory(flatbuffers)
add_subdirectory(fmt)
add_subdirectory(googleapis-common-protos)
add_subdirectory(grpc)
diff --git a/contrib/libs/CMakeLists.windows-x86_64.txt b/contrib/libs/CMakeLists.windows-x86_64.txt
index f4c4028e47..99a7d95650 100644
--- a/contrib/libs/CMakeLists.windows-x86_64.txt
+++ b/contrib/libs/CMakeLists.windows-x86_64.txt
@@ -20,6 +20,7 @@ add_subdirectory(double-conversion)
add_subdirectory(expat)
add_subdirectory(farmhash)
add_subdirectory(fastlz)
+add_subdirectory(flatbuffers)
add_subdirectory(fmt)
add_subdirectory(googleapis-common-protos)
add_subdirectory(grpc)
diff --git a/contrib/libs/apache/arrow/CMakeLists.darwin-x86_64.txt b/contrib/libs/apache/arrow/CMakeLists.darwin-x86_64.txt
index 94c9dda6b7..25ad7cb3bf 100644
--- a/contrib/libs/apache/arrow/CMakeLists.darwin-x86_64.txt
+++ b/contrib/libs/apache/arrow/CMakeLists.darwin-x86_64.txt
@@ -7,6 +7,42 @@
find_package(ZLIB REQUIRED)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
add_library(libs-apache-arrow)
target_compile_options(libs-apache-arrow PUBLIC
@@ -31,6 +67,7 @@ target_compile_options(libs-apache-arrow PRIVATE
$<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
)
target_include_directories(libs-apache-arrow PUBLIC
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/src
)
@@ -60,6 +97,7 @@ target_link_libraries(libs-apache-arrow PUBLIC
contrib-restricted-fast_float
contrib-restricted-thrift
contrib-restricted-uriparser
+ contrib-libs-flatbuffers
)
target_sources(libs-apache-arrow PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/arrow/adapters/orc/adapter.cc
@@ -262,4 +300,58 @@ target_sources(libs-apache-arrow PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/stream_reader.cc
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/stream_writer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/types.cc
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/File.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs.cpp
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/File.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
)
diff --git a/contrib/libs/apache/arrow/CMakeLists.linux-aarch64.txt b/contrib/libs/apache/arrow/CMakeLists.linux-aarch64.txt
index c7853de814..82596c804a 100644
--- a/contrib/libs/apache/arrow/CMakeLists.linux-aarch64.txt
+++ b/contrib/libs/apache/arrow/CMakeLists.linux-aarch64.txt
@@ -7,6 +7,42 @@
find_package(ZLIB REQUIRED)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
add_library(libs-apache-arrow)
target_compile_options(libs-apache-arrow PUBLIC
@@ -31,6 +67,7 @@ target_compile_options(libs-apache-arrow PRIVATE
$<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
)
target_include_directories(libs-apache-arrow PUBLIC
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/src
)
@@ -61,6 +98,7 @@ target_link_libraries(libs-apache-arrow PUBLIC
contrib-restricted-fast_float
contrib-restricted-thrift
contrib-restricted-uriparser
+ contrib-libs-flatbuffers
)
target_sources(libs-apache-arrow PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/arrow/adapters/orc/adapter.cc
@@ -263,4 +301,58 @@ target_sources(libs-apache-arrow PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/stream_reader.cc
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/stream_writer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/types.cc
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/File.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs.cpp
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/File.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
)
diff --git a/contrib/libs/apache/arrow/CMakeLists.linux-x86_64.txt b/contrib/libs/apache/arrow/CMakeLists.linux-x86_64.txt
index c7853de814..82596c804a 100644
--- a/contrib/libs/apache/arrow/CMakeLists.linux-x86_64.txt
+++ b/contrib/libs/apache/arrow/CMakeLists.linux-x86_64.txt
@@ -7,6 +7,42 @@
find_package(ZLIB REQUIRED)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
add_library(libs-apache-arrow)
target_compile_options(libs-apache-arrow PUBLIC
@@ -31,6 +67,7 @@ target_compile_options(libs-apache-arrow PRIVATE
$<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
)
target_include_directories(libs-apache-arrow PUBLIC
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/src
)
@@ -61,6 +98,7 @@ target_link_libraries(libs-apache-arrow PUBLIC
contrib-restricted-fast_float
contrib-restricted-thrift
contrib-restricted-uriparser
+ contrib-libs-flatbuffers
)
target_sources(libs-apache-arrow PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/arrow/adapters/orc/adapter.cc
@@ -263,4 +301,58 @@ target_sources(libs-apache-arrow PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/stream_reader.cc
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/stream_writer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/types.cc
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/File.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs.cpp
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/File.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
)
diff --git a/contrib/libs/apache/arrow/CMakeLists.windows-x86_64.txt b/contrib/libs/apache/arrow/CMakeLists.windows-x86_64.txt
index 78fddcc593..e0d4023872 100644
--- a/contrib/libs/apache/arrow/CMakeLists.windows-x86_64.txt
+++ b/contrib/libs/apache/arrow/CMakeLists.windows-x86_64.txt
@@ -7,6 +7,42 @@
find_package(ZLIB REQUIRED)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
+get_built_tool_path(
+ TOOL_flatc_bin
+ TOOL_flatc_dependency
+ contrib/tools/flatc/bin
+ flatc
+)
add_library(libs-apache-arrow)
target_compile_options(libs-apache-arrow PUBLIC
@@ -30,6 +66,7 @@ target_compile_options(libs-apache-arrow PRIVATE
$<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
)
target_include_directories(libs-apache-arrow PUBLIC
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/src
)
@@ -59,6 +96,7 @@ target_link_libraries(libs-apache-arrow PUBLIC
contrib-restricted-fast_float
contrib-restricted-thrift
contrib-restricted-uriparser
+ contrib-libs-flatbuffers
)
target_sources(libs-apache-arrow PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/arrow/adapters/orc/adapter.cc
@@ -261,4 +299,58 @@ target_sources(libs-apache-arrow PRIVATE
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/stream_reader.cc
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/stream_writer.cc
${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/parquet/types.cc
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/File.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs.cpp
+ ${CMAKE_BINARY_DIR}/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs.cpp
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/File.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
+)
+target_fbs_source(libs-apache-arrow
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs
+ -I
+ ${CMAKE_BINARY_DIR}
+ -I
+ ${CMAKE_SOURCE_DIR}
)
diff --git a/contrib/libs/apache/arrow/cpp/src/arrow/ipc/feather.cc b/contrib/libs/apache/arrow/cpp/src/arrow/ipc/feather.cc
index b1c30eec0b..ff7726ae4b 100644
--- a/contrib/libs/apache/arrow/cpp/src/arrow/ipc/feather.cc
+++ b/contrib/libs/apache/arrow/cpp/src/arrow/ipc/feather.cc
@@ -49,7 +49,7 @@
#include "arrow/util/make_unique.h"
#include "arrow/visitor_inline.h"
-#include "generated/feather_generated.h"
+#include "generated/feather.fbs.h"
namespace arrow {
@@ -207,8 +207,8 @@ class ReaderV1 : public Reader {
TimeUnit::type unit = FromFlatbufferEnum(meta->unit());
std::string tz;
// flatbuffer non-null
- if (meta->timezone() != 0) {
- tz = meta->timezone()->str();
+ if (meta->time_zone() != 0) {
+ tz = meta->time_zone()->str();
} else {
tz = "";
}
diff --git a/contrib/libs/apache/arrow/cpp/src/arrow/ipc/message.cc b/contrib/libs/apache/arrow/cpp/src/arrow/ipc/message.cc
index 197556efce..dd269a0dc0 100644
--- a/contrib/libs/apache/arrow/cpp/src/arrow/ipc/message.cc
+++ b/contrib/libs/apache/arrow/cpp/src/arrow/ipc/message.cc
@@ -37,7 +37,7 @@
#include "arrow/util/logging.h"
#include "arrow/util/ubsan.h"
-#include "generated/Message_generated.h"
+#include "generated/Message.fbs.h"
namespace arrow {
diff --git a/contrib/libs/apache/arrow/cpp/src/arrow/ipc/metadata_internal.cc b/contrib/libs/apache/arrow/cpp/src/arrow/ipc/metadata_internal.cc
index 4b332bd9e1..ad46cdc58f 100644
--- a/contrib/libs/apache/arrow/cpp/src/arrow/ipc/metadata_internal.cc
+++ b/contrib/libs/apache/arrow/cpp/src/arrow/ipc/metadata_internal.cc
@@ -41,11 +41,11 @@
#include "arrow/util/ubsan.h"
#include "arrow/visitor_inline.h"
-#include "generated/File_generated.h"
-#include "generated/Message_generated.h"
-#include "generated/Schema_generated.h"
-#include "generated/SparseTensor_generated.h"
-#include "generated/Tensor_generated.h"
+#include "generated/File.fbs.h"
+#include "generated/Message.fbs.h"
+#include "generated/Schema.fbs.h"
+#include "generated/SparseTensor.fbs.h"
+#include "generated/Tensor.fbs.h"
namespace arrow {
@@ -312,7 +312,7 @@ Status ConcreteTypeFromFlatbuffer(flatbuf::Type type, const void* type_data,
case flatbuf::Type::Timestamp: {
auto ts_type = static_cast<const flatbuf::Timestamp*>(type_data);
TimeUnit::type unit = FromFlatbufferUnit(ts_type->unit());
- *out = timestamp(unit, StringFromFlatbuffers(ts_type->timezone()));
+ *out = timestamp(unit, StringFromFlatbuffers(ts_type->time_zone()));
return Status::OK();
}
case flatbuf::Type::Duration: {
diff --git a/contrib/libs/apache/arrow/cpp/src/arrow/ipc/metadata_internal.h b/contrib/libs/apache/arrow/cpp/src/arrow/ipc/metadata_internal.h
index 9cf489dd66..9cc24a5d5b 100644
--- a/contrib/libs/apache/arrow/cpp/src/arrow/ipc/metadata_internal.h
+++ b/contrib/libs/apache/arrow/cpp/src/arrow/ipc/metadata_internal.h
@@ -38,9 +38,9 @@
#include "arrow/util/macros.h"
#include "arrow/util/visibility.h"
-#include "generated/Message_generated.h"
-#include "generated/Schema_generated.h"
-#include "generated/SparseTensor_generated.h" // IWYU pragma: keep
+#include "generated/Message.fbs.h"
+#include "generated/Schema.fbs.h"
+#include "generated/SparseTensor.fbs.h" // IWYU pragma: keep
namespace arrow {
diff --git a/contrib/libs/apache/arrow/cpp/src/arrow/ipc/reader.cc b/contrib/libs/apache/arrow/cpp/src/arrow/ipc/reader.cc
index a3c345cc44..eb62a83f04 100644
--- a/contrib/libs/apache/arrow/cpp/src/arrow/ipc/reader.cc
+++ b/contrib/libs/apache/arrow/cpp/src/arrow/ipc/reader.cc
@@ -57,10 +57,10 @@
#include "arrow/util/vector.h"
#include "arrow/visitor_inline.h"
-#include "generated/File_generated.h" // IWYU pragma: export
-#include "generated/Message_generated.h"
-#include "generated/Schema_generated.h"
-#include "generated/SparseTensor_generated.h"
+#include "generated/File.fbs.h" // IWYU pragma: export
+#include "generated/Message.fbs.h"
+#include "generated/Schema.fbs.h"
+#include "generated/SparseTensor.fbs.h"
namespace arrow {
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/File.fbs b/contrib/libs/apache/arrow/cpp/src/generated/File.fbs
new file mode 100644
index 0000000000..906d494f27
--- /dev/null
+++ b/contrib/libs/apache/arrow/cpp/src/generated/File.fbs
@@ -0,0 +1,52 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.
+
+include "Schema.fbs";
+
+namespace org.apache.arrow.flatbuf;
+
+/// ----------------------------------------------------------------------
+/// Arrow File metadata
+///
+
+table Footer {
+ version: org.apache.arrow.flatbuf.MetadataVersion;
+
+ schema: org.apache.arrow.flatbuf.Schema;
+
+ dictionaries: [ Block ];
+
+ recordBatches: [ Block ];
+
+ /// User-defined metadata
+ custom_metadata: [ KeyValue ];
+}
+
+struct Block {
+
+ /// Index to the start of the RecordBlock (note this is past the Message header)
+ offset: long;
+
+ /// Length of the metadata
+ metaDataLength: int;
+
+ /// Length of the data (this is aligned so there can be a gap between this and
+ /// the metadata).
+ bodyLength: long;
+}
+
+root_type Footer;
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/File_generated.h b/contrib/libs/apache/arrow/cpp/src/generated/File_generated.h
deleted file mode 100644
index 06953c4a04..0000000000
--- a/contrib/libs/apache/arrow/cpp/src/generated/File_generated.h
+++ /dev/null
@@ -1,200 +0,0 @@
-// automatically generated by the FlatBuffers compiler, do not modify
-
-
-#ifndef FLATBUFFERS_GENERATED_FILE_ORG_APACHE_ARROW_FLATBUF_H_
-#define FLATBUFFERS_GENERATED_FILE_ORG_APACHE_ARROW_FLATBUF_H_
-
-#include "flatbuffers/flatbuffers.h"
-
-#include "Schema_generated.h"
-
-namespace org {
-namespace apache {
-namespace arrow {
-namespace flatbuf {
-
-struct Footer;
-struct FooterBuilder;
-
-struct Block;
-
-FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Block FLATBUFFERS_FINAL_CLASS {
- private:
- int64_t offset_;
- int32_t metaDataLength_;
- int32_t padding0__;
- int64_t bodyLength_;
-
- public:
- Block() {
- memset(static_cast<void *>(this), 0, sizeof(Block));
- }
- Block(int64_t _offset, int32_t _metaDataLength, int64_t _bodyLength)
- : offset_(flatbuffers::EndianScalar(_offset)),
- metaDataLength_(flatbuffers::EndianScalar(_metaDataLength)),
- padding0__(0),
- bodyLength_(flatbuffers::EndianScalar(_bodyLength)) {
- (void)padding0__;
- }
- /// Index to the start of the RecordBlock (note this is past the Message header)
- int64_t offset() const {
- return flatbuffers::EndianScalar(offset_);
- }
- /// Length of the metadata
- int32_t metaDataLength() const {
- return flatbuffers::EndianScalar(metaDataLength_);
- }
- /// Length of the data (this is aligned so there can be a gap between this and
- /// the metadata).
- int64_t bodyLength() const {
- return flatbuffers::EndianScalar(bodyLength_);
- }
-};
-FLATBUFFERS_STRUCT_END(Block, 24);
-
-/// ----------------------------------------------------------------------
-/// Arrow File metadata
-///
-struct Footer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef FooterBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_VERSION = 4,
- VT_SCHEMA = 6,
- VT_DICTIONARIES = 8,
- VT_RECORDBATCHES = 10,
- VT_CUSTOM_METADATA = 12
- };
- org::apache::arrow::flatbuf::MetadataVersion version() const {
- return static_cast<org::apache::arrow::flatbuf::MetadataVersion>(GetField<int16_t>(VT_VERSION, 0));
- }
- const org::apache::arrow::flatbuf::Schema *schema() const {
- return GetPointer<const org::apache::arrow::flatbuf::Schema *>(VT_SCHEMA);
- }
- const flatbuffers::Vector<const org::apache::arrow::flatbuf::Block *> *dictionaries() const {
- return GetPointer<const flatbuffers::Vector<const org::apache::arrow::flatbuf::Block *> *>(VT_DICTIONARIES);
- }
- const flatbuffers::Vector<const org::apache::arrow::flatbuf::Block *> *recordBatches() const {
- return GetPointer<const flatbuffers::Vector<const org::apache::arrow::flatbuf::Block *> *>(VT_RECORDBATCHES);
- }
- /// User-defined metadata
- const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *custom_metadata() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *>(VT_CUSTOM_METADATA);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_VERSION) &&
- VerifyOffset(verifier, VT_SCHEMA) &&
- verifier.VerifyTable(schema()) &&
- VerifyOffset(verifier, VT_DICTIONARIES) &&
- verifier.VerifyVector(dictionaries()) &&
- VerifyOffset(verifier, VT_RECORDBATCHES) &&
- verifier.VerifyVector(recordBatches()) &&
- VerifyOffset(verifier, VT_CUSTOM_METADATA) &&
- verifier.VerifyVector(custom_metadata()) &&
- verifier.VerifyVectorOfTables(custom_metadata()) &&
- verifier.EndTable();
- }
-};
-
-struct FooterBuilder {
- typedef Footer Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_version(org::apache::arrow::flatbuf::MetadataVersion version) {
- fbb_.AddElement<int16_t>(Footer::VT_VERSION, static_cast<int16_t>(version), 0);
- }
- void add_schema(flatbuffers::Offset<org::apache::arrow::flatbuf::Schema> schema) {
- fbb_.AddOffset(Footer::VT_SCHEMA, schema);
- }
- void add_dictionaries(flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::Block *>> dictionaries) {
- fbb_.AddOffset(Footer::VT_DICTIONARIES, dictionaries);
- }
- void add_recordBatches(flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::Block *>> recordBatches) {
- fbb_.AddOffset(Footer::VT_RECORDBATCHES, recordBatches);
- }
- void add_custom_metadata(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>> custom_metadata) {
- fbb_.AddOffset(Footer::VT_CUSTOM_METADATA, custom_metadata);
- }
- explicit FooterBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- FooterBuilder &operator=(const FooterBuilder &);
- flatbuffers::Offset<Footer> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Footer>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Footer> CreateFooter(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::MetadataVersion version = org::apache::arrow::flatbuf::MetadataVersion::V1,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Schema> schema = 0,
- flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::Block *>> dictionaries = 0,
- flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::Block *>> recordBatches = 0,
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>> custom_metadata = 0) {
- FooterBuilder builder_(_fbb);
- builder_.add_custom_metadata(custom_metadata);
- builder_.add_recordBatches(recordBatches);
- builder_.add_dictionaries(dictionaries);
- builder_.add_schema(schema);
- builder_.add_version(version);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<Footer> CreateFooterDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::MetadataVersion version = org::apache::arrow::flatbuf::MetadataVersion::V1,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Schema> schema = 0,
- const std::vector<org::apache::arrow::flatbuf::Block> *dictionaries = nullptr,
- const std::vector<org::apache::arrow::flatbuf::Block> *recordBatches = nullptr,
- const std::vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *custom_metadata = nullptr) {
- auto dictionaries__ = dictionaries ? _fbb.CreateVectorOfStructs<org::apache::arrow::flatbuf::Block>(*dictionaries) : 0;
- auto recordBatches__ = recordBatches ? _fbb.CreateVectorOfStructs<org::apache::arrow::flatbuf::Block>(*recordBatches) : 0;
- auto custom_metadata__ = custom_metadata ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>(*custom_metadata) : 0;
- return org::apache::arrow::flatbuf::CreateFooter(
- _fbb,
- version,
- schema,
- dictionaries__,
- recordBatches__,
- custom_metadata__);
-}
-
-inline const org::apache::arrow::flatbuf::Footer *GetFooter(const void *buf) {
- return flatbuffers::GetRoot<org::apache::arrow::flatbuf::Footer>(buf);
-}
-
-inline const org::apache::arrow::flatbuf::Footer *GetSizePrefixedFooter(const void *buf) {
- return flatbuffers::GetSizePrefixedRoot<org::apache::arrow::flatbuf::Footer>(buf);
-}
-
-inline bool VerifyFooterBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifyBuffer<org::apache::arrow::flatbuf::Footer>(nullptr);
-}
-
-inline bool VerifySizePrefixedFooterBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifySizePrefixedBuffer<org::apache::arrow::flatbuf::Footer>(nullptr);
-}
-
-inline void FinishFooterBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Footer> root) {
- fbb.Finish(root);
-}
-
-inline void FinishSizePrefixedFooterBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Footer> root) {
- fbb.FinishSizePrefixed(root);
-}
-
-} // namespace flatbuf
-} // namespace arrow
-} // namespace apache
-} // namespace org
-
-#endif // FLATBUFFERS_GENERATED_FILE_ORG_APACHE_ARROW_FLATBUF_H_
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs b/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs
new file mode 100644
index 0000000000..f1c18d765d
--- /dev/null
+++ b/contrib/libs/apache/arrow/cpp/src/generated/Message.fbs
@@ -0,0 +1,140 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.
+
+include "Schema.fbs";
+include "SparseTensor.fbs";
+include "Tensor.fbs";
+
+namespace org.apache.arrow.flatbuf;
+
+/// ----------------------------------------------------------------------
+/// Data structures for describing a table row batch (a collection of
+/// equal-length Arrow arrays)
+
+/// Metadata about a field at some level of a nested type tree (but not
+/// its children).
+///
+/// For example, a List<Int16> with values `[[1, 2, 3], null, [4], [5, 6], null]`
+/// would have {length: 5, null_count: 2} for its List node, and {length: 6,
+/// null_count: 0} for its Int16 node, as separate FieldNode structs
+struct FieldNode {
+ /// The number of value slots in the Arrow array at this level of a nested
+ /// tree
+ length: long;
+
+ /// The number of observed nulls. Fields with null_count == 0 may choose not
+ /// to write their physical validity bitmap out as a materialized buffer,
+ /// instead setting the length of the bitmap buffer to 0.
+ null_count: long;
+}
+
+enum CompressionType:byte {
+ // LZ4 frame format, for portability, as provided by lz4frame.h or wrappers
+ // thereof. Not to be confused with "raw" (also called "block") format
+ // provided by lz4.h
+ LZ4_FRAME,
+
+ // Zstandard
+ ZSTD
+}
+
+/// Provided for forward compatibility in case we need to support different
+/// strategies for compressing the IPC message body (like whole-body
+/// compression rather than buffer-level) in the future
+enum BodyCompressionMethod:byte {
+ /// Each constituent buffer is first compressed with the indicated
+ /// compressor, and then written with the uncompressed length in the first 8
+ /// bytes as a 64-bit little-endian signed integer followed by the compressed
+ /// buffer bytes (and then padding as required by the protocol). The
+ /// uncompressed length may be set to -1 to indicate that the data that
+ /// follows is not compressed, which can be useful for cases where
+ /// compression does not yield appreciable savings.
+ BUFFER
+}
+
+/// Optional compression for the memory buffers constituting IPC message
+/// bodies. Intended for use with RecordBatch but could be used for other
+/// message types
+table BodyCompression {
+ /// Compressor library
+ codec: CompressionType = LZ4_FRAME;
+
+ /// Indicates the way the record batch body was compressed
+ method: BodyCompressionMethod = BUFFER;
+}
+
+/// A data header describing the shared memory layout of a "record" or "row"
+/// batch. Some systems call this a "row batch" internally and others a "record
+/// batch".
+table RecordBatch {
+ /// number of records / rows. The arrays in the batch should all have this
+ /// length
+ length: long;
+
+ /// Nodes correspond to the pre-ordered flattened logical schema
+ nodes: [FieldNode];
+
+ /// Buffers correspond to the pre-ordered flattened buffer tree
+ ///
+ /// The number of buffers appended to this list depends on the schema. For
+ /// example, most primitive arrays will have 2 buffers, 1 for the validity
+ /// bitmap and 1 for the values. For struct arrays, there will only be a
+ /// single buffer for the validity (nulls) bitmap
+ buffers: [Buffer];
+
+ /// Optional compression of the message body
+ compression: BodyCompression;
+}
+
+/// For sending dictionary encoding information. Any Field can be
+/// dictionary-encoded, but in this case none of its children may be
+/// dictionary-encoded.
+/// There is one vector / column per dictionary, but that vector / column
+/// may be spread across multiple dictionary batches by using the isDelta
+/// flag
+
+table DictionaryBatch {
+ id: long;
+ data: RecordBatch;
+
+ /// If isDelta is true the values in the dictionary are to be appended to a
+ /// dictionary with the indicated id. If isDelta is false this dictionary
+ /// should replace the existing dictionary.
+ isDelta: bool = false;
+}
+
+/// ----------------------------------------------------------------------
+/// The root Message type
+
+/// This union enables us to easily send different message types without
+/// redundant storage, and in the future we can easily add new message types.
+///
+/// Arrow implementations do not need to implement all of the message types,
+/// which may include experimental metadata types. For maximum compatibility,
+/// it is best to send data using RecordBatch
+union MessageHeader {
+ Schema, DictionaryBatch, RecordBatch, Tensor, SparseTensor
+}
+
+table Message {
+ version: org.apache.arrow.flatbuf.MetadataVersion;
+ header: MessageHeader;
+ bodyLength: long;
+ custom_metadata: [ KeyValue ];
+}
+
+root_type Message;
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/Message_generated.h b/contrib/libs/apache/arrow/cpp/src/generated/Message_generated.h
deleted file mode 100644
index 822bec9952..0000000000
--- a/contrib/libs/apache/arrow/cpp/src/generated/Message_generated.h
+++ /dev/null
@@ -1,659 +0,0 @@
-// automatically generated by the FlatBuffers compiler, do not modify
-
-
-#ifndef FLATBUFFERS_GENERATED_MESSAGE_ORG_APACHE_ARROW_FLATBUF_H_
-#define FLATBUFFERS_GENERATED_MESSAGE_ORG_APACHE_ARROW_FLATBUF_H_
-
-#include "flatbuffers/flatbuffers.h"
-
-#include "Schema_generated.h"
-#include "SparseTensor_generated.h"
-#include "Tensor_generated.h"
-
-namespace org {
-namespace apache {
-namespace arrow {
-namespace flatbuf {
-
-struct FieldNode;
-
-struct BodyCompression;
-struct BodyCompressionBuilder;
-
-struct RecordBatch;
-struct RecordBatchBuilder;
-
-struct DictionaryBatch;
-struct DictionaryBatchBuilder;
-
-struct Message;
-struct MessageBuilder;
-
-enum class CompressionType : int8_t {
- LZ4_FRAME = 0,
- ZSTD = 1,
- MIN = LZ4_FRAME,
- MAX = ZSTD
-};
-
-inline const CompressionType (&EnumValuesCompressionType())[2] {
- static const CompressionType values[] = {
- CompressionType::LZ4_FRAME,
- CompressionType::ZSTD
- };
- return values;
-}
-
-inline const char * const *EnumNamesCompressionType() {
- static const char * const names[3] = {
- "LZ4_FRAME",
- "ZSTD",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameCompressionType(CompressionType e) {
- if (flatbuffers::IsOutRange(e, CompressionType::LZ4_FRAME, CompressionType::ZSTD)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesCompressionType()[index];
-}
-
-/// Provided for forward compatibility in case we need to support different
-/// strategies for compressing the IPC message body (like whole-body
-/// compression rather than buffer-level) in the future
-enum class BodyCompressionMethod : int8_t {
- /// Each constituent buffer is first compressed with the indicated
- /// compressor, and then written with the uncompressed length in the first 8
- /// bytes as a 64-bit little-endian signed integer followed by the compressed
- /// buffer bytes (and then padding as required by the protocol). The
- /// uncompressed length may be set to -1 to indicate that the data that
- /// follows is not compressed, which can be useful for cases where
- /// compression does not yield appreciable savings.
- BUFFER = 0,
- MIN = BUFFER,
- MAX = BUFFER
-};
-
-inline const BodyCompressionMethod (&EnumValuesBodyCompressionMethod())[1] {
- static const BodyCompressionMethod values[] = {
- BodyCompressionMethod::BUFFER
- };
- return values;
-}
-
-inline const char * const *EnumNamesBodyCompressionMethod() {
- static const char * const names[2] = {
- "BUFFER",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameBodyCompressionMethod(BodyCompressionMethod e) {
- if (flatbuffers::IsOutRange(e, BodyCompressionMethod::BUFFER, BodyCompressionMethod::BUFFER)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesBodyCompressionMethod()[index];
-}
-
-/// ----------------------------------------------------------------------
-/// The root Message type
-/// This union enables us to easily send different message types without
-/// redundant storage, and in the future we can easily add new message types.
-///
-/// Arrow implementations do not need to implement all of the message types,
-/// which may include experimental metadata types. For maximum compatibility,
-/// it is best to send data using RecordBatch
-enum class MessageHeader : uint8_t {
- NONE = 0,
- Schema = 1,
- DictionaryBatch = 2,
- RecordBatch = 3,
- Tensor = 4,
- SparseTensor = 5,
- MIN = NONE,
- MAX = SparseTensor
-};
-
-inline const MessageHeader (&EnumValuesMessageHeader())[6] {
- static const MessageHeader values[] = {
- MessageHeader::NONE,
- MessageHeader::Schema,
- MessageHeader::DictionaryBatch,
- MessageHeader::RecordBatch,
- MessageHeader::Tensor,
- MessageHeader::SparseTensor
- };
- return values;
-}
-
-inline const char * const *EnumNamesMessageHeader() {
- static const char * const names[7] = {
- "NONE",
- "Schema",
- "DictionaryBatch",
- "RecordBatch",
- "Tensor",
- "SparseTensor",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameMessageHeader(MessageHeader e) {
- if (flatbuffers::IsOutRange(e, MessageHeader::NONE, MessageHeader::SparseTensor)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesMessageHeader()[index];
-}
-
-template<typename T> struct MessageHeaderTraits {
- static const MessageHeader enum_value = MessageHeader::NONE;
-};
-
-template<> struct MessageHeaderTraits<org::apache::arrow::flatbuf::Schema> {
- static const MessageHeader enum_value = MessageHeader::Schema;
-};
-
-template<> struct MessageHeaderTraits<org::apache::arrow::flatbuf::DictionaryBatch> {
- static const MessageHeader enum_value = MessageHeader::DictionaryBatch;
-};
-
-template<> struct MessageHeaderTraits<org::apache::arrow::flatbuf::RecordBatch> {
- static const MessageHeader enum_value = MessageHeader::RecordBatch;
-};
-
-template<> struct MessageHeaderTraits<org::apache::arrow::flatbuf::Tensor> {
- static const MessageHeader enum_value = MessageHeader::Tensor;
-};
-
-template<> struct MessageHeaderTraits<org::apache::arrow::flatbuf::SparseTensor> {
- static const MessageHeader enum_value = MessageHeader::SparseTensor;
-};
-
-bool VerifyMessageHeader(flatbuffers::Verifier &verifier, const void *obj, MessageHeader type);
-bool VerifyMessageHeaderVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
-
-/// ----------------------------------------------------------------------
-/// Data structures for describing a table row batch (a collection of
-/// equal-length Arrow arrays)
-/// Metadata about a field at some level of a nested type tree (but not
-/// its children).
-///
-/// For example, a List<Int16> with values [[1, 2, 3], null, [4], [5, 6], null]
-/// would have {length: 5, null_count: 2} for its List node, and {length: 6,
-/// null_count: 0} for its Int16 node, as separate FieldNode structs
-FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) FieldNode FLATBUFFERS_FINAL_CLASS {
- private:
- int64_t length_;
- int64_t null_count_;
-
- public:
- FieldNode() {
- memset(static_cast<void *>(this), 0, sizeof(FieldNode));
- }
- FieldNode(int64_t _length, int64_t _null_count)
- : length_(flatbuffers::EndianScalar(_length)),
- null_count_(flatbuffers::EndianScalar(_null_count)) {
- }
- /// The number of value slots in the Arrow array at this level of a nested
- /// tree
- int64_t length() const {
- return flatbuffers::EndianScalar(length_);
- }
- /// The number of observed nulls. Fields with null_count == 0 may choose not
- /// to write their physical validity bitmap out as a materialized buffer,
- /// instead setting the length of the bitmap buffer to 0.
- int64_t null_count() const {
- return flatbuffers::EndianScalar(null_count_);
- }
-};
-FLATBUFFERS_STRUCT_END(FieldNode, 16);
-
-/// Optional compression for the memory buffers constituting IPC message
-/// bodies. Intended for use with RecordBatch but could be used for other
-/// message types
-struct BodyCompression FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef BodyCompressionBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_CODEC = 4,
- VT_METHOD = 6
- };
- /// Compressor library
- org::apache::arrow::flatbuf::CompressionType codec() const {
- return static_cast<org::apache::arrow::flatbuf::CompressionType>(GetField<int8_t>(VT_CODEC, 0));
- }
- /// Indicates the way the record batch body was compressed
- org::apache::arrow::flatbuf::BodyCompressionMethod method() const {
- return static_cast<org::apache::arrow::flatbuf::BodyCompressionMethod>(GetField<int8_t>(VT_METHOD, 0));
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int8_t>(verifier, VT_CODEC) &&
- VerifyField<int8_t>(verifier, VT_METHOD) &&
- verifier.EndTable();
- }
-};
-
-struct BodyCompressionBuilder {
- typedef BodyCompression Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_codec(org::apache::arrow::flatbuf::CompressionType codec) {
- fbb_.AddElement<int8_t>(BodyCompression::VT_CODEC, static_cast<int8_t>(codec), 0);
- }
- void add_method(org::apache::arrow::flatbuf::BodyCompressionMethod method) {
- fbb_.AddElement<int8_t>(BodyCompression::VT_METHOD, static_cast<int8_t>(method), 0);
- }
- explicit BodyCompressionBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- BodyCompressionBuilder &operator=(const BodyCompressionBuilder &);
- flatbuffers::Offset<BodyCompression> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<BodyCompression>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<BodyCompression> CreateBodyCompression(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::CompressionType codec = org::apache::arrow::flatbuf::CompressionType::LZ4_FRAME,
- org::apache::arrow::flatbuf::BodyCompressionMethod method = org::apache::arrow::flatbuf::BodyCompressionMethod::BUFFER) {
- BodyCompressionBuilder builder_(_fbb);
- builder_.add_method(method);
- builder_.add_codec(codec);
- return builder_.Finish();
-}
-
-/// A data header describing the shared memory layout of a "record" or "row"
-/// batch. Some systems call this a "row batch" internally and others a "record
-/// batch".
-struct RecordBatch FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef RecordBatchBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_LENGTH = 4,
- VT_NODES = 6,
- VT_BUFFERS = 8,
- VT_COMPRESSION = 10
- };
- /// number of records / rows. The arrays in the batch should all have this
- /// length
- int64_t length() const {
- return GetField<int64_t>(VT_LENGTH, 0);
- }
- /// Nodes correspond to the pre-ordered flattened logical schema
- const flatbuffers::Vector<const org::apache::arrow::flatbuf::FieldNode *> *nodes() const {
- return GetPointer<const flatbuffers::Vector<const org::apache::arrow::flatbuf::FieldNode *> *>(VT_NODES);
- }
- /// Buffers correspond to the pre-ordered flattened buffer tree
- ///
- /// The number of buffers appended to this list depends on the schema. For
- /// example, most primitive arrays will have 2 buffers, 1 for the validity
- /// bitmap and 1 for the values. For struct arrays, there will only be a
- /// single buffer for the validity (nulls) bitmap
- const flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *> *buffers() const {
- return GetPointer<const flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *> *>(VT_BUFFERS);
- }
- /// Optional compression of the message body
- const org::apache::arrow::flatbuf::BodyCompression *compression() const {
- return GetPointer<const org::apache::arrow::flatbuf::BodyCompression *>(VT_COMPRESSION);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int64_t>(verifier, VT_LENGTH) &&
- VerifyOffset(verifier, VT_NODES) &&
- verifier.VerifyVector(nodes()) &&
- VerifyOffset(verifier, VT_BUFFERS) &&
- verifier.VerifyVector(buffers()) &&
- VerifyOffset(verifier, VT_COMPRESSION) &&
- verifier.VerifyTable(compression()) &&
- verifier.EndTable();
- }
-};
-
-struct RecordBatchBuilder {
- typedef RecordBatch Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_length(int64_t length) {
- fbb_.AddElement<int64_t>(RecordBatch::VT_LENGTH, length, 0);
- }
- void add_nodes(flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::FieldNode *>> nodes) {
- fbb_.AddOffset(RecordBatch::VT_NODES, nodes);
- }
- void add_buffers(flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *>> buffers) {
- fbb_.AddOffset(RecordBatch::VT_BUFFERS, buffers);
- }
- void add_compression(flatbuffers::Offset<org::apache::arrow::flatbuf::BodyCompression> compression) {
- fbb_.AddOffset(RecordBatch::VT_COMPRESSION, compression);
- }
- explicit RecordBatchBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- RecordBatchBuilder &operator=(const RecordBatchBuilder &);
- flatbuffers::Offset<RecordBatch> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<RecordBatch>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<RecordBatch> CreateRecordBatch(
- flatbuffers::FlatBufferBuilder &_fbb,
- int64_t length = 0,
- flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::FieldNode *>> nodes = 0,
- flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *>> buffers = 0,
- flatbuffers::Offset<org::apache::arrow::flatbuf::BodyCompression> compression = 0) {
- RecordBatchBuilder builder_(_fbb);
- builder_.add_length(length);
- builder_.add_compression(compression);
- builder_.add_buffers(buffers);
- builder_.add_nodes(nodes);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<RecordBatch> CreateRecordBatchDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- int64_t length = 0,
- const std::vector<org::apache::arrow::flatbuf::FieldNode> *nodes = nullptr,
- const std::vector<org::apache::arrow::flatbuf::Buffer> *buffers = nullptr,
- flatbuffers::Offset<org::apache::arrow::flatbuf::BodyCompression> compression = 0) {
- auto nodes__ = nodes ? _fbb.CreateVectorOfStructs<org::apache::arrow::flatbuf::FieldNode>(*nodes) : 0;
- auto buffers__ = buffers ? _fbb.CreateVectorOfStructs<org::apache::arrow::flatbuf::Buffer>(*buffers) : 0;
- return org::apache::arrow::flatbuf::CreateRecordBatch(
- _fbb,
- length,
- nodes__,
- buffers__,
- compression);
-}
-
-/// For sending dictionary encoding information. Any Field can be
-/// dictionary-encoded, but in this case none of its children may be
-/// dictionary-encoded.
-/// There is one vector / column per dictionary, but that vector / column
-/// may be spread across multiple dictionary batches by using the isDelta
-/// flag
-struct DictionaryBatch FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef DictionaryBatchBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_ID = 4,
- VT_DATA = 6,
- VT_ISDELTA = 8
- };
- int64_t id() const {
- return GetField<int64_t>(VT_ID, 0);
- }
- const org::apache::arrow::flatbuf::RecordBatch *data() const {
- return GetPointer<const org::apache::arrow::flatbuf::RecordBatch *>(VT_DATA);
- }
- /// If isDelta is true the values in the dictionary are to be appended to a
- /// dictionary with the indicated id. If isDelta is false this dictionary
- /// should replace the existing dictionary.
- bool isDelta() const {
- return GetField<uint8_t>(VT_ISDELTA, 0) != 0;
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int64_t>(verifier, VT_ID) &&
- VerifyOffset(verifier, VT_DATA) &&
- verifier.VerifyTable(data()) &&
- VerifyField<uint8_t>(verifier, VT_ISDELTA) &&
- verifier.EndTable();
- }
-};
-
-struct DictionaryBatchBuilder {
- typedef DictionaryBatch Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_id(int64_t id) {
- fbb_.AddElement<int64_t>(DictionaryBatch::VT_ID, id, 0);
- }
- void add_data(flatbuffers::Offset<org::apache::arrow::flatbuf::RecordBatch> data) {
- fbb_.AddOffset(DictionaryBatch::VT_DATA, data);
- }
- void add_isDelta(bool isDelta) {
- fbb_.AddElement<uint8_t>(DictionaryBatch::VT_ISDELTA, static_cast<uint8_t>(isDelta), 0);
- }
- explicit DictionaryBatchBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- DictionaryBatchBuilder &operator=(const DictionaryBatchBuilder &);
- flatbuffers::Offset<DictionaryBatch> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<DictionaryBatch>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<DictionaryBatch> CreateDictionaryBatch(
- flatbuffers::FlatBufferBuilder &_fbb,
- int64_t id = 0,
- flatbuffers::Offset<org::apache::arrow::flatbuf::RecordBatch> data = 0,
- bool isDelta = false) {
- DictionaryBatchBuilder builder_(_fbb);
- builder_.add_id(id);
- builder_.add_data(data);
- builder_.add_isDelta(isDelta);
- return builder_.Finish();
-}
-
-struct Message FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef MessageBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_VERSION = 4,
- VT_HEADER_TYPE = 6,
- VT_HEADER = 8,
- VT_BODYLENGTH = 10,
- VT_CUSTOM_METADATA = 12
- };
- org::apache::arrow::flatbuf::MetadataVersion version() const {
- return static_cast<org::apache::arrow::flatbuf::MetadataVersion>(GetField<int16_t>(VT_VERSION, 0));
- }
- org::apache::arrow::flatbuf::MessageHeader header_type() const {
- return static_cast<org::apache::arrow::flatbuf::MessageHeader>(GetField<uint8_t>(VT_HEADER_TYPE, 0));
- }
- const void *header() const {
- return GetPointer<const void *>(VT_HEADER);
- }
- template<typename T> const T *header_as() const;
- const org::apache::arrow::flatbuf::Schema *header_as_Schema() const {
- return header_type() == org::apache::arrow::flatbuf::MessageHeader::Schema ? static_cast<const org::apache::arrow::flatbuf::Schema *>(header()) : nullptr;
- }
- const org::apache::arrow::flatbuf::DictionaryBatch *header_as_DictionaryBatch() const {
- return header_type() == org::apache::arrow::flatbuf::MessageHeader::DictionaryBatch ? static_cast<const org::apache::arrow::flatbuf::DictionaryBatch *>(header()) : nullptr;
- }
- const org::apache::arrow::flatbuf::RecordBatch *header_as_RecordBatch() const {
- return header_type() == org::apache::arrow::flatbuf::MessageHeader::RecordBatch ? static_cast<const org::apache::arrow::flatbuf::RecordBatch *>(header()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Tensor *header_as_Tensor() const {
- return header_type() == org::apache::arrow::flatbuf::MessageHeader::Tensor ? static_cast<const org::apache::arrow::flatbuf::Tensor *>(header()) : nullptr;
- }
- const org::apache::arrow::flatbuf::SparseTensor *header_as_SparseTensor() const {
- return header_type() == org::apache::arrow::flatbuf::MessageHeader::SparseTensor ? static_cast<const org::apache::arrow::flatbuf::SparseTensor *>(header()) : nullptr;
- }
- int64_t bodyLength() const {
- return GetField<int64_t>(VT_BODYLENGTH, 0);
- }
- const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *custom_metadata() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *>(VT_CUSTOM_METADATA);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_VERSION) &&
- VerifyField<uint8_t>(verifier, VT_HEADER_TYPE) &&
- VerifyOffset(verifier, VT_HEADER) &&
- VerifyMessageHeader(verifier, header(), header_type()) &&
- VerifyField<int64_t>(verifier, VT_BODYLENGTH) &&
- VerifyOffset(verifier, VT_CUSTOM_METADATA) &&
- verifier.VerifyVector(custom_metadata()) &&
- verifier.VerifyVectorOfTables(custom_metadata()) &&
- verifier.EndTable();
- }
-};
-
-template<> inline const org::apache::arrow::flatbuf::Schema *Message::header_as<org::apache::arrow::flatbuf::Schema>() const {
- return header_as_Schema();
-}
-
-template<> inline const org::apache::arrow::flatbuf::DictionaryBatch *Message::header_as<org::apache::arrow::flatbuf::DictionaryBatch>() const {
- return header_as_DictionaryBatch();
-}
-
-template<> inline const org::apache::arrow::flatbuf::RecordBatch *Message::header_as<org::apache::arrow::flatbuf::RecordBatch>() const {
- return header_as_RecordBatch();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Tensor *Message::header_as<org::apache::arrow::flatbuf::Tensor>() const {
- return header_as_Tensor();
-}
-
-template<> inline const org::apache::arrow::flatbuf::SparseTensor *Message::header_as<org::apache::arrow::flatbuf::SparseTensor>() const {
- return header_as_SparseTensor();
-}
-
-struct MessageBuilder {
- typedef Message Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_version(org::apache::arrow::flatbuf::MetadataVersion version) {
- fbb_.AddElement<int16_t>(Message::VT_VERSION, static_cast<int16_t>(version), 0);
- }
- void add_header_type(org::apache::arrow::flatbuf::MessageHeader header_type) {
- fbb_.AddElement<uint8_t>(Message::VT_HEADER_TYPE, static_cast<uint8_t>(header_type), 0);
- }
- void add_header(flatbuffers::Offset<void> header) {
- fbb_.AddOffset(Message::VT_HEADER, header);
- }
- void add_bodyLength(int64_t bodyLength) {
- fbb_.AddElement<int64_t>(Message::VT_BODYLENGTH, bodyLength, 0);
- }
- void add_custom_metadata(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>> custom_metadata) {
- fbb_.AddOffset(Message::VT_CUSTOM_METADATA, custom_metadata);
- }
- explicit MessageBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- MessageBuilder &operator=(const MessageBuilder &);
- flatbuffers::Offset<Message> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Message>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Message> CreateMessage(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::MetadataVersion version = org::apache::arrow::flatbuf::MetadataVersion::V1,
- org::apache::arrow::flatbuf::MessageHeader header_type = org::apache::arrow::flatbuf::MessageHeader::NONE,
- flatbuffers::Offset<void> header = 0,
- int64_t bodyLength = 0,
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>> custom_metadata = 0) {
- MessageBuilder builder_(_fbb);
- builder_.add_bodyLength(bodyLength);
- builder_.add_custom_metadata(custom_metadata);
- builder_.add_header(header);
- builder_.add_version(version);
- builder_.add_header_type(header_type);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<Message> CreateMessageDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::MetadataVersion version = org::apache::arrow::flatbuf::MetadataVersion::V1,
- org::apache::arrow::flatbuf::MessageHeader header_type = org::apache::arrow::flatbuf::MessageHeader::NONE,
- flatbuffers::Offset<void> header = 0,
- int64_t bodyLength = 0,
- const std::vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *custom_metadata = nullptr) {
- auto custom_metadata__ = custom_metadata ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>(*custom_metadata) : 0;
- return org::apache::arrow::flatbuf::CreateMessage(
- _fbb,
- version,
- header_type,
- header,
- bodyLength,
- custom_metadata__);
-}
-
-inline bool VerifyMessageHeader(flatbuffers::Verifier &verifier, const void *obj, MessageHeader type) {
- switch (type) {
- case MessageHeader::NONE: {
- return true;
- }
- case MessageHeader::Schema: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Schema *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case MessageHeader::DictionaryBatch: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::DictionaryBatch *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case MessageHeader::RecordBatch: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::RecordBatch *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case MessageHeader::Tensor: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Tensor *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case MessageHeader::SparseTensor: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::SparseTensor *>(obj);
- return verifier.VerifyTable(ptr);
- }
- default: return true;
- }
-}
-
-inline bool VerifyMessageHeaderVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
- if (!values || !types) return !values && !types;
- if (values->size() != types->size()) return false;
- for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
- if (!VerifyMessageHeader(
- verifier, values->Get(i), types->GetEnum<MessageHeader>(i))) {
- return false;
- }
- }
- return true;
-}
-
-inline const org::apache::arrow::flatbuf::Message *GetMessage(const void *buf) {
- return flatbuffers::GetRoot<org::apache::arrow::flatbuf::Message>(buf);
-}
-
-inline const org::apache::arrow::flatbuf::Message *GetSizePrefixedMessage(const void *buf) {
- return flatbuffers::GetSizePrefixedRoot<org::apache::arrow::flatbuf::Message>(buf);
-}
-
-inline bool VerifyMessageBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifyBuffer<org::apache::arrow::flatbuf::Message>(nullptr);
-}
-
-inline bool VerifySizePrefixedMessageBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifySizePrefixedBuffer<org::apache::arrow::flatbuf::Message>(nullptr);
-}
-
-inline void FinishMessageBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Message> root) {
- fbb.Finish(root);
-}
-
-inline void FinishSizePrefixedMessageBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Message> root) {
- fbb.FinishSizePrefixed(root);
-}
-
-} // namespace flatbuf
-} // namespace arrow
-} // namespace apache
-} // namespace org
-
-#endif // FLATBUFFERS_GENERATED_MESSAGE_ORG_APACHE_ARROW_FLATBUF_H_
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs b/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs
new file mode 100644
index 0000000000..e19e8bac28
--- /dev/null
+++ b/contrib/libs/apache/arrow/cpp/src/generated/Schema.fbs
@@ -0,0 +1,430 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.
+
+/// Logical types, vector layouts, and schemas
+
+namespace org.apache.arrow.flatbuf;
+
+enum MetadataVersion:short {
+ /// 0.1.0 (October 2016).
+ V1,
+
+ /// 0.2.0 (February 2017). Non-backwards compatible with V1.
+ V2,
+
+ /// 0.3.0 -> 0.7.1 (May - December 2017). Non-backwards compatible with V2.
+ V3,
+
+ /// >= 0.8.0 (December 2017). Non-backwards compatible with V3.
+ V4,
+
+ /// >= 1.0.0 (July 2020. Backwards compatible with V4 (V5 readers can read V4
+ /// metadata and IPC messages). Implementations are recommended to provide a
+ /// V4 compatibility mode with V5 format changes disabled.
+ ///
+ /// Incompatible changes between V4 and V5:
+ /// - Union buffer layout has changed. In V5, Unions don't have a validity
+ /// bitmap buffer.
+ V5,
+}
+
+/// Represents Arrow Features that might not have full support
+/// within implementations. This is intended to be used in
+/// two scenarios:
+/// 1. A mechanism for readers of Arrow Streams
+/// and files to understand that the stream or file makes
+/// use of a feature that isn't supported or unknown to
+/// the implementation (and therefore can meet the Arrow
+/// forward compatibility guarantees).
+/// 2. A means of negotiating between a client and server
+/// what features a stream is allowed to use. The enums
+/// values here are intented to represent higher level
+/// features, additional details maybe negotiated
+/// with key-value pairs specific to the protocol.
+///
+/// Enums added to this list should be assigned power-of-two values
+/// to facilitate exchanging and comparing bitmaps for supported
+/// features.
+enum Feature : long {
+ /// Needed to make flatbuffers happy.
+ UNUSED = 0,
+ /// The stream makes use of multiple full dictionaries with the
+ /// same ID and assumes clients implement dictionary replacement
+ /// correctly.
+ DICTIONARY_REPLACEMENT = 1,
+ /// The stream makes use of compressed bodies as described
+ /// in Message.fbs.
+ COMPRESSED_BODY = 2
+}
+
+/// These are stored in the flatbuffer in the Type union below
+
+table Null {
+}
+
+/// A Struct_ in the flatbuffer metadata is the same as an Arrow Struct
+/// (according to the physical memory layout). We used Struct_ here as
+/// Struct is a reserved word in Flatbuffers
+table Struct_ {
+}
+
+table List {
+}
+
+/// Same as List, but with 64-bit offsets, allowing to represent
+/// extremely large data values.
+table LargeList {
+}
+
+table FixedSizeList {
+ /// Number of list items per value
+ listSize: int;
+}
+
+/// A Map is a logical nested type that is represented as
+///
+/// List<entries: Struct<key: K, value: V>>
+///
+/// In this layout, the keys and values are each respectively contiguous. We do
+/// not constrain the key and value types, so the application is responsible
+/// for ensuring that the keys are hashable and unique. Whether the keys are sorted
+/// may be set in the metadata for this field.
+///
+/// In a field with Map type, the field has a child Struct field, which then
+/// has two children: key type and the second the value type. The names of the
+/// child fields may be respectively "entries", "key", and "value", but this is
+/// not enforced.
+///
+/// Map
+/// ```text
+/// - child[0] entries: Struct
+/// - child[0] key: K
+/// - child[1] value: V
+/// ```
+/// Neither the "entries" field nor the "key" field may be nullable.
+///
+/// The metadata is structured so that Arrow systems without special handling
+/// for Map can make Map an alias for List. The "layout" attribute for the Map
+/// field must have the same contents as a List.
+table Map {
+ /// Set to true if the keys within each value are sorted
+ keysSorted: bool;
+}
+
+enum UnionMode:short { Sparse, Dense }
+
+/// A union is a complex type with children in Field
+/// By default ids in the type vector refer to the offsets in the children
+/// optionally typeIds provides an indirection between the child offset and the type id
+/// for each child `typeIds[offset]` is the id used in the type vector
+table Union {
+ mode: UnionMode;
+ typeIds: [ int ]; // optional, describes typeid of each child.
+}
+
+table Int {
+ bitWidth: int; // restricted to 8, 16, 32, and 64 in v1
+ is_signed: bool;
+}
+
+enum Precision:short {HALF, SINGLE, DOUBLE}
+
+table FloatingPoint {
+ precision: Precision;
+}
+
+/// Unicode with UTF-8 encoding
+table Utf8 {
+}
+
+/// Opaque binary data
+table Binary {
+}
+
+/// Same as Utf8, but with 64-bit offsets, allowing to represent
+/// extremely large data values.
+table LargeUtf8 {
+}
+
+/// Same as Binary, but with 64-bit offsets, allowing to represent
+/// extremely large data values.
+table LargeBinary {
+}
+
+table FixedSizeBinary {
+ /// Number of bytes per value
+ byteWidth: int;
+}
+
+table Bool {
+}
+
+/// Exact decimal value represented as an integer value in two's
+/// complement. Currently only 128-bit (16-byte) and 256-bit (32-byte) integers
+/// are used. The representation uses the endianness indicated
+/// in the Schema.
+table Decimal {
+ /// Total number of decimal digits
+ precision: int;
+
+ /// Number of digits after the decimal point "."
+ scale: int;
+
+ /// Number of bits per value. The only accepted widths are 128 and 256.
+ /// We use bitWidth for consistency with Int::bitWidth.
+ bitWidth: int = 128;
+}
+
+enum DateUnit: short {
+ DAY,
+ MILLISECOND
+}
+
+/// Date is either a 32-bit or 64-bit type representing elapsed time since UNIX
+/// epoch (1970-01-01), stored in either of two units:
+///
+/// * Milliseconds (64 bits) indicating UNIX time elapsed since the epoch (no
+/// leap seconds), where the values are evenly divisible by 86400000
+/// * Days (32 bits) since the UNIX epoch
+table Date {
+ unit: DateUnit = MILLISECOND;
+}
+
+enum TimeUnit: short { SECOND, MILLISECOND, MICROSECOND, NANOSECOND }
+
+/// Time type. The physical storage type depends on the unit
+/// - SECOND and MILLISECOND: 32 bits
+/// - MICROSECOND and NANOSECOND: 64 bits
+table Time {
+ unit: TimeUnit = MILLISECOND;
+ bitWidth: int = 32;
+}
+
+/// Time elapsed from the Unix epoch, 00:00:00.000 on 1 January 1970, excluding
+/// leap seconds, as a 64-bit integer. Note that UNIX time does not include
+/// leap seconds.
+///
+/// Date & time libraries often have multiple different data types for temporal
+/// data. In order to ease interoperability between different implementations the
+/// Arrow project has some recommendations for encoding these types into a Timestamp
+/// column.
+///
+/// An "instant" represents a single moment in time that has no meaningful time zone
+/// or the time zone is unknown. A column of instants can also contain values from
+/// multiple time zones. To encode an instant set the timezone string to "UTC".
+///
+/// A "zoned date-time" represents a single moment in time that has a meaningful
+/// reference time zone. To encode a zoned date-time as a Timestamp set the timezone
+/// string to the name of the timezone. There is some ambiguity between an instant
+/// and a zoned date-time with the UTC time zone. Both of these are stored the same.
+/// Typically, this distinction does not matter. If it does, then an application should
+/// use custom metadata or an extension type to distinguish between the two cases.
+///
+/// An "offset date-time" represents a single moment in time combined with a meaningful
+/// offset from UTC. To encode an offset date-time as a Timestamp set the timezone string
+/// to the numeric time zone offset string (e.g. "+03:00").
+///
+/// A "local date-time" does not represent a single moment in time. It represents a wall
+/// clock time combined with a date. Because of daylight savings time there may multiple
+/// instants that correspond to a single local date-time in any given time zone. A
+/// local date-time is often stored as a struct or a Date32/Time64 pair. However, it can
+/// also be encoded into a Timestamp column. To do so the value should be the the time
+/// elapsed from the Unix epoch so that a wall clock in UTC would display the desired time.
+/// The timezone string should be set to null or the empty string.
+table Timestamp {
+ unit: TimeUnit;
+
+ /// The time zone is a string indicating the name of a time zone, one of:
+ ///
+ /// * As used in the Olson time zone database (the "tz database" or
+ /// "tzdata"), such as "America/New_York"
+ /// * An absolute time zone offset of the form +XX:XX or -XX:XX, such as +07:30
+ ///
+ /// Whether a timezone string is present indicates different semantics about
+ /// the data:
+ ///
+ /// * If the time zone is null or an empty string, the data is a local date-time
+ /// and does not represent a single moment in time. Instead it represents a wall clock
+ /// time and care should be taken to avoid interpreting it semantically as an instant.
+ ///
+ /// * If the time zone is set to a valid value, values can be displayed as
+ /// "localized" to that time zone, even though the underlying 64-bit
+ /// integers are identical to the same data stored in UTC. Converting
+ /// between time zones is a metadata-only operation and does not change the
+ /// underlying values
+ time_zone: string;
+}
+
+enum IntervalUnit: short { YEAR_MONTH, DAY_TIME}
+// A "calendar" interval which models types that don't necessarily
+// have a precise duration without the context of a base timestamp (e.g.
+// days can differ in length during day light savings time transitions).
+// YEAR_MONTH - Indicates the number of elapsed whole months, stored as
+// 4-byte integers.
+// DAY_TIME - Indicates the number of elapsed days and milliseconds,
+// stored as 2 contiguous 32-bit integers (8-bytes in total). Support
+// of this IntervalUnit is not required for full arrow compatibility.
+table Interval {
+ unit: IntervalUnit;
+}
+
+// An absolute length of time unrelated to any calendar artifacts.
+//
+// For the purposes of Arrow Implementations, adding this value to a Timestamp
+// ("t1") naively (i.e. simply summing the two number) is acceptable even
+// though in some cases the resulting Timestamp (t2) would not account for
+// leap-seconds during the elapsed time between "t1" and "t2". Similarly,
+// representing the difference between two Unix timestamp is acceptable, but
+// would yield a value that is possibly a few seconds off from the true elapsed
+// time.
+//
+// The resolution defaults to millisecond, but can be any of the other
+// supported TimeUnit values as with Timestamp and Time types. This type is
+// always represented as an 8-byte integer.
+table Duration {
+ unit: TimeUnit = MILLISECOND;
+}
+
+/// ----------------------------------------------------------------------
+/// Top-level Type value, enabling extensible type-specific metadata. We can
+/// add new logical types to Type without breaking backwards compatibility
+
+union Type {
+ Null,
+ Int,
+ FloatingPoint,
+ Binary,
+ Utf8,
+ Bool,
+ Decimal,
+ Date,
+ Time,
+ Timestamp,
+ Interval,
+ List,
+ Struct_,
+ Union,
+ FixedSizeBinary,
+ FixedSizeList,
+ Map,
+ Duration,
+ LargeBinary,
+ LargeUtf8,
+ LargeList,
+}
+
+/// ----------------------------------------------------------------------
+/// user defined key value pairs to add custom metadata to arrow
+/// key namespacing is the responsibility of the user
+
+table KeyValue {
+ key: string;
+ value: string;
+}
+
+/// ----------------------------------------------------------------------
+/// Dictionary encoding metadata
+/// Maintained for forwards compatibility, in the future
+/// Dictionaries might be explicit maps between integers and values
+/// allowing for non-contiguous index values
+enum DictionaryKind : short { DenseArray }
+table DictionaryEncoding {
+ /// The known dictionary id in the application where this data is used. In
+ /// the file or streaming formats, the dictionary ids are found in the
+ /// DictionaryBatch messages
+ id: long;
+
+ /// The dictionary indices are constrained to be non-negative integers. If
+ /// this field is null, the indices must be signed int32. To maximize
+ /// cross-language compatibility and performance, implementations are
+ /// recommended to prefer signed integer types over unsigned integer types
+ /// and to avoid uint64 indices unless they are required by an application.
+ indexType: Int;
+
+ /// By default, dictionaries are not ordered, or the order does not have
+ /// semantic meaning. In some statistical, applications, dictionary-encoding
+ /// is used to represent ordered categorical data, and we provide a way to
+ /// preserve that metadata here
+ isOrdered: bool;
+
+ dictionaryKind: DictionaryKind;
+}
+
+/// ----------------------------------------------------------------------
+/// A field represents a named column in a record / row batch or child of a
+/// nested type.
+
+table Field {
+ /// Name is not required, in i.e. a List
+ name: string;
+
+ /// Whether or not this field can contain nulls. Should be true in general.
+ nullable: bool;
+
+ /// This is the type of the decoded value if the field is dictionary encoded.
+ type: Type;
+
+ /// Present only if the field is dictionary encoded.
+ dictionary: DictionaryEncoding;
+
+ /// children apply only to nested data types like Struct, List and Union. For
+ /// primitive types children will have length 0.
+ children: [ Field ];
+
+ /// User-defined metadata
+ custom_metadata: [ KeyValue ];
+}
+
+/// ----------------------------------------------------------------------
+/// Endianness of the platform producing the data
+
+enum Endianness:short { Little, Big }
+
+/// ----------------------------------------------------------------------
+/// A Buffer represents a single contiguous memory segment
+struct Buffer {
+ /// The relative offset into the shared memory page where the bytes for this
+ /// buffer starts
+ offset: long;
+
+ /// The absolute length (in bytes) of the memory buffer. The memory is found
+ /// from offset (inclusive) to offset + length (non-inclusive). When building
+ /// messages using the encapsulated IPC message, padding bytes may be written
+ /// after a buffer, but such padding bytes do not need to be accounted for in
+ /// the size here.
+ length: long;
+}
+
+/// ----------------------------------------------------------------------
+/// A Schema describes the columns in a row batch
+
+table Schema {
+
+ /// endianness of the buffer
+ /// it is Little Endian by default
+ /// if endianness doesn't match the underlying system then the vectors need to be converted
+ endianness: Endianness=Little;
+
+ fields: [Field];
+ // User-defined metadata
+ custom_metadata: [ KeyValue ];
+
+ /// Features used in the stream/file.
+ features : [ Feature ];
+}
+
+root_type Schema;
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/Schema_generated.h b/contrib/libs/apache/arrow/cpp/src/generated/Schema_generated.h
deleted file mode 100644
index 91e01d3375..0000000000
--- a/contrib/libs/apache/arrow/cpp/src/generated/Schema_generated.h
+++ /dev/null
@@ -1,2265 +0,0 @@
-// automatically generated by the FlatBuffers compiler, do not modify
-
-
-#ifndef FLATBUFFERS_GENERATED_SCHEMA_ORG_APACHE_ARROW_FLATBUF_H_
-#define FLATBUFFERS_GENERATED_SCHEMA_ORG_APACHE_ARROW_FLATBUF_H_
-
-#include "flatbuffers/flatbuffers.h"
-
-namespace org {
-namespace apache {
-namespace arrow {
-namespace flatbuf {
-
-struct Null;
-struct NullBuilder;
-
-struct Struct_;
-struct Struct_Builder;
-
-struct List;
-struct ListBuilder;
-
-struct LargeList;
-struct LargeListBuilder;
-
-struct FixedSizeList;
-struct FixedSizeListBuilder;
-
-struct Map;
-struct MapBuilder;
-
-struct Union;
-struct UnionBuilder;
-
-struct Int;
-struct IntBuilder;
-
-struct FloatingPoint;
-struct FloatingPointBuilder;
-
-struct Utf8;
-struct Utf8Builder;
-
-struct Binary;
-struct BinaryBuilder;
-
-struct LargeUtf8;
-struct LargeUtf8Builder;
-
-struct LargeBinary;
-struct LargeBinaryBuilder;
-
-struct FixedSizeBinary;
-struct FixedSizeBinaryBuilder;
-
-struct Bool;
-struct BoolBuilder;
-
-struct Decimal;
-struct DecimalBuilder;
-
-struct Date;
-struct DateBuilder;
-
-struct Time;
-struct TimeBuilder;
-
-struct Timestamp;
-struct TimestampBuilder;
-
-struct Interval;
-struct IntervalBuilder;
-
-struct Duration;
-struct DurationBuilder;
-
-struct KeyValue;
-struct KeyValueBuilder;
-
-struct DictionaryEncoding;
-struct DictionaryEncodingBuilder;
-
-struct Field;
-struct FieldBuilder;
-
-struct Buffer;
-
-struct Schema;
-struct SchemaBuilder;
-
-enum class MetadataVersion : int16_t {
- /// 0.1.0 (October 2016).
- V1 = 0,
- /// 0.2.0 (February 2017). Non-backwards compatible with V1.
- V2 = 1,
- /// 0.3.0 -> 0.7.1 (May - December 2017). Non-backwards compatible with V2.
- V3 = 2,
- /// >= 0.8.0 (December 2017). Non-backwards compatible with V3.
- V4 = 3,
- /// >= 1.0.0 (July 2020. Backwards compatible with V4 (V5 readers can read V4
- /// metadata and IPC messages). Implementations are recommended to provide a
- /// V4 compatibility mode with V5 format changes disabled.
- ///
- /// Incompatible changes between V4 and V5:
- /// - Union buffer layout has changed. In V5, Unions don't have a validity
- /// bitmap buffer.
- V5 = 4,
- MIN = V1,
- MAX = V5
-};
-
-inline const MetadataVersion (&EnumValuesMetadataVersion())[5] {
- static const MetadataVersion values[] = {
- MetadataVersion::V1,
- MetadataVersion::V2,
- MetadataVersion::V3,
- MetadataVersion::V4,
- MetadataVersion::V5
- };
- return values;
-}
-
-inline const char * const *EnumNamesMetadataVersion() {
- static const char * const names[6] = {
- "V1",
- "V2",
- "V3",
- "V4",
- "V5",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameMetadataVersion(MetadataVersion e) {
- if (flatbuffers::IsOutRange(e, MetadataVersion::V1, MetadataVersion::V5)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesMetadataVersion()[index];
-}
-
-/// Represents Arrow Features that might not have full support
-/// within implementations. This is intended to be used in
-/// two scenarios:
-/// 1. A mechanism for readers of Arrow Streams
-/// and files to understand that the stream or file makes
-/// use of a feature that isn't supported or unknown to
-/// the implementation (and therefore can meet the Arrow
-/// forward compatibility guarantees).
-/// 2. A means of negotiating between a client and server
-/// what features a stream is allowed to use. The enums
-/// values here are intented to represent higher level
-/// features, additional details maybe negotiated
-/// with key-value pairs specific to the protocol.
-///
-/// Enums added to this list should be assigned power-of-two values
-/// to facilitate exchanging and comparing bitmaps for supported
-/// features.
-enum class Feature : int64_t {
- /// Needed to make flatbuffers happy.
- UNUSED = 0,
- /// The stream makes use of multiple full dictionaries with the
- /// same ID and assumes clients implement dictionary replacement
- /// correctly.
- DICTIONARY_REPLACEMENT = 1LL,
- /// The stream makes use of compressed bodies as described
- /// in Message.fbs.
- COMPRESSED_BODY = 2LL,
- MIN = UNUSED,
- MAX = COMPRESSED_BODY
-};
-
-inline const Feature (&EnumValuesFeature())[3] {
- static const Feature values[] = {
- Feature::UNUSED,
- Feature::DICTIONARY_REPLACEMENT,
- Feature::COMPRESSED_BODY
- };
- return values;
-}
-
-inline const char * const *EnumNamesFeature() {
- static const char * const names[4] = {
- "UNUSED",
- "DICTIONARY_REPLACEMENT",
- "COMPRESSED_BODY",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameFeature(Feature e) {
- if (flatbuffers::IsOutRange(e, Feature::UNUSED, Feature::COMPRESSED_BODY)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesFeature()[index];
-}
-
-enum class UnionMode : int16_t {
- Sparse = 0,
- Dense = 1,
- MIN = Sparse,
- MAX = Dense
-};
-
-inline const UnionMode (&EnumValuesUnionMode())[2] {
- static const UnionMode values[] = {
- UnionMode::Sparse,
- UnionMode::Dense
- };
- return values;
-}
-
-inline const char * const *EnumNamesUnionMode() {
- static const char * const names[3] = {
- "Sparse",
- "Dense",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameUnionMode(UnionMode e) {
- if (flatbuffers::IsOutRange(e, UnionMode::Sparse, UnionMode::Dense)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesUnionMode()[index];
-}
-
-enum class Precision : int16_t {
- HALF = 0,
- SINGLE = 1,
- DOUBLE = 2,
- MIN = HALF,
- MAX = DOUBLE
-};
-
-inline const Precision (&EnumValuesPrecision())[3] {
- static const Precision values[] = {
- Precision::HALF,
- Precision::SINGLE,
- Precision::DOUBLE
- };
- return values;
-}
-
-inline const char * const *EnumNamesPrecision() {
- static const char * const names[4] = {
- "HALF",
- "SINGLE",
- "DOUBLE",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNamePrecision(Precision e) {
- if (flatbuffers::IsOutRange(e, Precision::HALF, Precision::DOUBLE)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesPrecision()[index];
-}
-
-enum class DateUnit : int16_t {
- DAY = 0,
- MILLISECOND = 1,
- MIN = DAY,
- MAX = MILLISECOND
-};
-
-inline const DateUnit (&EnumValuesDateUnit())[2] {
- static const DateUnit values[] = {
- DateUnit::DAY,
- DateUnit::MILLISECOND
- };
- return values;
-}
-
-inline const char * const *EnumNamesDateUnit() {
- static const char * const names[3] = {
- "DAY",
- "MILLISECOND",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameDateUnit(DateUnit e) {
- if (flatbuffers::IsOutRange(e, DateUnit::DAY, DateUnit::MILLISECOND)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesDateUnit()[index];
-}
-
-enum class TimeUnit : int16_t {
- SECOND = 0,
- MILLISECOND = 1,
- MICROSECOND = 2,
- NANOSECOND = 3,
- MIN = SECOND,
- MAX = NANOSECOND
-};
-
-inline const TimeUnit (&EnumValuesTimeUnit())[4] {
- static const TimeUnit values[] = {
- TimeUnit::SECOND,
- TimeUnit::MILLISECOND,
- TimeUnit::MICROSECOND,
- TimeUnit::NANOSECOND
- };
- return values;
-}
-
-inline const char * const *EnumNamesTimeUnit() {
- static const char * const names[5] = {
- "SECOND",
- "MILLISECOND",
- "MICROSECOND",
- "NANOSECOND",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameTimeUnit(TimeUnit e) {
- if (flatbuffers::IsOutRange(e, TimeUnit::SECOND, TimeUnit::NANOSECOND)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesTimeUnit()[index];
-}
-
-enum class IntervalUnit : int16_t {
- YEAR_MONTH = 0,
- DAY_TIME = 1,
- MIN = YEAR_MONTH,
- MAX = DAY_TIME
-};
-
-inline const IntervalUnit (&EnumValuesIntervalUnit())[2] {
- static const IntervalUnit values[] = {
- IntervalUnit::YEAR_MONTH,
- IntervalUnit::DAY_TIME
- };
- return values;
-}
-
-inline const char * const *EnumNamesIntervalUnit() {
- static const char * const names[3] = {
- "YEAR_MONTH",
- "DAY_TIME",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameIntervalUnit(IntervalUnit e) {
- if (flatbuffers::IsOutRange(e, IntervalUnit::YEAR_MONTH, IntervalUnit::DAY_TIME)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesIntervalUnit()[index];
-}
-
-/// ----------------------------------------------------------------------
-/// Top-level Type value, enabling extensible type-specific metadata. We can
-/// add new logical types to Type without breaking backwards compatibility
-enum class Type : uint8_t {
- NONE = 0,
- Null = 1,
- Int = 2,
- FloatingPoint = 3,
- Binary = 4,
- Utf8 = 5,
- Bool = 6,
- Decimal = 7,
- Date = 8,
- Time = 9,
- Timestamp = 10,
- Interval = 11,
- List = 12,
- Struct_ = 13,
- Union = 14,
- FixedSizeBinary = 15,
- FixedSizeList = 16,
- Map = 17,
- Duration = 18,
- LargeBinary = 19,
- LargeUtf8 = 20,
- LargeList = 21,
- MIN = NONE,
- MAX = LargeList
-};
-
-inline const Type (&EnumValuesType())[22] {
- static const Type values[] = {
- Type::NONE,
- Type::Null,
- Type::Int,
- Type::FloatingPoint,
- Type::Binary,
- Type::Utf8,
- Type::Bool,
- Type::Decimal,
- Type::Date,
- Type::Time,
- Type::Timestamp,
- Type::Interval,
- Type::List,
- Type::Struct_,
- Type::Union,
- Type::FixedSizeBinary,
- Type::FixedSizeList,
- Type::Map,
- Type::Duration,
- Type::LargeBinary,
- Type::LargeUtf8,
- Type::LargeList
- };
- return values;
-}
-
-inline const char * const *EnumNamesType() {
- static const char * const names[23] = {
- "NONE",
- "Null",
- "Int",
- "FloatingPoint",
- "Binary",
- "Utf8",
- "Bool",
- "Decimal",
- "Date",
- "Time",
- "Timestamp",
- "Interval",
- "List",
- "Struct_",
- "Union",
- "FixedSizeBinary",
- "FixedSizeList",
- "Map",
- "Duration",
- "LargeBinary",
- "LargeUtf8",
- "LargeList",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameType(Type e) {
- if (flatbuffers::IsOutRange(e, Type::NONE, Type::LargeList)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesType()[index];
-}
-
-template<typename T> struct TypeTraits {
- static const Type enum_value = Type::NONE;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Null> {
- static const Type enum_value = Type::Null;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Int> {
- static const Type enum_value = Type::Int;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::FloatingPoint> {
- static const Type enum_value = Type::FloatingPoint;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Binary> {
- static const Type enum_value = Type::Binary;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Utf8> {
- static const Type enum_value = Type::Utf8;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Bool> {
- static const Type enum_value = Type::Bool;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Decimal> {
- static const Type enum_value = Type::Decimal;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Date> {
- static const Type enum_value = Type::Date;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Time> {
- static const Type enum_value = Type::Time;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Timestamp> {
- static const Type enum_value = Type::Timestamp;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Interval> {
- static const Type enum_value = Type::Interval;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::List> {
- static const Type enum_value = Type::List;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Struct_> {
- static const Type enum_value = Type::Struct_;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Union> {
- static const Type enum_value = Type::Union;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::FixedSizeBinary> {
- static const Type enum_value = Type::FixedSizeBinary;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::FixedSizeList> {
- static const Type enum_value = Type::FixedSizeList;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Map> {
- static const Type enum_value = Type::Map;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::Duration> {
- static const Type enum_value = Type::Duration;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::LargeBinary> {
- static const Type enum_value = Type::LargeBinary;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::LargeUtf8> {
- static const Type enum_value = Type::LargeUtf8;
-};
-
-template<> struct TypeTraits<org::apache::arrow::flatbuf::LargeList> {
- static const Type enum_value = Type::LargeList;
-};
-
-bool VerifyType(flatbuffers::Verifier &verifier, const void *obj, Type type);
-bool VerifyTypeVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
-
-/// ----------------------------------------------------------------------
-/// Dictionary encoding metadata
-/// Maintained for forwards compatibility, in the future
-/// Dictionaries might be explicit maps between integers and values
-/// allowing for non-contiguous index values
-enum class DictionaryKind : int16_t {
- DenseArray = 0,
- MIN = DenseArray,
- MAX = DenseArray
-};
-
-inline const DictionaryKind (&EnumValuesDictionaryKind())[1] {
- static const DictionaryKind values[] = {
- DictionaryKind::DenseArray
- };
- return values;
-}
-
-inline const char * const *EnumNamesDictionaryKind() {
- static const char * const names[2] = {
- "DenseArray",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameDictionaryKind(DictionaryKind e) {
- if (flatbuffers::IsOutRange(e, DictionaryKind::DenseArray, DictionaryKind::DenseArray)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesDictionaryKind()[index];
-}
-
-/// ----------------------------------------------------------------------
-/// Endianness of the platform producing the data
-enum class Endianness : int16_t {
- Little = 0,
- Big = 1,
- MIN = Little,
- MAX = Big
-};
-
-inline const Endianness (&EnumValuesEndianness())[2] {
- static const Endianness values[] = {
- Endianness::Little,
- Endianness::Big
- };
- return values;
-}
-
-inline const char * const *EnumNamesEndianness() {
- static const char * const names[3] = {
- "Little",
- "Big",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameEndianness(Endianness e) {
- if (flatbuffers::IsOutRange(e, Endianness::Little, Endianness::Big)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesEndianness()[index];
-}
-
-/// ----------------------------------------------------------------------
-/// A Buffer represents a single contiguous memory segment
-FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Buffer FLATBUFFERS_FINAL_CLASS {
- private:
- int64_t offset_;
- int64_t length_;
-
- public:
- Buffer() {
- memset(static_cast<void *>(this), 0, sizeof(Buffer));
- }
- Buffer(int64_t _offset, int64_t _length)
- : offset_(flatbuffers::EndianScalar(_offset)),
- length_(flatbuffers::EndianScalar(_length)) {
- }
- /// The relative offset into the shared memory page where the bytes for this
- /// buffer starts
- int64_t offset() const {
- return flatbuffers::EndianScalar(offset_);
- }
- /// The absolute length (in bytes) of the memory buffer. The memory is found
- /// from offset (inclusive) to offset + length (non-inclusive). When building
- /// messages using the encapsulated IPC message, padding bytes may be written
- /// after a buffer, but such padding bytes do not need to be accounted for in
- /// the size here.
- int64_t length() const {
- return flatbuffers::EndianScalar(length_);
- }
-};
-FLATBUFFERS_STRUCT_END(Buffer, 16);
-
-/// These are stored in the flatbuffer in the Type union below
-struct Null FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef NullBuilder Builder;
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- verifier.EndTable();
- }
-};
-
-struct NullBuilder {
- typedef Null Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- explicit NullBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- NullBuilder &operator=(const NullBuilder &);
- flatbuffers::Offset<Null> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Null>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Null> CreateNull(
- flatbuffers::FlatBufferBuilder &_fbb) {
- NullBuilder builder_(_fbb);
- return builder_.Finish();
-}
-
-/// A Struct_ in the flatbuffer metadata is the same as an Arrow Struct
-/// (according to the physical memory layout). We used Struct_ here as
-/// Struct is a reserved word in Flatbuffers
-struct Struct_ FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef Struct_Builder Builder;
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- verifier.EndTable();
- }
-};
-
-struct Struct_Builder {
- typedef Struct_ Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- explicit Struct_Builder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- Struct_Builder &operator=(const Struct_Builder &);
- flatbuffers::Offset<Struct_> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Struct_>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Struct_> CreateStruct_(
- flatbuffers::FlatBufferBuilder &_fbb) {
- Struct_Builder builder_(_fbb);
- return builder_.Finish();
-}
-
-struct List FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef ListBuilder Builder;
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- verifier.EndTable();
- }
-};
-
-struct ListBuilder {
- typedef List Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- explicit ListBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- ListBuilder &operator=(const ListBuilder &);
- flatbuffers::Offset<List> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<List>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<List> CreateList(
- flatbuffers::FlatBufferBuilder &_fbb) {
- ListBuilder builder_(_fbb);
- return builder_.Finish();
-}
-
-/// Same as List, but with 64-bit offsets, allowing to represent
-/// extremely large data values.
-struct LargeList FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef LargeListBuilder Builder;
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- verifier.EndTable();
- }
-};
-
-struct LargeListBuilder {
- typedef LargeList Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- explicit LargeListBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- LargeListBuilder &operator=(const LargeListBuilder &);
- flatbuffers::Offset<LargeList> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<LargeList>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<LargeList> CreateLargeList(
- flatbuffers::FlatBufferBuilder &_fbb) {
- LargeListBuilder builder_(_fbb);
- return builder_.Finish();
-}
-
-struct FixedSizeList FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef FixedSizeListBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_LISTSIZE = 4
- };
- /// Number of list items per value
- int32_t listSize() const {
- return GetField<int32_t>(VT_LISTSIZE, 0);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int32_t>(verifier, VT_LISTSIZE) &&
- verifier.EndTable();
- }
-};
-
-struct FixedSizeListBuilder {
- typedef FixedSizeList Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_listSize(int32_t listSize) {
- fbb_.AddElement<int32_t>(FixedSizeList::VT_LISTSIZE, listSize, 0);
- }
- explicit FixedSizeListBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- FixedSizeListBuilder &operator=(const FixedSizeListBuilder &);
- flatbuffers::Offset<FixedSizeList> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<FixedSizeList>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<FixedSizeList> CreateFixedSizeList(
- flatbuffers::FlatBufferBuilder &_fbb,
- int32_t listSize = 0) {
- FixedSizeListBuilder builder_(_fbb);
- builder_.add_listSize(listSize);
- return builder_.Finish();
-}
-
-/// A Map is a logical nested type that is represented as
-///
-/// List<entries: Struct<key: K, value: V>>
-///
-/// In this layout, the keys and values are each respectively contiguous. We do
-/// not constrain the key and value types, so the application is responsible
-/// for ensuring that the keys are hashable and unique. Whether the keys are sorted
-/// may be set in the metadata for this field.
-///
-/// In a field with Map type, the field has a child Struct field, which then
-/// has two children: key type and the second the value type. The names of the
-/// child fields may be respectively "entries", "key", and "value", but this is
-/// not enforced.
-///
-/// Map
-/// - child[0] entries: Struct
-/// - child[0] key: K
-/// - child[1] value: V
-///
-/// Neither the "entries" field nor the "key" field may be nullable.
-///
-/// The metadata is structured so that Arrow systems without special handling
-/// for Map can make Map an alias for List. The "layout" attribute for the Map
-/// field must have the same contents as a List.
-struct Map FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef MapBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_KEYSSORTED = 4
- };
- /// Set to true if the keys within each value are sorted
- bool keysSorted() const {
- return GetField<uint8_t>(VT_KEYSSORTED, 0) != 0;
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<uint8_t>(verifier, VT_KEYSSORTED) &&
- verifier.EndTable();
- }
-};
-
-struct MapBuilder {
- typedef Map Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_keysSorted(bool keysSorted) {
- fbb_.AddElement<uint8_t>(Map::VT_KEYSSORTED, static_cast<uint8_t>(keysSorted), 0);
- }
- explicit MapBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- MapBuilder &operator=(const MapBuilder &);
- flatbuffers::Offset<Map> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Map>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Map> CreateMap(
- flatbuffers::FlatBufferBuilder &_fbb,
- bool keysSorted = false) {
- MapBuilder builder_(_fbb);
- builder_.add_keysSorted(keysSorted);
- return builder_.Finish();
-}
-
-/// A union is a complex type with children in Field
-/// By default ids in the type vector refer to the offsets in the children
-/// optionally typeIds provides an indirection between the child offset and the type id
-/// for each child typeIds[offset] is the id used in the type vector
-struct Union FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef UnionBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_MODE = 4,
- VT_TYPEIDS = 6
- };
- org::apache::arrow::flatbuf::UnionMode mode() const {
- return static_cast<org::apache::arrow::flatbuf::UnionMode>(GetField<int16_t>(VT_MODE, 0));
- }
- const flatbuffers::Vector<int32_t> *typeIds() const {
- return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_TYPEIDS);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_MODE) &&
- VerifyOffset(verifier, VT_TYPEIDS) &&
- verifier.VerifyVector(typeIds()) &&
- verifier.EndTable();
- }
-};
-
-struct UnionBuilder {
- typedef Union Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_mode(org::apache::arrow::flatbuf::UnionMode mode) {
- fbb_.AddElement<int16_t>(Union::VT_MODE, static_cast<int16_t>(mode), 0);
- }
- void add_typeIds(flatbuffers::Offset<flatbuffers::Vector<int32_t>> typeIds) {
- fbb_.AddOffset(Union::VT_TYPEIDS, typeIds);
- }
- explicit UnionBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- UnionBuilder &operator=(const UnionBuilder &);
- flatbuffers::Offset<Union> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Union>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Union> CreateUnion(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::UnionMode mode = org::apache::arrow::flatbuf::UnionMode::Sparse,
- flatbuffers::Offset<flatbuffers::Vector<int32_t>> typeIds = 0) {
- UnionBuilder builder_(_fbb);
- builder_.add_typeIds(typeIds);
- builder_.add_mode(mode);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<Union> CreateUnionDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::UnionMode mode = org::apache::arrow::flatbuf::UnionMode::Sparse,
- const std::vector<int32_t> *typeIds = nullptr) {
- auto typeIds__ = typeIds ? _fbb.CreateVector<int32_t>(*typeIds) : 0;
- return org::apache::arrow::flatbuf::CreateUnion(
- _fbb,
- mode,
- typeIds__);
-}
-
-struct Int FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef IntBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_BITWIDTH = 4,
- VT_IS_SIGNED = 6
- };
- int32_t bitWidth() const {
- return GetField<int32_t>(VT_BITWIDTH, 0);
- }
- bool is_signed() const {
- return GetField<uint8_t>(VT_IS_SIGNED, 0) != 0;
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int32_t>(verifier, VT_BITWIDTH) &&
- VerifyField<uint8_t>(verifier, VT_IS_SIGNED) &&
- verifier.EndTable();
- }
-};
-
-struct IntBuilder {
- typedef Int Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_bitWidth(int32_t bitWidth) {
- fbb_.AddElement<int32_t>(Int::VT_BITWIDTH, bitWidth, 0);
- }
- void add_is_signed(bool is_signed) {
- fbb_.AddElement<uint8_t>(Int::VT_IS_SIGNED, static_cast<uint8_t>(is_signed), 0);
- }
- explicit IntBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- IntBuilder &operator=(const IntBuilder &);
- flatbuffers::Offset<Int> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Int>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Int> CreateInt(
- flatbuffers::FlatBufferBuilder &_fbb,
- int32_t bitWidth = 0,
- bool is_signed = false) {
- IntBuilder builder_(_fbb);
- builder_.add_bitWidth(bitWidth);
- builder_.add_is_signed(is_signed);
- return builder_.Finish();
-}
-
-struct FloatingPoint FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef FloatingPointBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_PRECISION = 4
- };
- org::apache::arrow::flatbuf::Precision precision() const {
- return static_cast<org::apache::arrow::flatbuf::Precision>(GetField<int16_t>(VT_PRECISION, 0));
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_PRECISION) &&
- verifier.EndTable();
- }
-};
-
-struct FloatingPointBuilder {
- typedef FloatingPoint Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_precision(org::apache::arrow::flatbuf::Precision precision) {
- fbb_.AddElement<int16_t>(FloatingPoint::VT_PRECISION, static_cast<int16_t>(precision), 0);
- }
- explicit FloatingPointBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- FloatingPointBuilder &operator=(const FloatingPointBuilder &);
- flatbuffers::Offset<FloatingPoint> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<FloatingPoint>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<FloatingPoint> CreateFloatingPoint(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::Precision precision = org::apache::arrow::flatbuf::Precision::HALF) {
- FloatingPointBuilder builder_(_fbb);
- builder_.add_precision(precision);
- return builder_.Finish();
-}
-
-/// Unicode with UTF-8 encoding
-struct Utf8 FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef Utf8Builder Builder;
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- verifier.EndTable();
- }
-};
-
-struct Utf8Builder {
- typedef Utf8 Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- explicit Utf8Builder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- Utf8Builder &operator=(const Utf8Builder &);
- flatbuffers::Offset<Utf8> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Utf8>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Utf8> CreateUtf8(
- flatbuffers::FlatBufferBuilder &_fbb) {
- Utf8Builder builder_(_fbb);
- return builder_.Finish();
-}
-
-/// Opaque binary data
-struct Binary FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef BinaryBuilder Builder;
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- verifier.EndTable();
- }
-};
-
-struct BinaryBuilder {
- typedef Binary Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- explicit BinaryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- BinaryBuilder &operator=(const BinaryBuilder &);
- flatbuffers::Offset<Binary> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Binary>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Binary> CreateBinary(
- flatbuffers::FlatBufferBuilder &_fbb) {
- BinaryBuilder builder_(_fbb);
- return builder_.Finish();
-}
-
-/// Same as Utf8, but with 64-bit offsets, allowing to represent
-/// extremely large data values.
-struct LargeUtf8 FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef LargeUtf8Builder Builder;
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- verifier.EndTable();
- }
-};
-
-struct LargeUtf8Builder {
- typedef LargeUtf8 Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- explicit LargeUtf8Builder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- LargeUtf8Builder &operator=(const LargeUtf8Builder &);
- flatbuffers::Offset<LargeUtf8> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<LargeUtf8>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<LargeUtf8> CreateLargeUtf8(
- flatbuffers::FlatBufferBuilder &_fbb) {
- LargeUtf8Builder builder_(_fbb);
- return builder_.Finish();
-}
-
-/// Same as Binary, but with 64-bit offsets, allowing to represent
-/// extremely large data values.
-struct LargeBinary FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef LargeBinaryBuilder Builder;
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- verifier.EndTable();
- }
-};
-
-struct LargeBinaryBuilder {
- typedef LargeBinary Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- explicit LargeBinaryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- LargeBinaryBuilder &operator=(const LargeBinaryBuilder &);
- flatbuffers::Offset<LargeBinary> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<LargeBinary>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<LargeBinary> CreateLargeBinary(
- flatbuffers::FlatBufferBuilder &_fbb) {
- LargeBinaryBuilder builder_(_fbb);
- return builder_.Finish();
-}
-
-struct FixedSizeBinary FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef FixedSizeBinaryBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_BYTEWIDTH = 4
- };
- /// Number of bytes per value
- int32_t byteWidth() const {
- return GetField<int32_t>(VT_BYTEWIDTH, 0);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int32_t>(verifier, VT_BYTEWIDTH) &&
- verifier.EndTable();
- }
-};
-
-struct FixedSizeBinaryBuilder {
- typedef FixedSizeBinary Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_byteWidth(int32_t byteWidth) {
- fbb_.AddElement<int32_t>(FixedSizeBinary::VT_BYTEWIDTH, byteWidth, 0);
- }
- explicit FixedSizeBinaryBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- FixedSizeBinaryBuilder &operator=(const FixedSizeBinaryBuilder &);
- flatbuffers::Offset<FixedSizeBinary> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<FixedSizeBinary>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<FixedSizeBinary> CreateFixedSizeBinary(
- flatbuffers::FlatBufferBuilder &_fbb,
- int32_t byteWidth = 0) {
- FixedSizeBinaryBuilder builder_(_fbb);
- builder_.add_byteWidth(byteWidth);
- return builder_.Finish();
-}
-
-struct Bool FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef BoolBuilder Builder;
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- verifier.EndTable();
- }
-};
-
-struct BoolBuilder {
- typedef Bool Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- explicit BoolBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- BoolBuilder &operator=(const BoolBuilder &);
- flatbuffers::Offset<Bool> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Bool>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Bool> CreateBool(
- flatbuffers::FlatBufferBuilder &_fbb) {
- BoolBuilder builder_(_fbb);
- return builder_.Finish();
-}
-
-/// Exact decimal value represented as an integer value in two's
-/// complement. Currently only 128-bit (16-byte) integers are used but this may
-/// be expanded in the future. The representation uses the endianness indicated
-/// in the Schema.
-struct Decimal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef DecimalBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_PRECISION = 4,
- VT_SCALE = 6,
- VT_BITWIDTH = 8
- };
- /// Total number of decimal digits
- int32_t precision() const {
- return GetField<int32_t>(VT_PRECISION, 0);
- }
- /// Number of digits after the decimal point "."
- int32_t scale() const {
- return GetField<int32_t>(VT_SCALE, 0);
- }
- /// Number of bits per value. The only accepted width right now is 128 but
- /// this field exists for forward compatibility so that other bit widths may
- /// be supported in future format versions. We use bitWidth for consistency
- /// with Int::bitWidth.
- int32_t bitWidth() const {
- return GetField<int32_t>(VT_BITWIDTH, 128);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int32_t>(verifier, VT_PRECISION) &&
- VerifyField<int32_t>(verifier, VT_SCALE) &&
- VerifyField<int32_t>(verifier, VT_BITWIDTH) &&
- verifier.EndTable();
- }
-};
-
-struct DecimalBuilder {
- typedef Decimal Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_precision(int32_t precision) {
- fbb_.AddElement<int32_t>(Decimal::VT_PRECISION, precision, 0);
- }
- void add_scale(int32_t scale) {
- fbb_.AddElement<int32_t>(Decimal::VT_SCALE, scale, 0);
- }
- void add_bitWidth(int32_t bitWidth) {
- fbb_.AddElement<int32_t>(Decimal::VT_BITWIDTH, bitWidth, 128);
- }
- explicit DecimalBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- DecimalBuilder &operator=(const DecimalBuilder &);
- flatbuffers::Offset<Decimal> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Decimal>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Decimal> CreateDecimal(
- flatbuffers::FlatBufferBuilder &_fbb,
- int32_t precision = 0,
- int32_t scale = 0,
- int32_t bitWidth = 128) {
- DecimalBuilder builder_(_fbb);
- builder_.add_bitWidth(bitWidth);
- builder_.add_scale(scale);
- builder_.add_precision(precision);
- return builder_.Finish();
-}
-
-/// Date is either a 32-bit or 64-bit type representing elapsed time since UNIX
-/// epoch (1970-01-01), stored in either of two units:
-///
-/// * Milliseconds (64 bits) indicating UNIX time elapsed since the epoch (no
-/// leap seconds), where the values are evenly divisible by 86400000
-/// * Days (32 bits) since the UNIX epoch
-struct Date FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef DateBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_UNIT = 4
- };
- org::apache::arrow::flatbuf::DateUnit unit() const {
- return static_cast<org::apache::arrow::flatbuf::DateUnit>(GetField<int16_t>(VT_UNIT, 1));
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_UNIT) &&
- verifier.EndTable();
- }
-};
-
-struct DateBuilder {
- typedef Date Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_unit(org::apache::arrow::flatbuf::DateUnit unit) {
- fbb_.AddElement<int16_t>(Date::VT_UNIT, static_cast<int16_t>(unit), 1);
- }
- explicit DateBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- DateBuilder &operator=(const DateBuilder &);
- flatbuffers::Offset<Date> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Date>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Date> CreateDate(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::DateUnit unit = org::apache::arrow::flatbuf::DateUnit::MILLISECOND) {
- DateBuilder builder_(_fbb);
- builder_.add_unit(unit);
- return builder_.Finish();
-}
-
-/// Time type. The physical storage type depends on the unit
-/// - SECOND and MILLISECOND: 32 bits
-/// - MICROSECOND and NANOSECOND: 64 bits
-struct Time FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef TimeBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_UNIT = 4,
- VT_BITWIDTH = 6
- };
- org::apache::arrow::flatbuf::TimeUnit unit() const {
- return static_cast<org::apache::arrow::flatbuf::TimeUnit>(GetField<int16_t>(VT_UNIT, 1));
- }
- int32_t bitWidth() const {
- return GetField<int32_t>(VT_BITWIDTH, 32);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_UNIT) &&
- VerifyField<int32_t>(verifier, VT_BITWIDTH) &&
- verifier.EndTable();
- }
-};
-
-struct TimeBuilder {
- typedef Time Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_unit(org::apache::arrow::flatbuf::TimeUnit unit) {
- fbb_.AddElement<int16_t>(Time::VT_UNIT, static_cast<int16_t>(unit), 1);
- }
- void add_bitWidth(int32_t bitWidth) {
- fbb_.AddElement<int32_t>(Time::VT_BITWIDTH, bitWidth, 32);
- }
- explicit TimeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- TimeBuilder &operator=(const TimeBuilder &);
- flatbuffers::Offset<Time> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Time>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Time> CreateTime(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::TimeUnit unit = org::apache::arrow::flatbuf::TimeUnit::MILLISECOND,
- int32_t bitWidth = 32) {
- TimeBuilder builder_(_fbb);
- builder_.add_bitWidth(bitWidth);
- builder_.add_unit(unit);
- return builder_.Finish();
-}
-
-/// Time elapsed from the Unix epoch, 00:00:00.000 on 1 January 1970, excluding
-/// leap seconds, as a 64-bit integer. Note that UNIX time does not include
-/// leap seconds.
-///
-/// The Timestamp metadata supports both "time zone naive" and "time zone
-/// aware" timestamps. Read about the timezone attribute for more detail
-struct Timestamp FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef TimestampBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_UNIT = 4,
- VT_TIMEZONE = 6
- };
- org::apache::arrow::flatbuf::TimeUnit unit() const {
- return static_cast<org::apache::arrow::flatbuf::TimeUnit>(GetField<int16_t>(VT_UNIT, 0));
- }
- /// The time zone is a string indicating the name of a time zone, one of:
- ///
- /// * As used in the Olson time zone database (the "tz database" or
- /// "tzdata"), such as "America/New_York"
- /// * An absolute time zone offset of the form +XX:XX or -XX:XX, such as +07:30
- ///
- /// Whether a timezone string is present indicates different semantics about
- /// the data:
- ///
- /// * If the time zone is null or equal to an empty string, the data is "time
- /// zone naive" and shall be displayed *as is* to the user, not localized
- /// to the locale of the user. This data can be though of as UTC but
- /// without having "UTC" as the time zone, it is not considered to be
- /// localized to any time zone
- ///
- /// * If the time zone is set to a valid value, values can be displayed as
- /// "localized" to that time zone, even though the underlying 64-bit
- /// integers are identical to the same data stored in UTC. Converting
- /// between time zones is a metadata-only operation and does not change the
- /// underlying values
- const flatbuffers::String *timezone() const {
- return GetPointer<const flatbuffers::String *>(VT_TIMEZONE);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_UNIT) &&
- VerifyOffset(verifier, VT_TIMEZONE) &&
- verifier.VerifyString(timezone()) &&
- verifier.EndTable();
- }
-};
-
-struct TimestampBuilder {
- typedef Timestamp Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_unit(org::apache::arrow::flatbuf::TimeUnit unit) {
- fbb_.AddElement<int16_t>(Timestamp::VT_UNIT, static_cast<int16_t>(unit), 0);
- }
- void add_timezone(flatbuffers::Offset<flatbuffers::String> timezone) {
- fbb_.AddOffset(Timestamp::VT_TIMEZONE, timezone);
- }
- explicit TimestampBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- TimestampBuilder &operator=(const TimestampBuilder &);
- flatbuffers::Offset<Timestamp> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Timestamp>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Timestamp> CreateTimestamp(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::TimeUnit unit = org::apache::arrow::flatbuf::TimeUnit::SECOND,
- flatbuffers::Offset<flatbuffers::String> timezone = 0) {
- TimestampBuilder builder_(_fbb);
- builder_.add_timezone(timezone);
- builder_.add_unit(unit);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<Timestamp> CreateTimestampDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::TimeUnit unit = org::apache::arrow::flatbuf::TimeUnit::SECOND,
- const char *timezone = nullptr) {
- auto timezone__ = timezone ? _fbb.CreateString(timezone) : 0;
- return org::apache::arrow::flatbuf::CreateTimestamp(
- _fbb,
- unit,
- timezone__);
-}
-
-struct Interval FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef IntervalBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_UNIT = 4
- };
- org::apache::arrow::flatbuf::IntervalUnit unit() const {
- return static_cast<org::apache::arrow::flatbuf::IntervalUnit>(GetField<int16_t>(VT_UNIT, 0));
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_UNIT) &&
- verifier.EndTable();
- }
-};
-
-struct IntervalBuilder {
- typedef Interval Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_unit(org::apache::arrow::flatbuf::IntervalUnit unit) {
- fbb_.AddElement<int16_t>(Interval::VT_UNIT, static_cast<int16_t>(unit), 0);
- }
- explicit IntervalBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- IntervalBuilder &operator=(const IntervalBuilder &);
- flatbuffers::Offset<Interval> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Interval>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Interval> CreateInterval(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::IntervalUnit unit = org::apache::arrow::flatbuf::IntervalUnit::YEAR_MONTH) {
- IntervalBuilder builder_(_fbb);
- builder_.add_unit(unit);
- return builder_.Finish();
-}
-
-struct Duration FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef DurationBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_UNIT = 4
- };
- org::apache::arrow::flatbuf::TimeUnit unit() const {
- return static_cast<org::apache::arrow::flatbuf::TimeUnit>(GetField<int16_t>(VT_UNIT, 1));
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_UNIT) &&
- verifier.EndTable();
- }
-};
-
-struct DurationBuilder {
- typedef Duration Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_unit(org::apache::arrow::flatbuf::TimeUnit unit) {
- fbb_.AddElement<int16_t>(Duration::VT_UNIT, static_cast<int16_t>(unit), 1);
- }
- explicit DurationBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- DurationBuilder &operator=(const DurationBuilder &);
- flatbuffers::Offset<Duration> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Duration>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Duration> CreateDuration(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::TimeUnit unit = org::apache::arrow::flatbuf::TimeUnit::MILLISECOND) {
- DurationBuilder builder_(_fbb);
- builder_.add_unit(unit);
- return builder_.Finish();
-}
-
-/// ----------------------------------------------------------------------
-/// user defined key value pairs to add custom metadata to arrow
-/// key namespacing is the responsibility of the user
-struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef KeyValueBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_KEY = 4,
- VT_VALUE = 6
- };
- const flatbuffers::String *key() const {
- return GetPointer<const flatbuffers::String *>(VT_KEY);
- }
- const flatbuffers::String *value() const {
- return GetPointer<const flatbuffers::String *>(VT_VALUE);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyOffset(verifier, VT_KEY) &&
- verifier.VerifyString(key()) &&
- VerifyOffset(verifier, VT_VALUE) &&
- verifier.VerifyString(value()) &&
- verifier.EndTable();
- }
-};
-
-struct KeyValueBuilder {
- typedef KeyValue Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_key(flatbuffers::Offset<flatbuffers::String> key) {
- fbb_.AddOffset(KeyValue::VT_KEY, key);
- }
- void add_value(flatbuffers::Offset<flatbuffers::String> value) {
- fbb_.AddOffset(KeyValue::VT_VALUE, value);
- }
- explicit KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- KeyValueBuilder &operator=(const KeyValueBuilder &);
- flatbuffers::Offset<KeyValue> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<KeyValue>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<KeyValue> CreateKeyValue(
- flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<flatbuffers::String> key = 0,
- flatbuffers::Offset<flatbuffers::String> value = 0) {
- KeyValueBuilder builder_(_fbb);
- builder_.add_value(value);
- builder_.add_key(key);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- const char *key = nullptr,
- const char *value = nullptr) {
- auto key__ = key ? _fbb.CreateString(key) : 0;
- auto value__ = value ? _fbb.CreateString(value) : 0;
- return org::apache::arrow::flatbuf::CreateKeyValue(
- _fbb,
- key__,
- value__);
-}
-
-struct DictionaryEncoding FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef DictionaryEncodingBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_ID = 4,
- VT_INDEXTYPE = 6,
- VT_ISORDERED = 8,
- VT_DICTIONARYKIND = 10
- };
- /// The known dictionary id in the application where this data is used. In
- /// the file or streaming formats, the dictionary ids are found in the
- /// DictionaryBatch messages
- int64_t id() const {
- return GetField<int64_t>(VT_ID, 0);
- }
- /// The dictionary indices are constrained to be non-negative integers. If
- /// this field is null, the indices must be signed int32. To maximize
- /// cross-language compatibility and performance, implementations are
- /// recommended to prefer signed integer types over unsigned integer types
- /// and to avoid uint64 indices unless they are required by an application.
- const org::apache::arrow::flatbuf::Int *indexType() const {
- return GetPointer<const org::apache::arrow::flatbuf::Int *>(VT_INDEXTYPE);
- }
- /// By default, dictionaries are not ordered, or the order does not have
- /// semantic meaning. In some statistical, applications, dictionary-encoding
- /// is used to represent ordered categorical data, and we provide a way to
- /// preserve that metadata here
- bool isOrdered() const {
- return GetField<uint8_t>(VT_ISORDERED, 0) != 0;
- }
- org::apache::arrow::flatbuf::DictionaryKind dictionaryKind() const {
- return static_cast<org::apache::arrow::flatbuf::DictionaryKind>(GetField<int16_t>(VT_DICTIONARYKIND, 0));
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int64_t>(verifier, VT_ID) &&
- VerifyOffset(verifier, VT_INDEXTYPE) &&
- verifier.VerifyTable(indexType()) &&
- VerifyField<uint8_t>(verifier, VT_ISORDERED) &&
- VerifyField<int16_t>(verifier, VT_DICTIONARYKIND) &&
- verifier.EndTable();
- }
-};
-
-struct DictionaryEncodingBuilder {
- typedef DictionaryEncoding Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_id(int64_t id) {
- fbb_.AddElement<int64_t>(DictionaryEncoding::VT_ID, id, 0);
- }
- void add_indexType(flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indexType) {
- fbb_.AddOffset(DictionaryEncoding::VT_INDEXTYPE, indexType);
- }
- void add_isOrdered(bool isOrdered) {
- fbb_.AddElement<uint8_t>(DictionaryEncoding::VT_ISORDERED, static_cast<uint8_t>(isOrdered), 0);
- }
- void add_dictionaryKind(org::apache::arrow::flatbuf::DictionaryKind dictionaryKind) {
- fbb_.AddElement<int16_t>(DictionaryEncoding::VT_DICTIONARYKIND, static_cast<int16_t>(dictionaryKind), 0);
- }
- explicit DictionaryEncodingBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- DictionaryEncodingBuilder &operator=(const DictionaryEncodingBuilder &);
- flatbuffers::Offset<DictionaryEncoding> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<DictionaryEncoding>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<DictionaryEncoding> CreateDictionaryEncoding(
- flatbuffers::FlatBufferBuilder &_fbb,
- int64_t id = 0,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indexType = 0,
- bool isOrdered = false,
- org::apache::arrow::flatbuf::DictionaryKind dictionaryKind = org::apache::arrow::flatbuf::DictionaryKind::DenseArray) {
- DictionaryEncodingBuilder builder_(_fbb);
- builder_.add_id(id);
- builder_.add_indexType(indexType);
- builder_.add_dictionaryKind(dictionaryKind);
- builder_.add_isOrdered(isOrdered);
- return builder_.Finish();
-}
-
-/// ----------------------------------------------------------------------
-/// A field represents a named column in a record / row batch or child of a
-/// nested type.
-struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef FieldBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_NAME = 4,
- VT_NULLABLE = 6,
- VT_TYPE_TYPE = 8,
- VT_TYPE = 10,
- VT_DICTIONARY = 12,
- VT_CHILDREN = 14,
- VT_CUSTOM_METADATA = 16
- };
- /// Name is not required, in i.e. a List
- const flatbuffers::String *name() const {
- return GetPointer<const flatbuffers::String *>(VT_NAME);
- }
- /// Whether or not this field can contain nulls. Should be true in general.
- bool nullable() const {
- return GetField<uint8_t>(VT_NULLABLE, 0) != 0;
- }
- org::apache::arrow::flatbuf::Type type_type() const {
- return static_cast<org::apache::arrow::flatbuf::Type>(GetField<uint8_t>(VT_TYPE_TYPE, 0));
- }
- /// This is the type of the decoded value if the field is dictionary encoded.
- const void *type() const {
- return GetPointer<const void *>(VT_TYPE);
- }
- template<typename T> const T *type_as() const;
- const org::apache::arrow::flatbuf::Null *type_as_Null() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Null ? static_cast<const org::apache::arrow::flatbuf::Null *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Int *type_as_Int() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Int ? static_cast<const org::apache::arrow::flatbuf::Int *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::FloatingPoint *type_as_FloatingPoint() const {
- return type_type() == org::apache::arrow::flatbuf::Type::FloatingPoint ? static_cast<const org::apache::arrow::flatbuf::FloatingPoint *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Binary *type_as_Binary() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Binary ? static_cast<const org::apache::arrow::flatbuf::Binary *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Utf8 *type_as_Utf8() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Utf8 ? static_cast<const org::apache::arrow::flatbuf::Utf8 *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Bool *type_as_Bool() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Bool ? static_cast<const org::apache::arrow::flatbuf::Bool *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Decimal *type_as_Decimal() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Decimal ? static_cast<const org::apache::arrow::flatbuf::Decimal *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Date *type_as_Date() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Date ? static_cast<const org::apache::arrow::flatbuf::Date *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Time *type_as_Time() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Time ? static_cast<const org::apache::arrow::flatbuf::Time *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Timestamp *type_as_Timestamp() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Timestamp ? static_cast<const org::apache::arrow::flatbuf::Timestamp *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Interval *type_as_Interval() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Interval ? static_cast<const org::apache::arrow::flatbuf::Interval *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::List *type_as_List() const {
- return type_type() == org::apache::arrow::flatbuf::Type::List ? static_cast<const org::apache::arrow::flatbuf::List *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Struct_ *type_as_Struct_() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Struct_ ? static_cast<const org::apache::arrow::flatbuf::Struct_ *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Union *type_as_Union() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Union ? static_cast<const org::apache::arrow::flatbuf::Union *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::FixedSizeBinary *type_as_FixedSizeBinary() const {
- return type_type() == org::apache::arrow::flatbuf::Type::FixedSizeBinary ? static_cast<const org::apache::arrow::flatbuf::FixedSizeBinary *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::FixedSizeList *type_as_FixedSizeList() const {
- return type_type() == org::apache::arrow::flatbuf::Type::FixedSizeList ? static_cast<const org::apache::arrow::flatbuf::FixedSizeList *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Map *type_as_Map() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Map ? static_cast<const org::apache::arrow::flatbuf::Map *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Duration *type_as_Duration() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Duration ? static_cast<const org::apache::arrow::flatbuf::Duration *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::LargeBinary *type_as_LargeBinary() const {
- return type_type() == org::apache::arrow::flatbuf::Type::LargeBinary ? static_cast<const org::apache::arrow::flatbuf::LargeBinary *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::LargeUtf8 *type_as_LargeUtf8() const {
- return type_type() == org::apache::arrow::flatbuf::Type::LargeUtf8 ? static_cast<const org::apache::arrow::flatbuf::LargeUtf8 *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::LargeList *type_as_LargeList() const {
- return type_type() == org::apache::arrow::flatbuf::Type::LargeList ? static_cast<const org::apache::arrow::flatbuf::LargeList *>(type()) : nullptr;
- }
- /// Present only if the field is dictionary encoded.
- const org::apache::arrow::flatbuf::DictionaryEncoding *dictionary() const {
- return GetPointer<const org::apache::arrow::flatbuf::DictionaryEncoding *>(VT_DICTIONARY);
- }
- /// children apply only to nested data types like Struct, List and Union. For
- /// primitive types children will have length 0.
- const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>> *children() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>> *>(VT_CHILDREN);
- }
- /// User-defined metadata
- const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *custom_metadata() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *>(VT_CUSTOM_METADATA);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyOffset(verifier, VT_NAME) &&
- verifier.VerifyString(name()) &&
- VerifyField<uint8_t>(verifier, VT_NULLABLE) &&
- VerifyField<uint8_t>(verifier, VT_TYPE_TYPE) &&
- VerifyOffset(verifier, VT_TYPE) &&
- VerifyType(verifier, type(), type_type()) &&
- VerifyOffset(verifier, VT_DICTIONARY) &&
- verifier.VerifyTable(dictionary()) &&
- VerifyOffset(verifier, VT_CHILDREN) &&
- verifier.VerifyVector(children()) &&
- verifier.VerifyVectorOfTables(children()) &&
- VerifyOffset(verifier, VT_CUSTOM_METADATA) &&
- verifier.VerifyVector(custom_metadata()) &&
- verifier.VerifyVectorOfTables(custom_metadata()) &&
- verifier.EndTable();
- }
-};
-
-template<> inline const org::apache::arrow::flatbuf::Null *Field::type_as<org::apache::arrow::flatbuf::Null>() const {
- return type_as_Null();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Int *Field::type_as<org::apache::arrow::flatbuf::Int>() const {
- return type_as_Int();
-}
-
-template<> inline const org::apache::arrow::flatbuf::FloatingPoint *Field::type_as<org::apache::arrow::flatbuf::FloatingPoint>() const {
- return type_as_FloatingPoint();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Binary *Field::type_as<org::apache::arrow::flatbuf::Binary>() const {
- return type_as_Binary();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Utf8 *Field::type_as<org::apache::arrow::flatbuf::Utf8>() const {
- return type_as_Utf8();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Bool *Field::type_as<org::apache::arrow::flatbuf::Bool>() const {
- return type_as_Bool();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Decimal *Field::type_as<org::apache::arrow::flatbuf::Decimal>() const {
- return type_as_Decimal();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Date *Field::type_as<org::apache::arrow::flatbuf::Date>() const {
- return type_as_Date();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Time *Field::type_as<org::apache::arrow::flatbuf::Time>() const {
- return type_as_Time();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Timestamp *Field::type_as<org::apache::arrow::flatbuf::Timestamp>() const {
- return type_as_Timestamp();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Interval *Field::type_as<org::apache::arrow::flatbuf::Interval>() const {
- return type_as_Interval();
-}
-
-template<> inline const org::apache::arrow::flatbuf::List *Field::type_as<org::apache::arrow::flatbuf::List>() const {
- return type_as_List();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Struct_ *Field::type_as<org::apache::arrow::flatbuf::Struct_>() const {
- return type_as_Struct_();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Union *Field::type_as<org::apache::arrow::flatbuf::Union>() const {
- return type_as_Union();
-}
-
-template<> inline const org::apache::arrow::flatbuf::FixedSizeBinary *Field::type_as<org::apache::arrow::flatbuf::FixedSizeBinary>() const {
- return type_as_FixedSizeBinary();
-}
-
-template<> inline const org::apache::arrow::flatbuf::FixedSizeList *Field::type_as<org::apache::arrow::flatbuf::FixedSizeList>() const {
- return type_as_FixedSizeList();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Map *Field::type_as<org::apache::arrow::flatbuf::Map>() const {
- return type_as_Map();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Duration *Field::type_as<org::apache::arrow::flatbuf::Duration>() const {
- return type_as_Duration();
-}
-
-template<> inline const org::apache::arrow::flatbuf::LargeBinary *Field::type_as<org::apache::arrow::flatbuf::LargeBinary>() const {
- return type_as_LargeBinary();
-}
-
-template<> inline const org::apache::arrow::flatbuf::LargeUtf8 *Field::type_as<org::apache::arrow::flatbuf::LargeUtf8>() const {
- return type_as_LargeUtf8();
-}
-
-template<> inline const org::apache::arrow::flatbuf::LargeList *Field::type_as<org::apache::arrow::flatbuf::LargeList>() const {
- return type_as_LargeList();
-}
-
-struct FieldBuilder {
- typedef Field Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_name(flatbuffers::Offset<flatbuffers::String> name) {
- fbb_.AddOffset(Field::VT_NAME, name);
- }
- void add_nullable(bool nullable) {
- fbb_.AddElement<uint8_t>(Field::VT_NULLABLE, static_cast<uint8_t>(nullable), 0);
- }
- void add_type_type(org::apache::arrow::flatbuf::Type type_type) {
- fbb_.AddElement<uint8_t>(Field::VT_TYPE_TYPE, static_cast<uint8_t>(type_type), 0);
- }
- void add_type(flatbuffers::Offset<void> type) {
- fbb_.AddOffset(Field::VT_TYPE, type);
- }
- void add_dictionary(flatbuffers::Offset<org::apache::arrow::flatbuf::DictionaryEncoding> dictionary) {
- fbb_.AddOffset(Field::VT_DICTIONARY, dictionary);
- }
- void add_children(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>>> children) {
- fbb_.AddOffset(Field::VT_CHILDREN, children);
- }
- void add_custom_metadata(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>> custom_metadata) {
- fbb_.AddOffset(Field::VT_CUSTOM_METADATA, custom_metadata);
- }
- explicit FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- FieldBuilder &operator=(const FieldBuilder &);
- flatbuffers::Offset<Field> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Field>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Field> CreateField(
- flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<flatbuffers::String> name = 0,
- bool nullable = false,
- org::apache::arrow::flatbuf::Type type_type = org::apache::arrow::flatbuf::Type::NONE,
- flatbuffers::Offset<void> type = 0,
- flatbuffers::Offset<org::apache::arrow::flatbuf::DictionaryEncoding> dictionary = 0,
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>>> children = 0,
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>> custom_metadata = 0) {
- FieldBuilder builder_(_fbb);
- builder_.add_custom_metadata(custom_metadata);
- builder_.add_children(children);
- builder_.add_dictionary(dictionary);
- builder_.add_type(type);
- builder_.add_name(name);
- builder_.add_type_type(type_type);
- builder_.add_nullable(nullable);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<Field> CreateFieldDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- const char *name = nullptr,
- bool nullable = false,
- org::apache::arrow::flatbuf::Type type_type = org::apache::arrow::flatbuf::Type::NONE,
- flatbuffers::Offset<void> type = 0,
- flatbuffers::Offset<org::apache::arrow::flatbuf::DictionaryEncoding> dictionary = 0,
- const std::vector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>> *children = nullptr,
- const std::vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *custom_metadata = nullptr) {
- auto name__ = name ? _fbb.CreateString(name) : 0;
- auto children__ = children ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>>(*children) : 0;
- auto custom_metadata__ = custom_metadata ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>(*custom_metadata) : 0;
- return org::apache::arrow::flatbuf::CreateField(
- _fbb,
- name__,
- nullable,
- type_type,
- type,
- dictionary,
- children__,
- custom_metadata__);
-}
-
-/// ----------------------------------------------------------------------
-/// A Schema describes the columns in a row batch
-struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef SchemaBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_ENDIANNESS = 4,
- VT_FIELDS = 6,
- VT_CUSTOM_METADATA = 8,
- VT_FEATURES = 10
- };
- /// endianness of the buffer
- /// it is Little Endian by default
- /// if endianness doesn't match the underlying system then the vectors need to be converted
- org::apache::arrow::flatbuf::Endianness endianness() const {
- return static_cast<org::apache::arrow::flatbuf::Endianness>(GetField<int16_t>(VT_ENDIANNESS, 0));
- }
- const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>> *fields() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>> *>(VT_FIELDS);
- }
- const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *custom_metadata() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *>(VT_CUSTOM_METADATA);
- }
- /// Features used in the stream/file.
- const flatbuffers::Vector<int64_t> *features() const {
- return GetPointer<const flatbuffers::Vector<int64_t> *>(VT_FEATURES);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_ENDIANNESS) &&
- VerifyOffset(verifier, VT_FIELDS) &&
- verifier.VerifyVector(fields()) &&
- verifier.VerifyVectorOfTables(fields()) &&
- VerifyOffset(verifier, VT_CUSTOM_METADATA) &&
- verifier.VerifyVector(custom_metadata()) &&
- verifier.VerifyVectorOfTables(custom_metadata()) &&
- VerifyOffset(verifier, VT_FEATURES) &&
- verifier.VerifyVector(features()) &&
- verifier.EndTable();
- }
-};
-
-struct SchemaBuilder {
- typedef Schema Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_endianness(org::apache::arrow::flatbuf::Endianness endianness) {
- fbb_.AddElement<int16_t>(Schema::VT_ENDIANNESS, static_cast<int16_t>(endianness), 0);
- }
- void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>>> fields) {
- fbb_.AddOffset(Schema::VT_FIELDS, fields);
- }
- void add_custom_metadata(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>> custom_metadata) {
- fbb_.AddOffset(Schema::VT_CUSTOM_METADATA, custom_metadata);
- }
- void add_features(flatbuffers::Offset<flatbuffers::Vector<int64_t>> features) {
- fbb_.AddOffset(Schema::VT_FEATURES, features);
- }
- explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- SchemaBuilder &operator=(const SchemaBuilder &);
- flatbuffers::Offset<Schema> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Schema>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Schema> CreateSchema(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::Endianness endianness = org::apache::arrow::flatbuf::Endianness::Little,
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>>> fields = 0,
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>> custom_metadata = 0,
- flatbuffers::Offset<flatbuffers::Vector<int64_t>> features = 0) {
- SchemaBuilder builder_(_fbb);
- builder_.add_features(features);
- builder_.add_custom_metadata(custom_metadata);
- builder_.add_fields(fields);
- builder_.add_endianness(endianness);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<Schema> CreateSchemaDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::Endianness endianness = org::apache::arrow::flatbuf::Endianness::Little,
- const std::vector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>> *fields = nullptr,
- const std::vector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>> *custom_metadata = nullptr,
- const std::vector<int64_t> *features = nullptr) {
- auto fields__ = fields ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::flatbuf::Field>>(*fields) : 0;
- auto custom_metadata__ = custom_metadata ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::flatbuf::KeyValue>>(*custom_metadata) : 0;
- auto features__ = features ? _fbb.CreateVector<int64_t>(*features) : 0;
- return org::apache::arrow::flatbuf::CreateSchema(
- _fbb,
- endianness,
- fields__,
- custom_metadata__,
- features__);
-}
-
-inline bool VerifyType(flatbuffers::Verifier &verifier, const void *obj, Type type) {
- switch (type) {
- case Type::NONE: {
- return true;
- }
- case Type::Null: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Null *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Int: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Int *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::FloatingPoint: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::FloatingPoint *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Binary: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Binary *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Utf8: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Utf8 *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Bool: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Bool *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Decimal: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Decimal *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Date: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Date *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Time: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Time *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Timestamp: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Timestamp *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Interval: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Interval *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::List: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::List *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Struct_: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Struct_ *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Union: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Union *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::FixedSizeBinary: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::FixedSizeBinary *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::FixedSizeList: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::FixedSizeList *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Map: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Map *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::Duration: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::Duration *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::LargeBinary: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::LargeBinary *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::LargeUtf8: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::LargeUtf8 *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case Type::LargeList: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::LargeList *>(obj);
- return verifier.VerifyTable(ptr);
- }
- default: return true;
- }
-}
-
-inline bool VerifyTypeVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
- if (!values || !types) return !values && !types;
- if (values->size() != types->size()) return false;
- for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
- if (!VerifyType(
- verifier, values->Get(i), types->GetEnum<Type>(i))) {
- return false;
- }
- }
- return true;
-}
-
-inline const org::apache::arrow::flatbuf::Schema *GetSchema(const void *buf) {
- return flatbuffers::GetRoot<org::apache::arrow::flatbuf::Schema>(buf);
-}
-
-inline const org::apache::arrow::flatbuf::Schema *GetSizePrefixedSchema(const void *buf) {
- return flatbuffers::GetSizePrefixedRoot<org::apache::arrow::flatbuf::Schema>(buf);
-}
-
-inline bool VerifySchemaBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifyBuffer<org::apache::arrow::flatbuf::Schema>(nullptr);
-}
-
-inline bool VerifySizePrefixedSchemaBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifySizePrefixedBuffer<org::apache::arrow::flatbuf::Schema>(nullptr);
-}
-
-inline void FinishSchemaBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Schema> root) {
- fbb.Finish(root);
-}
-
-inline void FinishSizePrefixedSchemaBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Schema> root) {
- fbb.FinishSizePrefixed(root);
-}
-
-} // namespace flatbuf
-} // namespace arrow
-} // namespace apache
-} // namespace org
-
-#endif // FLATBUFFERS_GENERATED_SCHEMA_ORG_APACHE_ARROW_FLATBUF_H_
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs b/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs
new file mode 100644
index 0000000000..a6fd2f9e74
--- /dev/null
+++ b/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor.fbs
@@ -0,0 +1,228 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.
+
+/// EXPERIMENTAL: Metadata for n-dimensional sparse arrays, aka "sparse tensors".
+/// Arrow implementations in general are not required to implement this type
+
+include "Tensor.fbs";
+
+namespace org.apache.arrow.flatbuf;
+
+/// ----------------------------------------------------------------------
+/// EXPERIMENTAL: Data structures for sparse tensors
+
+/// Coordinate (COO) format of sparse tensor index.
+///
+/// COO's index list are represented as a NxM matrix,
+/// where N is the number of non-zero values,
+/// and M is the number of dimensions of a sparse tensor.
+///
+/// indicesBuffer stores the location and size of the data of this indices
+/// matrix. The value type and the stride of the indices matrix is
+/// specified in indicesType and indicesStrides fields.
+///
+/// For example, let X be a 2x3x4x5 tensor, and it has the following
+/// 6 non-zero values:
+/// ```text
+/// X[0, 1, 2, 0] := 1
+/// X[1, 1, 2, 3] := 2
+/// X[0, 2, 1, 0] := 3
+/// X[0, 1, 3, 0] := 4
+/// X[0, 1, 2, 1] := 5
+/// X[1, 2, 0, 4] := 6
+/// ```
+/// In COO format, the index matrix of X is the following 4x6 matrix:
+/// ```text
+/// [[0, 0, 0, 0, 1, 1],
+/// [1, 1, 1, 2, 1, 2],
+/// [2, 2, 3, 1, 2, 0],
+/// [0, 1, 0, 0, 3, 4]]
+/// ```
+/// When isCanonical is true, the indices is sorted in lexicographical order
+/// (row-major order), and it does not have duplicated entries. Otherwise,
+/// the indices may not be sorted, or may have duplicated entries.
+table SparseTensorIndexCOO {
+ /// The type of values in indicesBuffer
+ indicesType: Int (required);
+
+ /// Non-negative byte offsets to advance one value cell along each dimension
+ /// If omitted, default to row-major order (C-like).
+ indicesStrides: [long];
+
+ /// The location and size of the indices matrix's data
+ indicesBuffer: Buffer (required);
+
+ /// This flag is true if and only if the indices matrix is sorted in
+ /// row-major order, and does not have duplicated entries.
+ /// This sort order is the same as of Tensorflow's SparseTensor,
+ /// but it is inverse order of SciPy's canonical coo_matrix
+ /// (SciPy employs column-major order for its coo_matrix).
+ isCanonical: bool;
+}
+
+enum SparseMatrixCompressedAxis: short { Row, Column }
+
+/// Compressed Sparse format, that is matrix-specific.
+table SparseMatrixIndexCSX {
+ /// Which axis, row or column, is compressed
+ compressedAxis: SparseMatrixCompressedAxis;
+
+ /// The type of values in indptrBuffer
+ indptrType: Int (required);
+
+ /// indptrBuffer stores the location and size of indptr array that
+ /// represents the range of the rows.
+ /// The i-th row spans from `indptr[i]` to `indptr[i+1]` in the data.
+ /// The length of this array is 1 + (the number of rows), and the type
+ /// of index value is long.
+ ///
+ /// For example, let X be the following 6x4 matrix:
+ /// ```text
+ /// X := [[0, 1, 2, 0],
+ /// [0, 0, 3, 0],
+ /// [0, 4, 0, 5],
+ /// [0, 0, 0, 0],
+ /// [6, 0, 7, 8],
+ /// [0, 9, 0, 0]].
+ /// ```
+ /// The array of non-zero values in X is:
+ /// ```text
+ /// values(X) = [1, 2, 3, 4, 5, 6, 7, 8, 9].
+ /// ```
+ /// And the indptr of X is:
+ /// ```text
+ /// indptr(X) = [0, 2, 3, 5, 5, 8, 10].
+ /// ```
+ indptrBuffer: Buffer (required);
+
+ /// The type of values in indicesBuffer
+ indicesType: Int (required);
+
+ /// indicesBuffer stores the location and size of the array that
+ /// contains the column indices of the corresponding non-zero values.
+ /// The type of index value is long.
+ ///
+ /// For example, the indices of the above X is:
+ /// ```text
+ /// indices(X) = [1, 2, 2, 1, 3, 0, 2, 3, 1].
+ /// ```
+ /// Note that the indices are sorted in lexicographical order for each row.
+ indicesBuffer: Buffer (required);
+}
+
+/// Compressed Sparse Fiber (CSF) sparse tensor index.
+table SparseTensorIndexCSF {
+ /// CSF is a generalization of compressed sparse row (CSR) index.
+ /// See [smith2017knl](http://shaden.io/pub-files/smith2017knl.pdf)
+ ///
+ /// CSF index recursively compresses each dimension of a tensor into a set
+ /// of prefix trees. Each path from a root to leaf forms one tensor
+ /// non-zero index. CSF is implemented with two arrays of buffers and one
+ /// arrays of integers.
+ ///
+ /// For example, let X be a 2x3x4x5 tensor and let it have the following
+ /// 8 non-zero values:
+ /// ```text
+ /// X[0, 0, 0, 1] := 1
+ /// X[0, 0, 0, 2] := 2
+ /// X[0, 1, 0, 0] := 3
+ /// X[0, 1, 0, 2] := 4
+ /// X[0, 1, 1, 0] := 5
+ /// X[1, 1, 1, 0] := 6
+ /// X[1, 1, 1, 1] := 7
+ /// X[1, 1, 1, 2] := 8
+ /// ```
+ /// As a prefix tree this would be represented as:
+ /// ```text
+ /// 0 1
+ /// / \ |
+ /// 0 1 1
+ /// / / \ |
+ /// 0 0 1 1
+ /// /| /| | /| |
+ /// 1 2 0 2 0 0 1 2
+ /// ```
+ /// The type of values in indptrBuffers
+ indptrType: Int (required);
+
+ /// indptrBuffers stores the sparsity structure.
+ /// Each two consecutive dimensions in a tensor correspond to a buffer in
+ /// indptrBuffers. A pair of consecutive values at `indptrBuffers[dim][i]`
+ /// and `indptrBuffers[dim][i + 1]` signify a range of nodes in
+ /// `indicesBuffers[dim + 1]` who are children of `indicesBuffers[dim][i]` node.
+ ///
+ /// For example, the indptrBuffers for the above X is:
+ /// ```text
+ /// indptrBuffer(X) = [
+ /// [0, 2, 3],
+ /// [0, 1, 3, 4],
+ /// [0, 2, 4, 5, 8]
+ /// ].
+ /// ```
+ indptrBuffers: [Buffer] (required);
+
+ /// The type of values in indicesBuffers
+ indicesType: Int (required);
+
+ /// indicesBuffers stores values of nodes.
+ /// Each tensor dimension corresponds to a buffer in indicesBuffers.
+ /// For example, the indicesBuffers for the above X is:
+ /// ```text
+ /// indicesBuffer(X) = [
+ /// [0, 1],
+ /// [0, 1, 1],
+ /// [0, 0, 1, 1],
+ /// [1, 2, 0, 2, 0, 0, 1, 2]
+ /// ].
+ /// ```
+ indicesBuffers: [Buffer] (required);
+
+ /// axisOrder stores the sequence in which dimensions were traversed to
+ /// produce the prefix tree.
+ /// For example, the axisOrder for the above X is:
+ /// ```text
+ /// axisOrder(X) = [0, 1, 2, 3].
+ /// ```
+ axisOrder: [int] (required);
+}
+
+union SparseTensorIndex {
+ SparseTensorIndexCOO,
+ SparseMatrixIndexCSX,
+ SparseTensorIndexCSF
+}
+
+table SparseTensor {
+ /// The type of data contained in a value cell.
+ /// Currently only fixed-width value types are supported,
+ /// no strings or nested types.
+ type: Type (required);
+
+ /// The dimensions of the tensor, optionally named.
+ shape: [TensorDim] (required);
+
+ /// The number of non-zero values in a sparse tensor.
+ non_zero_length: long;
+
+ /// Sparse tensor index
+ sparseIndex: SparseTensorIndex (required);
+
+ /// The location and size of the tensor's data
+ data: Buffer (required);
+}
+
+root_type SparseTensor;
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor_generated.h b/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor_generated.h
deleted file mode 100644
index ec4d414d4f..0000000000
--- a/contrib/libs/apache/arrow/cpp/src/generated/SparseTensor_generated.h
+++ /dev/null
@@ -1,913 +0,0 @@
-// automatically generated by the FlatBuffers compiler, do not modify
-
-
-#ifndef FLATBUFFERS_GENERATED_SPARSETENSOR_ORG_APACHE_ARROW_FLATBUF_H_
-#define FLATBUFFERS_GENERATED_SPARSETENSOR_ORG_APACHE_ARROW_FLATBUF_H_
-
-#include "flatbuffers/flatbuffers.h"
-
-#include "Schema_generated.h"
-#include "Tensor_generated.h"
-
-namespace org {
-namespace apache {
-namespace arrow {
-namespace flatbuf {
-
-struct SparseTensorIndexCOO;
-struct SparseTensorIndexCOOBuilder;
-
-struct SparseMatrixIndexCSX;
-struct SparseMatrixIndexCSXBuilder;
-
-struct SparseTensorIndexCSF;
-struct SparseTensorIndexCSFBuilder;
-
-struct SparseTensor;
-struct SparseTensorBuilder;
-
-enum class SparseMatrixCompressedAxis : int16_t {
- Row = 0,
- Column = 1,
- MIN = Row,
- MAX = Column
-};
-
-inline const SparseMatrixCompressedAxis (&EnumValuesSparseMatrixCompressedAxis())[2] {
- static const SparseMatrixCompressedAxis values[] = {
- SparseMatrixCompressedAxis::Row,
- SparseMatrixCompressedAxis::Column
- };
- return values;
-}
-
-inline const char * const *EnumNamesSparseMatrixCompressedAxis() {
- static const char * const names[3] = {
- "Row",
- "Column",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameSparseMatrixCompressedAxis(SparseMatrixCompressedAxis e) {
- if (flatbuffers::IsOutRange(e, SparseMatrixCompressedAxis::Row, SparseMatrixCompressedAxis::Column)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesSparseMatrixCompressedAxis()[index];
-}
-
-enum class SparseTensorIndex : uint8_t {
- NONE = 0,
- SparseTensorIndexCOO = 1,
- SparseMatrixIndexCSX = 2,
- SparseTensorIndexCSF = 3,
- MIN = NONE,
- MAX = SparseTensorIndexCSF
-};
-
-inline const SparseTensorIndex (&EnumValuesSparseTensorIndex())[4] {
- static const SparseTensorIndex values[] = {
- SparseTensorIndex::NONE,
- SparseTensorIndex::SparseTensorIndexCOO,
- SparseTensorIndex::SparseMatrixIndexCSX,
- SparseTensorIndex::SparseTensorIndexCSF
- };
- return values;
-}
-
-inline const char * const *EnumNamesSparseTensorIndex() {
- static const char * const names[5] = {
- "NONE",
- "SparseTensorIndexCOO",
- "SparseMatrixIndexCSX",
- "SparseTensorIndexCSF",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameSparseTensorIndex(SparseTensorIndex e) {
- if (flatbuffers::IsOutRange(e, SparseTensorIndex::NONE, SparseTensorIndex::SparseTensorIndexCSF)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesSparseTensorIndex()[index];
-}
-
-template<typename T> struct SparseTensorIndexTraits {
- static const SparseTensorIndex enum_value = SparseTensorIndex::NONE;
-};
-
-template<> struct SparseTensorIndexTraits<org::apache::arrow::flatbuf::SparseTensorIndexCOO> {
- static const SparseTensorIndex enum_value = SparseTensorIndex::SparseTensorIndexCOO;
-};
-
-template<> struct SparseTensorIndexTraits<org::apache::arrow::flatbuf::SparseMatrixIndexCSX> {
- static const SparseTensorIndex enum_value = SparseTensorIndex::SparseMatrixIndexCSX;
-};
-
-template<> struct SparseTensorIndexTraits<org::apache::arrow::flatbuf::SparseTensorIndexCSF> {
- static const SparseTensorIndex enum_value = SparseTensorIndex::SparseTensorIndexCSF;
-};
-
-bool VerifySparseTensorIndex(flatbuffers::Verifier &verifier, const void *obj, SparseTensorIndex type);
-bool VerifySparseTensorIndexVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
-
-/// ----------------------------------------------------------------------
-/// EXPERIMENTAL: Data structures for sparse tensors
-/// Coordinate (COO) format of sparse tensor index.
-///
-/// COO's index list are represented as a NxM matrix,
-/// where N is the number of non-zero values,
-/// and M is the number of dimensions of a sparse tensor.
-///
-/// indicesBuffer stores the location and size of the data of this indices
-/// matrix. The value type and the stride of the indices matrix is
-/// specified in indicesType and indicesStrides fields.
-///
-/// For example, let X be a 2x3x4x5 tensor, and it has the following
-/// 6 non-zero values:
-///
-/// X[0, 1, 2, 0] := 1
-/// X[1, 1, 2, 3] := 2
-/// X[0, 2, 1, 0] := 3
-/// X[0, 1, 3, 0] := 4
-/// X[0, 1, 2, 1] := 5
-/// X[1, 2, 0, 4] := 6
-///
-/// In COO format, the index matrix of X is the following 4x6 matrix:
-///
-/// [[0, 0, 0, 0, 1, 1],
-/// [1, 1, 1, 2, 1, 2],
-/// [2, 2, 3, 1, 2, 0],
-/// [0, 1, 0, 0, 3, 4]]
-///
-/// Note that the indices are sorted in lexicographical order.
-struct SparseTensorIndexCOO FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef SparseTensorIndexCOOBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_INDICESTYPE = 4,
- VT_INDICESSTRIDES = 6,
- VT_INDICESBUFFER = 8,
- VT_ISCANONICAL = 10
- };
- /// The type of values in indicesBuffer
- const org::apache::arrow::flatbuf::Int *indicesType() const {
- return GetPointer<const org::apache::arrow::flatbuf::Int *>(VT_INDICESTYPE);
- }
- /// Non-negative byte offsets to advance one value cell along each dimension
- /// If omitted, default to row-major order (C-like).
- const flatbuffers::Vector<int64_t> *indicesStrides() const {
- return GetPointer<const flatbuffers::Vector<int64_t> *>(VT_INDICESSTRIDES);
- }
- /// The location and size of the indices matrix's data
- const org::apache::arrow::flatbuf::Buffer *indicesBuffer() const {
- return GetStruct<const org::apache::arrow::flatbuf::Buffer *>(VT_INDICESBUFFER);
- }
- /// The canonicality flag
- bool isCanonical() const {
- return GetField<uint8_t>(VT_ISCANONICAL, 0) != 0;
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyOffsetRequired(verifier, VT_INDICESTYPE) &&
- verifier.VerifyTable(indicesType()) &&
- VerifyOffset(verifier, VT_INDICESSTRIDES) &&
- verifier.VerifyVector(indicesStrides()) &&
- VerifyFieldRequired<org::apache::arrow::flatbuf::Buffer>(verifier, VT_INDICESBUFFER) &&
- VerifyField<uint8_t>(verifier, VT_ISCANONICAL) &&
- verifier.EndTable();
- }
-};
-
-struct SparseTensorIndexCOOBuilder {
- typedef SparseTensorIndexCOO Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_indicesType(flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indicesType) {
- fbb_.AddOffset(SparseTensorIndexCOO::VT_INDICESTYPE, indicesType);
- }
- void add_indicesStrides(flatbuffers::Offset<flatbuffers::Vector<int64_t>> indicesStrides) {
- fbb_.AddOffset(SparseTensorIndexCOO::VT_INDICESSTRIDES, indicesStrides);
- }
- void add_indicesBuffer(const org::apache::arrow::flatbuf::Buffer *indicesBuffer) {
- fbb_.AddStruct(SparseTensorIndexCOO::VT_INDICESBUFFER, indicesBuffer);
- }
- void add_isCanonical(bool isCanonical) {
- fbb_.AddElement<uint8_t>(SparseTensorIndexCOO::VT_ISCANONICAL, static_cast<uint8_t>(isCanonical), 0);
- }
- explicit SparseTensorIndexCOOBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- SparseTensorIndexCOOBuilder &operator=(const SparseTensorIndexCOOBuilder &);
- flatbuffers::Offset<SparseTensorIndexCOO> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<SparseTensorIndexCOO>(end);
- fbb_.Required(o, SparseTensorIndexCOO::VT_INDICESTYPE);
- fbb_.Required(o, SparseTensorIndexCOO::VT_INDICESBUFFER);
- return o;
- }
-};
-
-inline flatbuffers::Offset<SparseTensorIndexCOO> CreateSparseTensorIndexCOO(
- flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indicesType = 0,
- flatbuffers::Offset<flatbuffers::Vector<int64_t>> indicesStrides = 0,
- const org::apache::arrow::flatbuf::Buffer *indicesBuffer = 0,
- bool isCanonical = false) {
- SparseTensorIndexCOOBuilder builder_(_fbb);
- builder_.add_indicesBuffer(indicesBuffer);
- builder_.add_indicesStrides(indicesStrides);
- builder_.add_indicesType(indicesType);
- builder_.add_isCanonical(isCanonical);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<SparseTensorIndexCOO> CreateSparseTensorIndexCOODirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indicesType = 0,
- const std::vector<int64_t> *indicesStrides = nullptr,
- const org::apache::arrow::flatbuf::Buffer *indicesBuffer = 0,
- bool isCanonical = false) {
- auto indicesStrides__ = indicesStrides ? _fbb.CreateVector<int64_t>(*indicesStrides) : 0;
- return org::apache::arrow::flatbuf::CreateSparseTensorIndexCOO(
- _fbb,
- indicesType,
- indicesStrides__,
- indicesBuffer,
- isCanonical);
-}
-
-/// Compressed Sparse format, that is matrix-specific.
-struct SparseMatrixIndexCSX FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef SparseMatrixIndexCSXBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_COMPRESSEDAXIS = 4,
- VT_INDPTRTYPE = 6,
- VT_INDPTRBUFFER = 8,
- VT_INDICESTYPE = 10,
- VT_INDICESBUFFER = 12
- };
- /// Which axis, row or column, is compressed
- org::apache::arrow::flatbuf::SparseMatrixCompressedAxis compressedAxis() const {
- return static_cast<org::apache::arrow::flatbuf::SparseMatrixCompressedAxis>(GetField<int16_t>(VT_COMPRESSEDAXIS, 0));
- }
- /// The type of values in indptrBuffer
- const org::apache::arrow::flatbuf::Int *indptrType() const {
- return GetPointer<const org::apache::arrow::flatbuf::Int *>(VT_INDPTRTYPE);
- }
- /// indptrBuffer stores the location and size of indptr array that
- /// represents the range of the rows.
- /// The i-th row spans from indptr[i] to indptr[i+1] in the data.
- /// The length of this array is 1 + (the number of rows), and the type
- /// of index value is long.
- ///
- /// For example, let X be the following 6x4 matrix:
- ///
- /// X := [[0, 1, 2, 0],
- /// [0, 0, 3, 0],
- /// [0, 4, 0, 5],
- /// [0, 0, 0, 0],
- /// [6, 0, 7, 8],
- /// [0, 9, 0, 0]].
- ///
- /// The array of non-zero values in X is:
- ///
- /// values(X) = [1, 2, 3, 4, 5, 6, 7, 8, 9].
- ///
- /// And the indptr of X is:
- ///
- /// indptr(X) = [0, 2, 3, 5, 5, 8, 10].
- const org::apache::arrow::flatbuf::Buffer *indptrBuffer() const {
- return GetStruct<const org::apache::arrow::flatbuf::Buffer *>(VT_INDPTRBUFFER);
- }
- /// The type of values in indicesBuffer
- const org::apache::arrow::flatbuf::Int *indicesType() const {
- return GetPointer<const org::apache::arrow::flatbuf::Int *>(VT_INDICESTYPE);
- }
- /// indicesBuffer stores the location and size of the array that
- /// contains the column indices of the corresponding non-zero values.
- /// The type of index value is long.
- ///
- /// For example, the indices of the above X is:
- ///
- /// indices(X) = [1, 2, 2, 1, 3, 0, 2, 3, 1].
- ///
- /// Note that the indices are sorted in lexicographical order for each row.
- const org::apache::arrow::flatbuf::Buffer *indicesBuffer() const {
- return GetStruct<const org::apache::arrow::flatbuf::Buffer *>(VT_INDICESBUFFER);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int16_t>(verifier, VT_COMPRESSEDAXIS) &&
- VerifyOffsetRequired(verifier, VT_INDPTRTYPE) &&
- verifier.VerifyTable(indptrType()) &&
- VerifyFieldRequired<org::apache::arrow::flatbuf::Buffer>(verifier, VT_INDPTRBUFFER) &&
- VerifyOffsetRequired(verifier, VT_INDICESTYPE) &&
- verifier.VerifyTable(indicesType()) &&
- VerifyFieldRequired<org::apache::arrow::flatbuf::Buffer>(verifier, VT_INDICESBUFFER) &&
- verifier.EndTable();
- }
-};
-
-struct SparseMatrixIndexCSXBuilder {
- typedef SparseMatrixIndexCSX Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_compressedAxis(org::apache::arrow::flatbuf::SparseMatrixCompressedAxis compressedAxis) {
- fbb_.AddElement<int16_t>(SparseMatrixIndexCSX::VT_COMPRESSEDAXIS, static_cast<int16_t>(compressedAxis), 0);
- }
- void add_indptrType(flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indptrType) {
- fbb_.AddOffset(SparseMatrixIndexCSX::VT_INDPTRTYPE, indptrType);
- }
- void add_indptrBuffer(const org::apache::arrow::flatbuf::Buffer *indptrBuffer) {
- fbb_.AddStruct(SparseMatrixIndexCSX::VT_INDPTRBUFFER, indptrBuffer);
- }
- void add_indicesType(flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indicesType) {
- fbb_.AddOffset(SparseMatrixIndexCSX::VT_INDICESTYPE, indicesType);
- }
- void add_indicesBuffer(const org::apache::arrow::flatbuf::Buffer *indicesBuffer) {
- fbb_.AddStruct(SparseMatrixIndexCSX::VT_INDICESBUFFER, indicesBuffer);
- }
- explicit SparseMatrixIndexCSXBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- SparseMatrixIndexCSXBuilder &operator=(const SparseMatrixIndexCSXBuilder &);
- flatbuffers::Offset<SparseMatrixIndexCSX> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<SparseMatrixIndexCSX>(end);
- fbb_.Required(o, SparseMatrixIndexCSX::VT_INDPTRTYPE);
- fbb_.Required(o, SparseMatrixIndexCSX::VT_INDPTRBUFFER);
- fbb_.Required(o, SparseMatrixIndexCSX::VT_INDICESTYPE);
- fbb_.Required(o, SparseMatrixIndexCSX::VT_INDICESBUFFER);
- return o;
- }
-};
-
-inline flatbuffers::Offset<SparseMatrixIndexCSX> CreateSparseMatrixIndexCSX(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::SparseMatrixCompressedAxis compressedAxis = org::apache::arrow::flatbuf::SparseMatrixCompressedAxis::Row,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indptrType = 0,
- const org::apache::arrow::flatbuf::Buffer *indptrBuffer = 0,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indicesType = 0,
- const org::apache::arrow::flatbuf::Buffer *indicesBuffer = 0) {
- SparseMatrixIndexCSXBuilder builder_(_fbb);
- builder_.add_indicesBuffer(indicesBuffer);
- builder_.add_indicesType(indicesType);
- builder_.add_indptrBuffer(indptrBuffer);
- builder_.add_indptrType(indptrType);
- builder_.add_compressedAxis(compressedAxis);
- return builder_.Finish();
-}
-
-/// Compressed Sparse Fiber (CSF) sparse tensor index.
-struct SparseTensorIndexCSF FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef SparseTensorIndexCSFBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_INDPTRTYPE = 4,
- VT_INDPTRBUFFERS = 6,
- VT_INDICESTYPE = 8,
- VT_INDICESBUFFERS = 10,
- VT_AXISORDER = 12
- };
- /// CSF is a generalization of compressed sparse row (CSR) index.
- /// See [smith2017knl]: http://shaden.io/pub-files/smith2017knl.pdf
- ///
- /// CSF index recursively compresses each dimension of a tensor into a set
- /// of prefix trees. Each path from a root to leaf forms one tensor
- /// non-zero index. CSF is implemented with two arrays of buffers and one
- /// arrays of integers.
- ///
- /// For example, let X be a 2x3x4x5 tensor and let it have the following
- /// 8 non-zero values:
- ///
- /// X[0, 0, 0, 1] := 1
- /// X[0, 0, 0, 2] := 2
- /// X[0, 1, 0, 0] := 3
- /// X[0, 1, 0, 2] := 4
- /// X[0, 1, 1, 0] := 5
- /// X[1, 1, 1, 0] := 6
- /// X[1, 1, 1, 1] := 7
- /// X[1, 1, 1, 2] := 8
- ///
- /// As a prefix tree this would be represented as:
- ///
- /// 0 1
- /// / \ |
- /// 0 1 1
- /// / / \ |
- /// 0 0 1 1
- /// /| /| | /| |
- /// 1 2 0 2 0 0 1 2
- /// The type of values in indptrBuffers
- const org::apache::arrow::flatbuf::Int *indptrType() const {
- return GetPointer<const org::apache::arrow::flatbuf::Int *>(VT_INDPTRTYPE);
- }
- /// indptrBuffers stores the sparsity structure.
- /// Each two consecutive dimensions in a tensor correspond to a buffer in
- /// indptrBuffers. A pair of consecutive values at indptrBuffers[dim][i]
- /// and indptrBuffers[dim][i + 1] signify a range of nodes in
- /// indicesBuffers[dim + 1] who are children of indicesBuffers[dim][i] node.
- ///
- /// For example, the indptrBuffers for the above X is:
- ///
- /// indptrBuffer(X) = [
- /// [0, 2, 3],
- /// [0, 1, 3, 4],
- /// [0, 2, 4, 5, 8]
- /// ].
- ///
- const flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *> *indptrBuffers() const {
- return GetPointer<const flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *> *>(VT_INDPTRBUFFERS);
- }
- /// The type of values in indicesBuffers
- const org::apache::arrow::flatbuf::Int *indicesType() const {
- return GetPointer<const org::apache::arrow::flatbuf::Int *>(VT_INDICESTYPE);
- }
- /// indicesBuffers stores values of nodes.
- /// Each tensor dimension corresponds to a buffer in indicesBuffers.
- /// For example, the indicesBuffers for the above X is:
- ///
- /// indicesBuffer(X) = [
- /// [0, 1],
- /// [0, 1, 1],
- /// [0, 0, 1, 1],
- /// [1, 2, 0, 2, 0, 0, 1, 2]
- /// ].
- ///
- const flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *> *indicesBuffers() const {
- return GetPointer<const flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *> *>(VT_INDICESBUFFERS);
- }
- /// axisOrder stores the sequence in which dimensions were traversed to
- /// produce the prefix tree.
- /// For example, the axisOrder for the above X is:
- ///
- /// axisOrder(X) = [0, 1, 2, 3].
- ///
- const flatbuffers::Vector<int32_t> *axisOrder() const {
- return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_AXISORDER);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyOffsetRequired(verifier, VT_INDPTRTYPE) &&
- verifier.VerifyTable(indptrType()) &&
- VerifyOffsetRequired(verifier, VT_INDPTRBUFFERS) &&
- verifier.VerifyVector(indptrBuffers()) &&
- VerifyOffsetRequired(verifier, VT_INDICESTYPE) &&
- verifier.VerifyTable(indicesType()) &&
- VerifyOffsetRequired(verifier, VT_INDICESBUFFERS) &&
- verifier.VerifyVector(indicesBuffers()) &&
- VerifyOffsetRequired(verifier, VT_AXISORDER) &&
- verifier.VerifyVector(axisOrder()) &&
- verifier.EndTable();
- }
-};
-
-struct SparseTensorIndexCSFBuilder {
- typedef SparseTensorIndexCSF Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_indptrType(flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indptrType) {
- fbb_.AddOffset(SparseTensorIndexCSF::VT_INDPTRTYPE, indptrType);
- }
- void add_indptrBuffers(flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *>> indptrBuffers) {
- fbb_.AddOffset(SparseTensorIndexCSF::VT_INDPTRBUFFERS, indptrBuffers);
- }
- void add_indicesType(flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indicesType) {
- fbb_.AddOffset(SparseTensorIndexCSF::VT_INDICESTYPE, indicesType);
- }
- void add_indicesBuffers(flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *>> indicesBuffers) {
- fbb_.AddOffset(SparseTensorIndexCSF::VT_INDICESBUFFERS, indicesBuffers);
- }
- void add_axisOrder(flatbuffers::Offset<flatbuffers::Vector<int32_t>> axisOrder) {
- fbb_.AddOffset(SparseTensorIndexCSF::VT_AXISORDER, axisOrder);
- }
- explicit SparseTensorIndexCSFBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- SparseTensorIndexCSFBuilder &operator=(const SparseTensorIndexCSFBuilder &);
- flatbuffers::Offset<SparseTensorIndexCSF> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<SparseTensorIndexCSF>(end);
- fbb_.Required(o, SparseTensorIndexCSF::VT_INDPTRTYPE);
- fbb_.Required(o, SparseTensorIndexCSF::VT_INDPTRBUFFERS);
- fbb_.Required(o, SparseTensorIndexCSF::VT_INDICESTYPE);
- fbb_.Required(o, SparseTensorIndexCSF::VT_INDICESBUFFERS);
- fbb_.Required(o, SparseTensorIndexCSF::VT_AXISORDER);
- return o;
- }
-};
-
-inline flatbuffers::Offset<SparseTensorIndexCSF> CreateSparseTensorIndexCSF(
- flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indptrType = 0,
- flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *>> indptrBuffers = 0,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indicesType = 0,
- flatbuffers::Offset<flatbuffers::Vector<const org::apache::arrow::flatbuf::Buffer *>> indicesBuffers = 0,
- flatbuffers::Offset<flatbuffers::Vector<int32_t>> axisOrder = 0) {
- SparseTensorIndexCSFBuilder builder_(_fbb);
- builder_.add_axisOrder(axisOrder);
- builder_.add_indicesBuffers(indicesBuffers);
- builder_.add_indicesType(indicesType);
- builder_.add_indptrBuffers(indptrBuffers);
- builder_.add_indptrType(indptrType);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<SparseTensorIndexCSF> CreateSparseTensorIndexCSFDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indptrType = 0,
- const std::vector<org::apache::arrow::flatbuf::Buffer> *indptrBuffers = nullptr,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Int> indicesType = 0,
- const std::vector<org::apache::arrow::flatbuf::Buffer> *indicesBuffers = nullptr,
- const std::vector<int32_t> *axisOrder = nullptr) {
- auto indptrBuffers__ = indptrBuffers ? _fbb.CreateVectorOfStructs<org::apache::arrow::flatbuf::Buffer>(*indptrBuffers) : 0;
- auto indicesBuffers__ = indicesBuffers ? _fbb.CreateVectorOfStructs<org::apache::arrow::flatbuf::Buffer>(*indicesBuffers) : 0;
- auto axisOrder__ = axisOrder ? _fbb.CreateVector<int32_t>(*axisOrder) : 0;
- return org::apache::arrow::flatbuf::CreateSparseTensorIndexCSF(
- _fbb,
- indptrType,
- indptrBuffers__,
- indicesType,
- indicesBuffers__,
- axisOrder__);
-}
-
-struct SparseTensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef SparseTensorBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_TYPE_TYPE = 4,
- VT_TYPE = 6,
- VT_SHAPE = 8,
- VT_NON_ZERO_LENGTH = 10,
- VT_SPARSEINDEX_TYPE = 12,
- VT_SPARSEINDEX = 14,
- VT_DATA = 16
- };
- org::apache::arrow::flatbuf::Type type_type() const {
- return static_cast<org::apache::arrow::flatbuf::Type>(GetField<uint8_t>(VT_TYPE_TYPE, 0));
- }
- /// The type of data contained in a value cell.
- /// Currently only fixed-width value types are supported,
- /// no strings or nested types.
- const void *type() const {
- return GetPointer<const void *>(VT_TYPE);
- }
- template<typename T> const T *type_as() const;
- const org::apache::arrow::flatbuf::Null *type_as_Null() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Null ? static_cast<const org::apache::arrow::flatbuf::Null *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Int *type_as_Int() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Int ? static_cast<const org::apache::arrow::flatbuf::Int *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::FloatingPoint *type_as_FloatingPoint() const {
- return type_type() == org::apache::arrow::flatbuf::Type::FloatingPoint ? static_cast<const org::apache::arrow::flatbuf::FloatingPoint *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Binary *type_as_Binary() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Binary ? static_cast<const org::apache::arrow::flatbuf::Binary *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Utf8 *type_as_Utf8() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Utf8 ? static_cast<const org::apache::arrow::flatbuf::Utf8 *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Bool *type_as_Bool() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Bool ? static_cast<const org::apache::arrow::flatbuf::Bool *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Decimal *type_as_Decimal() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Decimal ? static_cast<const org::apache::arrow::flatbuf::Decimal *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Date *type_as_Date() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Date ? static_cast<const org::apache::arrow::flatbuf::Date *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Time *type_as_Time() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Time ? static_cast<const org::apache::arrow::flatbuf::Time *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Timestamp *type_as_Timestamp() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Timestamp ? static_cast<const org::apache::arrow::flatbuf::Timestamp *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Interval *type_as_Interval() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Interval ? static_cast<const org::apache::arrow::flatbuf::Interval *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::List *type_as_List() const {
- return type_type() == org::apache::arrow::flatbuf::Type::List ? static_cast<const org::apache::arrow::flatbuf::List *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Struct_ *type_as_Struct_() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Struct_ ? static_cast<const org::apache::arrow::flatbuf::Struct_ *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Union *type_as_Union() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Union ? static_cast<const org::apache::arrow::flatbuf::Union *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::FixedSizeBinary *type_as_FixedSizeBinary() const {
- return type_type() == org::apache::arrow::flatbuf::Type::FixedSizeBinary ? static_cast<const org::apache::arrow::flatbuf::FixedSizeBinary *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::FixedSizeList *type_as_FixedSizeList() const {
- return type_type() == org::apache::arrow::flatbuf::Type::FixedSizeList ? static_cast<const org::apache::arrow::flatbuf::FixedSizeList *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Map *type_as_Map() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Map ? static_cast<const org::apache::arrow::flatbuf::Map *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Duration *type_as_Duration() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Duration ? static_cast<const org::apache::arrow::flatbuf::Duration *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::LargeBinary *type_as_LargeBinary() const {
- return type_type() == org::apache::arrow::flatbuf::Type::LargeBinary ? static_cast<const org::apache::arrow::flatbuf::LargeBinary *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::LargeUtf8 *type_as_LargeUtf8() const {
- return type_type() == org::apache::arrow::flatbuf::Type::LargeUtf8 ? static_cast<const org::apache::arrow::flatbuf::LargeUtf8 *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::LargeList *type_as_LargeList() const {
- return type_type() == org::apache::arrow::flatbuf::Type::LargeList ? static_cast<const org::apache::arrow::flatbuf::LargeList *>(type()) : nullptr;
- }
- /// The dimensions of the tensor, optionally named.
- const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>> *shape() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>> *>(VT_SHAPE);
- }
- /// The number of non-zero values in a sparse tensor.
- int64_t non_zero_length() const {
- return GetField<int64_t>(VT_NON_ZERO_LENGTH, 0);
- }
- org::apache::arrow::flatbuf::SparseTensorIndex sparseIndex_type() const {
- return static_cast<org::apache::arrow::flatbuf::SparseTensorIndex>(GetField<uint8_t>(VT_SPARSEINDEX_TYPE, 0));
- }
- /// Sparse tensor index
- const void *sparseIndex() const {
- return GetPointer<const void *>(VT_SPARSEINDEX);
- }
- template<typename T> const T *sparseIndex_as() const;
- const org::apache::arrow::flatbuf::SparseTensorIndexCOO *sparseIndex_as_SparseTensorIndexCOO() const {
- return sparseIndex_type() == org::apache::arrow::flatbuf::SparseTensorIndex::SparseTensorIndexCOO ? static_cast<const org::apache::arrow::flatbuf::SparseTensorIndexCOO *>(sparseIndex()) : nullptr;
- }
- const org::apache::arrow::flatbuf::SparseMatrixIndexCSX *sparseIndex_as_SparseMatrixIndexCSX() const {
- return sparseIndex_type() == org::apache::arrow::flatbuf::SparseTensorIndex::SparseMatrixIndexCSX ? static_cast<const org::apache::arrow::flatbuf::SparseMatrixIndexCSX *>(sparseIndex()) : nullptr;
- }
- const org::apache::arrow::flatbuf::SparseTensorIndexCSF *sparseIndex_as_SparseTensorIndexCSF() const {
- return sparseIndex_type() == org::apache::arrow::flatbuf::SparseTensorIndex::SparseTensorIndexCSF ? static_cast<const org::apache::arrow::flatbuf::SparseTensorIndexCSF *>(sparseIndex()) : nullptr;
- }
- /// The location and size of the tensor's data
- const org::apache::arrow::flatbuf::Buffer *data() const {
- return GetStruct<const org::apache::arrow::flatbuf::Buffer *>(VT_DATA);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<uint8_t>(verifier, VT_TYPE_TYPE) &&
- VerifyOffsetRequired(verifier, VT_TYPE) &&
- VerifyType(verifier, type(), type_type()) &&
- VerifyOffsetRequired(verifier, VT_SHAPE) &&
- verifier.VerifyVector(shape()) &&
- verifier.VerifyVectorOfTables(shape()) &&
- VerifyField<int64_t>(verifier, VT_NON_ZERO_LENGTH) &&
- VerifyField<uint8_t>(verifier, VT_SPARSEINDEX_TYPE) &&
- VerifyOffsetRequired(verifier, VT_SPARSEINDEX) &&
- VerifySparseTensorIndex(verifier, sparseIndex(), sparseIndex_type()) &&
- VerifyFieldRequired<org::apache::arrow::flatbuf::Buffer>(verifier, VT_DATA) &&
- verifier.EndTable();
- }
-};
-
-template<> inline const org::apache::arrow::flatbuf::Null *SparseTensor::type_as<org::apache::arrow::flatbuf::Null>() const {
- return type_as_Null();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Int *SparseTensor::type_as<org::apache::arrow::flatbuf::Int>() const {
- return type_as_Int();
-}
-
-template<> inline const org::apache::arrow::flatbuf::FloatingPoint *SparseTensor::type_as<org::apache::arrow::flatbuf::FloatingPoint>() const {
- return type_as_FloatingPoint();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Binary *SparseTensor::type_as<org::apache::arrow::flatbuf::Binary>() const {
- return type_as_Binary();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Utf8 *SparseTensor::type_as<org::apache::arrow::flatbuf::Utf8>() const {
- return type_as_Utf8();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Bool *SparseTensor::type_as<org::apache::arrow::flatbuf::Bool>() const {
- return type_as_Bool();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Decimal *SparseTensor::type_as<org::apache::arrow::flatbuf::Decimal>() const {
- return type_as_Decimal();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Date *SparseTensor::type_as<org::apache::arrow::flatbuf::Date>() const {
- return type_as_Date();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Time *SparseTensor::type_as<org::apache::arrow::flatbuf::Time>() const {
- return type_as_Time();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Timestamp *SparseTensor::type_as<org::apache::arrow::flatbuf::Timestamp>() const {
- return type_as_Timestamp();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Interval *SparseTensor::type_as<org::apache::arrow::flatbuf::Interval>() const {
- return type_as_Interval();
-}
-
-template<> inline const org::apache::arrow::flatbuf::List *SparseTensor::type_as<org::apache::arrow::flatbuf::List>() const {
- return type_as_List();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Struct_ *SparseTensor::type_as<org::apache::arrow::flatbuf::Struct_>() const {
- return type_as_Struct_();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Union *SparseTensor::type_as<org::apache::arrow::flatbuf::Union>() const {
- return type_as_Union();
-}
-
-template<> inline const org::apache::arrow::flatbuf::FixedSizeBinary *SparseTensor::type_as<org::apache::arrow::flatbuf::FixedSizeBinary>() const {
- return type_as_FixedSizeBinary();
-}
-
-template<> inline const org::apache::arrow::flatbuf::FixedSizeList *SparseTensor::type_as<org::apache::arrow::flatbuf::FixedSizeList>() const {
- return type_as_FixedSizeList();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Map *SparseTensor::type_as<org::apache::arrow::flatbuf::Map>() const {
- return type_as_Map();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Duration *SparseTensor::type_as<org::apache::arrow::flatbuf::Duration>() const {
- return type_as_Duration();
-}
-
-template<> inline const org::apache::arrow::flatbuf::LargeBinary *SparseTensor::type_as<org::apache::arrow::flatbuf::LargeBinary>() const {
- return type_as_LargeBinary();
-}
-
-template<> inline const org::apache::arrow::flatbuf::LargeUtf8 *SparseTensor::type_as<org::apache::arrow::flatbuf::LargeUtf8>() const {
- return type_as_LargeUtf8();
-}
-
-template<> inline const org::apache::arrow::flatbuf::LargeList *SparseTensor::type_as<org::apache::arrow::flatbuf::LargeList>() const {
- return type_as_LargeList();
-}
-
-template<> inline const org::apache::arrow::flatbuf::SparseTensorIndexCOO *SparseTensor::sparseIndex_as<org::apache::arrow::flatbuf::SparseTensorIndexCOO>() const {
- return sparseIndex_as_SparseTensorIndexCOO();
-}
-
-template<> inline const org::apache::arrow::flatbuf::SparseMatrixIndexCSX *SparseTensor::sparseIndex_as<org::apache::arrow::flatbuf::SparseMatrixIndexCSX>() const {
- return sparseIndex_as_SparseMatrixIndexCSX();
-}
-
-template<> inline const org::apache::arrow::flatbuf::SparseTensorIndexCSF *SparseTensor::sparseIndex_as<org::apache::arrow::flatbuf::SparseTensorIndexCSF>() const {
- return sparseIndex_as_SparseTensorIndexCSF();
-}
-
-struct SparseTensorBuilder {
- typedef SparseTensor Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_type_type(org::apache::arrow::flatbuf::Type type_type) {
- fbb_.AddElement<uint8_t>(SparseTensor::VT_TYPE_TYPE, static_cast<uint8_t>(type_type), 0);
- }
- void add_type(flatbuffers::Offset<void> type) {
- fbb_.AddOffset(SparseTensor::VT_TYPE, type);
- }
- void add_shape(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>>> shape) {
- fbb_.AddOffset(SparseTensor::VT_SHAPE, shape);
- }
- void add_non_zero_length(int64_t non_zero_length) {
- fbb_.AddElement<int64_t>(SparseTensor::VT_NON_ZERO_LENGTH, non_zero_length, 0);
- }
- void add_sparseIndex_type(org::apache::arrow::flatbuf::SparseTensorIndex sparseIndex_type) {
- fbb_.AddElement<uint8_t>(SparseTensor::VT_SPARSEINDEX_TYPE, static_cast<uint8_t>(sparseIndex_type), 0);
- }
- void add_sparseIndex(flatbuffers::Offset<void> sparseIndex) {
- fbb_.AddOffset(SparseTensor::VT_SPARSEINDEX, sparseIndex);
- }
- void add_data(const org::apache::arrow::flatbuf::Buffer *data) {
- fbb_.AddStruct(SparseTensor::VT_DATA, data);
- }
- explicit SparseTensorBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- SparseTensorBuilder &operator=(const SparseTensorBuilder &);
- flatbuffers::Offset<SparseTensor> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<SparseTensor>(end);
- fbb_.Required(o, SparseTensor::VT_TYPE);
- fbb_.Required(o, SparseTensor::VT_SHAPE);
- fbb_.Required(o, SparseTensor::VT_SPARSEINDEX);
- fbb_.Required(o, SparseTensor::VT_DATA);
- return o;
- }
-};
-
-inline flatbuffers::Offset<SparseTensor> CreateSparseTensor(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::Type type_type = org::apache::arrow::flatbuf::Type::NONE,
- flatbuffers::Offset<void> type = 0,
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>>> shape = 0,
- int64_t non_zero_length = 0,
- org::apache::arrow::flatbuf::SparseTensorIndex sparseIndex_type = org::apache::arrow::flatbuf::SparseTensorIndex::NONE,
- flatbuffers::Offset<void> sparseIndex = 0,
- const org::apache::arrow::flatbuf::Buffer *data = 0) {
- SparseTensorBuilder builder_(_fbb);
- builder_.add_non_zero_length(non_zero_length);
- builder_.add_data(data);
- builder_.add_sparseIndex(sparseIndex);
- builder_.add_shape(shape);
- builder_.add_type(type);
- builder_.add_sparseIndex_type(sparseIndex_type);
- builder_.add_type_type(type_type);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<SparseTensor> CreateSparseTensorDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::Type type_type = org::apache::arrow::flatbuf::Type::NONE,
- flatbuffers::Offset<void> type = 0,
- const std::vector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>> *shape = nullptr,
- int64_t non_zero_length = 0,
- org::apache::arrow::flatbuf::SparseTensorIndex sparseIndex_type = org::apache::arrow::flatbuf::SparseTensorIndex::NONE,
- flatbuffers::Offset<void> sparseIndex = 0,
- const org::apache::arrow::flatbuf::Buffer *data = 0) {
- auto shape__ = shape ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>>(*shape) : 0;
- return org::apache::arrow::flatbuf::CreateSparseTensor(
- _fbb,
- type_type,
- type,
- shape__,
- non_zero_length,
- sparseIndex_type,
- sparseIndex,
- data);
-}
-
-inline bool VerifySparseTensorIndex(flatbuffers::Verifier &verifier, const void *obj, SparseTensorIndex type) {
- switch (type) {
- case SparseTensorIndex::NONE: {
- return true;
- }
- case SparseTensorIndex::SparseTensorIndexCOO: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::SparseTensorIndexCOO *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case SparseTensorIndex::SparseMatrixIndexCSX: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::SparseMatrixIndexCSX *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case SparseTensorIndex::SparseTensorIndexCSF: {
- auto ptr = reinterpret_cast<const org::apache::arrow::flatbuf::SparseTensorIndexCSF *>(obj);
- return verifier.VerifyTable(ptr);
- }
- default: return true;
- }
-}
-
-inline bool VerifySparseTensorIndexVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
- if (!values || !types) return !values && !types;
- if (values->size() != types->size()) return false;
- for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
- if (!VerifySparseTensorIndex(
- verifier, values->Get(i), types->GetEnum<SparseTensorIndex>(i))) {
- return false;
- }
- }
- return true;
-}
-
-inline const org::apache::arrow::flatbuf::SparseTensor *GetSparseTensor(const void *buf) {
- return flatbuffers::GetRoot<org::apache::arrow::flatbuf::SparseTensor>(buf);
-}
-
-inline const org::apache::arrow::flatbuf::SparseTensor *GetSizePrefixedSparseTensor(const void *buf) {
- return flatbuffers::GetSizePrefixedRoot<org::apache::arrow::flatbuf::SparseTensor>(buf);
-}
-
-inline bool VerifySparseTensorBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifyBuffer<org::apache::arrow::flatbuf::SparseTensor>(nullptr);
-}
-
-inline bool VerifySizePrefixedSparseTensorBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifySizePrefixedBuffer<org::apache::arrow::flatbuf::SparseTensor>(nullptr);
-}
-
-inline void FinishSparseTensorBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::SparseTensor> root) {
- fbb.Finish(root);
-}
-
-inline void FinishSizePrefixedSparseTensorBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::SparseTensor> root) {
- fbb.FinishSizePrefixed(root);
-}
-
-} // namespace flatbuf
-} // namespace arrow
-} // namespace apache
-} // namespace org
-
-#endif // FLATBUFFERS_GENERATED_SPARSETENSOR_ORG_APACHE_ARROW_FLATBUF_H_
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs b/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs
new file mode 100644
index 0000000000..409297ccf8
--- /dev/null
+++ b/contrib/libs/apache/arrow/cpp/src/generated/Tensor.fbs
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.
+
+/// EXPERIMENTAL: Metadata for n-dimensional arrays, aka "tensors" or
+/// "ndarrays". Arrow implementations in general are not required to implement
+/// this type
+
+include "Schema.fbs";
+
+namespace org.apache.arrow.flatbuf;
+
+/// ----------------------------------------------------------------------
+/// Data structures for dense tensors
+
+/// Shape data for a single axis in a tensor
+table TensorDim {
+ /// Length of dimension
+ size: long;
+
+ /// Name of the dimension, optional
+ name: string;
+}
+
+table Tensor {
+ /// The type of data contained in a value cell. Currently only fixed-width
+ /// value types are supported, no strings or nested types
+ type: Type (required);
+
+ /// The dimensions of the tensor, optionally named
+ shape: [TensorDim] (required);
+
+ /// Non-negative byte offsets to advance one value cell along each dimension
+ /// If omitted, default to row-major order (C-like).
+ strides: [long];
+
+ /// The location and size of the tensor's data
+ data: Buffer (required);
+}
+
+root_type Tensor;
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/Tensor_generated.h b/contrib/libs/apache/arrow/cpp/src/generated/Tensor_generated.h
deleted file mode 100644
index 062a3b91aa..0000000000
--- a/contrib/libs/apache/arrow/cpp/src/generated/Tensor_generated.h
+++ /dev/null
@@ -1,387 +0,0 @@
-// automatically generated by the FlatBuffers compiler, do not modify
-
-
-#ifndef FLATBUFFERS_GENERATED_TENSOR_ORG_APACHE_ARROW_FLATBUF_H_
-#define FLATBUFFERS_GENERATED_TENSOR_ORG_APACHE_ARROW_FLATBUF_H_
-
-#include "flatbuffers/flatbuffers.h"
-
-#include "Schema_generated.h"
-
-namespace org {
-namespace apache {
-namespace arrow {
-namespace flatbuf {
-
-struct TensorDim;
-struct TensorDimBuilder;
-
-struct Tensor;
-struct TensorBuilder;
-
-/// ----------------------------------------------------------------------
-/// Data structures for dense tensors
-/// Shape data for a single axis in a tensor
-struct TensorDim FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef TensorDimBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_SIZE = 4,
- VT_NAME = 6
- };
- /// Length of dimension
- int64_t size() const {
- return GetField<int64_t>(VT_SIZE, 0);
- }
- /// Name of the dimension, optional
- const flatbuffers::String *name() const {
- return GetPointer<const flatbuffers::String *>(VT_NAME);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int64_t>(verifier, VT_SIZE) &&
- VerifyOffset(verifier, VT_NAME) &&
- verifier.VerifyString(name()) &&
- verifier.EndTable();
- }
-};
-
-struct TensorDimBuilder {
- typedef TensorDim Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_size(int64_t size) {
- fbb_.AddElement<int64_t>(TensorDim::VT_SIZE, size, 0);
- }
- void add_name(flatbuffers::Offset<flatbuffers::String> name) {
- fbb_.AddOffset(TensorDim::VT_NAME, name);
- }
- explicit TensorDimBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- TensorDimBuilder &operator=(const TensorDimBuilder &);
- flatbuffers::Offset<TensorDim> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<TensorDim>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<TensorDim> CreateTensorDim(
- flatbuffers::FlatBufferBuilder &_fbb,
- int64_t size = 0,
- flatbuffers::Offset<flatbuffers::String> name = 0) {
- TensorDimBuilder builder_(_fbb);
- builder_.add_size(size);
- builder_.add_name(name);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<TensorDim> CreateTensorDimDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- int64_t size = 0,
- const char *name = nullptr) {
- auto name__ = name ? _fbb.CreateString(name) : 0;
- return org::apache::arrow::flatbuf::CreateTensorDim(
- _fbb,
- size,
- name__);
-}
-
-struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef TensorBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_TYPE_TYPE = 4,
- VT_TYPE = 6,
- VT_SHAPE = 8,
- VT_STRIDES = 10,
- VT_DATA = 12
- };
- org::apache::arrow::flatbuf::Type type_type() const {
- return static_cast<org::apache::arrow::flatbuf::Type>(GetField<uint8_t>(VT_TYPE_TYPE, 0));
- }
- /// The type of data contained in a value cell. Currently only fixed-width
- /// value types are supported, no strings or nested types
- const void *type() const {
- return GetPointer<const void *>(VT_TYPE);
- }
- template<typename T> const T *type_as() const;
- const org::apache::arrow::flatbuf::Null *type_as_Null() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Null ? static_cast<const org::apache::arrow::flatbuf::Null *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Int *type_as_Int() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Int ? static_cast<const org::apache::arrow::flatbuf::Int *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::FloatingPoint *type_as_FloatingPoint() const {
- return type_type() == org::apache::arrow::flatbuf::Type::FloatingPoint ? static_cast<const org::apache::arrow::flatbuf::FloatingPoint *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Binary *type_as_Binary() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Binary ? static_cast<const org::apache::arrow::flatbuf::Binary *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Utf8 *type_as_Utf8() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Utf8 ? static_cast<const org::apache::arrow::flatbuf::Utf8 *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Bool *type_as_Bool() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Bool ? static_cast<const org::apache::arrow::flatbuf::Bool *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Decimal *type_as_Decimal() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Decimal ? static_cast<const org::apache::arrow::flatbuf::Decimal *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Date *type_as_Date() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Date ? static_cast<const org::apache::arrow::flatbuf::Date *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Time *type_as_Time() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Time ? static_cast<const org::apache::arrow::flatbuf::Time *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Timestamp *type_as_Timestamp() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Timestamp ? static_cast<const org::apache::arrow::flatbuf::Timestamp *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Interval *type_as_Interval() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Interval ? static_cast<const org::apache::arrow::flatbuf::Interval *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::List *type_as_List() const {
- return type_type() == org::apache::arrow::flatbuf::Type::List ? static_cast<const org::apache::arrow::flatbuf::List *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Struct_ *type_as_Struct_() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Struct_ ? static_cast<const org::apache::arrow::flatbuf::Struct_ *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Union *type_as_Union() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Union ? static_cast<const org::apache::arrow::flatbuf::Union *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::FixedSizeBinary *type_as_FixedSizeBinary() const {
- return type_type() == org::apache::arrow::flatbuf::Type::FixedSizeBinary ? static_cast<const org::apache::arrow::flatbuf::FixedSizeBinary *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::FixedSizeList *type_as_FixedSizeList() const {
- return type_type() == org::apache::arrow::flatbuf::Type::FixedSizeList ? static_cast<const org::apache::arrow::flatbuf::FixedSizeList *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Map *type_as_Map() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Map ? static_cast<const org::apache::arrow::flatbuf::Map *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::Duration *type_as_Duration() const {
- return type_type() == org::apache::arrow::flatbuf::Type::Duration ? static_cast<const org::apache::arrow::flatbuf::Duration *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::LargeBinary *type_as_LargeBinary() const {
- return type_type() == org::apache::arrow::flatbuf::Type::LargeBinary ? static_cast<const org::apache::arrow::flatbuf::LargeBinary *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::LargeUtf8 *type_as_LargeUtf8() const {
- return type_type() == org::apache::arrow::flatbuf::Type::LargeUtf8 ? static_cast<const org::apache::arrow::flatbuf::LargeUtf8 *>(type()) : nullptr;
- }
- const org::apache::arrow::flatbuf::LargeList *type_as_LargeList() const {
- return type_type() == org::apache::arrow::flatbuf::Type::LargeList ? static_cast<const org::apache::arrow::flatbuf::LargeList *>(type()) : nullptr;
- }
- /// The dimensions of the tensor, optionally named
- const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>> *shape() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>> *>(VT_SHAPE);
- }
- /// Non-negative byte offsets to advance one value cell along each dimension
- /// If omitted, default to row-major order (C-like).
- const flatbuffers::Vector<int64_t> *strides() const {
- return GetPointer<const flatbuffers::Vector<int64_t> *>(VT_STRIDES);
- }
- /// The location and size of the tensor's data
- const org::apache::arrow::flatbuf::Buffer *data() const {
- return GetStruct<const org::apache::arrow::flatbuf::Buffer *>(VT_DATA);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<uint8_t>(verifier, VT_TYPE_TYPE) &&
- VerifyOffsetRequired(verifier, VT_TYPE) &&
- VerifyType(verifier, type(), type_type()) &&
- VerifyOffsetRequired(verifier, VT_SHAPE) &&
- verifier.VerifyVector(shape()) &&
- verifier.VerifyVectorOfTables(shape()) &&
- VerifyOffset(verifier, VT_STRIDES) &&
- verifier.VerifyVector(strides()) &&
- VerifyFieldRequired<org::apache::arrow::flatbuf::Buffer>(verifier, VT_DATA) &&
- verifier.EndTable();
- }
-};
-
-template<> inline const org::apache::arrow::flatbuf::Null *Tensor::type_as<org::apache::arrow::flatbuf::Null>() const {
- return type_as_Null();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Int *Tensor::type_as<org::apache::arrow::flatbuf::Int>() const {
- return type_as_Int();
-}
-
-template<> inline const org::apache::arrow::flatbuf::FloatingPoint *Tensor::type_as<org::apache::arrow::flatbuf::FloatingPoint>() const {
- return type_as_FloatingPoint();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Binary *Tensor::type_as<org::apache::arrow::flatbuf::Binary>() const {
- return type_as_Binary();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Utf8 *Tensor::type_as<org::apache::arrow::flatbuf::Utf8>() const {
- return type_as_Utf8();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Bool *Tensor::type_as<org::apache::arrow::flatbuf::Bool>() const {
- return type_as_Bool();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Decimal *Tensor::type_as<org::apache::arrow::flatbuf::Decimal>() const {
- return type_as_Decimal();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Date *Tensor::type_as<org::apache::arrow::flatbuf::Date>() const {
- return type_as_Date();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Time *Tensor::type_as<org::apache::arrow::flatbuf::Time>() const {
- return type_as_Time();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Timestamp *Tensor::type_as<org::apache::arrow::flatbuf::Timestamp>() const {
- return type_as_Timestamp();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Interval *Tensor::type_as<org::apache::arrow::flatbuf::Interval>() const {
- return type_as_Interval();
-}
-
-template<> inline const org::apache::arrow::flatbuf::List *Tensor::type_as<org::apache::arrow::flatbuf::List>() const {
- return type_as_List();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Struct_ *Tensor::type_as<org::apache::arrow::flatbuf::Struct_>() const {
- return type_as_Struct_();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Union *Tensor::type_as<org::apache::arrow::flatbuf::Union>() const {
- return type_as_Union();
-}
-
-template<> inline const org::apache::arrow::flatbuf::FixedSizeBinary *Tensor::type_as<org::apache::arrow::flatbuf::FixedSizeBinary>() const {
- return type_as_FixedSizeBinary();
-}
-
-template<> inline const org::apache::arrow::flatbuf::FixedSizeList *Tensor::type_as<org::apache::arrow::flatbuf::FixedSizeList>() const {
- return type_as_FixedSizeList();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Map *Tensor::type_as<org::apache::arrow::flatbuf::Map>() const {
- return type_as_Map();
-}
-
-template<> inline const org::apache::arrow::flatbuf::Duration *Tensor::type_as<org::apache::arrow::flatbuf::Duration>() const {
- return type_as_Duration();
-}
-
-template<> inline const org::apache::arrow::flatbuf::LargeBinary *Tensor::type_as<org::apache::arrow::flatbuf::LargeBinary>() const {
- return type_as_LargeBinary();
-}
-
-template<> inline const org::apache::arrow::flatbuf::LargeUtf8 *Tensor::type_as<org::apache::arrow::flatbuf::LargeUtf8>() const {
- return type_as_LargeUtf8();
-}
-
-template<> inline const org::apache::arrow::flatbuf::LargeList *Tensor::type_as<org::apache::arrow::flatbuf::LargeList>() const {
- return type_as_LargeList();
-}
-
-struct TensorBuilder {
- typedef Tensor Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_type_type(org::apache::arrow::flatbuf::Type type_type) {
- fbb_.AddElement<uint8_t>(Tensor::VT_TYPE_TYPE, static_cast<uint8_t>(type_type), 0);
- }
- void add_type(flatbuffers::Offset<void> type) {
- fbb_.AddOffset(Tensor::VT_TYPE, type);
- }
- void add_shape(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>>> shape) {
- fbb_.AddOffset(Tensor::VT_SHAPE, shape);
- }
- void add_strides(flatbuffers::Offset<flatbuffers::Vector<int64_t>> strides) {
- fbb_.AddOffset(Tensor::VT_STRIDES, strides);
- }
- void add_data(const org::apache::arrow::flatbuf::Buffer *data) {
- fbb_.AddStruct(Tensor::VT_DATA, data);
- }
- explicit TensorBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- TensorBuilder &operator=(const TensorBuilder &);
- flatbuffers::Offset<Tensor> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Tensor>(end);
- fbb_.Required(o, Tensor::VT_TYPE);
- fbb_.Required(o, Tensor::VT_SHAPE);
- fbb_.Required(o, Tensor::VT_DATA);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Tensor> CreateTensor(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::Type type_type = org::apache::arrow::flatbuf::Type::NONE,
- flatbuffers::Offset<void> type = 0,
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>>> shape = 0,
- flatbuffers::Offset<flatbuffers::Vector<int64_t>> strides = 0,
- const org::apache::arrow::flatbuf::Buffer *data = 0) {
- TensorBuilder builder_(_fbb);
- builder_.add_data(data);
- builder_.add_strides(strides);
- builder_.add_shape(shape);
- builder_.add_type(type);
- builder_.add_type_type(type_type);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<Tensor> CreateTensorDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- org::apache::arrow::flatbuf::Type type_type = org::apache::arrow::flatbuf::Type::NONE,
- flatbuffers::Offset<void> type = 0,
- const std::vector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>> *shape = nullptr,
- const std::vector<int64_t> *strides = nullptr,
- const org::apache::arrow::flatbuf::Buffer *data = 0) {
- auto shape__ = shape ? _fbb.CreateVector<flatbuffers::Offset<org::apache::arrow::flatbuf::TensorDim>>(*shape) : 0;
- auto strides__ = strides ? _fbb.CreateVector<int64_t>(*strides) : 0;
- return org::apache::arrow::flatbuf::CreateTensor(
- _fbb,
- type_type,
- type,
- shape__,
- strides__,
- data);
-}
-
-inline const org::apache::arrow::flatbuf::Tensor *GetTensor(const void *buf) {
- return flatbuffers::GetRoot<org::apache::arrow::flatbuf::Tensor>(buf);
-}
-
-inline const org::apache::arrow::flatbuf::Tensor *GetSizePrefixedTensor(const void *buf) {
- return flatbuffers::GetSizePrefixedRoot<org::apache::arrow::flatbuf::Tensor>(buf);
-}
-
-inline bool VerifyTensorBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifyBuffer<org::apache::arrow::flatbuf::Tensor>(nullptr);
-}
-
-inline bool VerifySizePrefixedTensorBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifySizePrefixedBuffer<org::apache::arrow::flatbuf::Tensor>(nullptr);
-}
-
-inline void FinishTensorBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Tensor> root) {
- fbb.Finish(root);
-}
-
-inline void FinishSizePrefixedTensorBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<org::apache::arrow::flatbuf::Tensor> root) {
- fbb.FinishSizePrefixed(root);
-}
-
-} // namespace flatbuf
-} // namespace arrow
-} // namespace apache
-} // namespace org
-
-#endif // FLATBUFFERS_GENERATED_TENSOR_ORG_APACHE_ARROW_FLATBUF_H_
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs b/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs
new file mode 100644
index 0000000000..50cc104199
--- /dev/null
+++ b/contrib/libs/apache/arrow/cpp/src/generated/feather.fbs
@@ -0,0 +1,156 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.
+
+/// DEPRECATED: Feather V2 is available starting in version 0.17.0 and does not
+/// use this file at all.
+
+namespace arrow.ipc.feather.fbs;
+
+/// Feather is an experimental serialization format implemented using
+/// techniques from Apache Arrow. It was created as a proof-of-concept of an
+/// interoperable file format for storing data frames originating in Python or
+/// R. It enabled the developers to sidestep some of the open design questions
+/// in Arrow from early 2016 and instead create something simple and useful for
+/// the intended use cases.
+
+enum Type : byte {
+ BOOL = 0,
+
+ INT8 = 1,
+ INT16 = 2,
+ INT32 = 3,
+ INT64 = 4,
+
+ UINT8 = 5,
+ UINT16 = 6,
+ UINT32 = 7,
+ UINT64 = 8,
+
+ FLOAT = 9,
+ DOUBLE = 10,
+
+ UTF8 = 11,
+
+ BINARY = 12,
+
+ CATEGORY = 13,
+
+ TIMESTAMP = 14,
+ DATE = 15,
+ TIME = 16,
+
+ LARGE_UTF8 = 17,
+ LARGE_BINARY = 18
+}
+
+enum Encoding : byte {
+ PLAIN = 0,
+
+ /// Data is stored dictionary-encoded
+ /// dictionary size: <INT32 Dictionary size>
+ /// dictionary data: <TYPE primitive array>
+ /// dictionary index: <INT32 primitive array>
+ ///
+ /// TODO: do we care about storing the index values in a smaller typeclass
+ DICTIONARY = 1
+}
+
+enum TimeUnit : byte {
+ SECOND = 0,
+ MILLISECOND = 1,
+ MICROSECOND = 2,
+ NANOSECOND = 3
+}
+
+table PrimitiveArray {
+ type: Type;
+
+ encoding: Encoding = PLAIN;
+
+ /// Relative memory offset of the start of the array data excluding the size
+ /// of the metadata
+ offset: long;
+
+ /// The number of logical values in the array
+ length: long;
+
+ /// The number of observed nulls
+ null_count: long;
+
+ /// The total size of the actual data in the file
+ total_bytes: long;
+
+ /// TODO: Compression
+}
+
+table CategoryMetadata {
+ /// The category codes are presumed to be integers that are valid indexes into
+ /// the levels array
+
+ levels: PrimitiveArray;
+ ordered: bool = false;
+}
+
+table TimestampMetadata {
+ unit: TimeUnit;
+
+ /// Timestamp data is assumed to be UTC, but the time zone is stored here for
+ /// presentation as localized
+ time_zone: string;
+}
+
+table DateMetadata {
+}
+
+table TimeMetadata {
+ unit: TimeUnit;
+}
+
+union TypeMetadata {
+ CategoryMetadata,
+ TimestampMetadata,
+ DateMetadata,
+ TimeMetadata,
+}
+
+table Column {
+ name: string;
+ values: PrimitiveArray;
+ metadata: TypeMetadata;
+
+ /// This should (probably) be JSON
+ user_metadata: string;
+}
+
+table CTable {
+ /// Some text (or a name) metadata about what the file is, optional
+ description: string;
+
+ num_rows: long;
+ columns: [Column];
+
+ /// Version number of the Feather format
+ ///
+ /// Internal versions 0, 1, and 2: Implemented in Apache Arrow <= 0.16.0 and
+ /// wesm/feather. Uses "custom" metadata defined in this file.
+ version: int;
+
+ /// Table metadata (likely JSON), not yet used
+ metadata: string;
+}
+
+root_type CTable;
diff --git a/contrib/libs/apache/arrow/cpp/src/generated/feather_generated.h b/contrib/libs/apache/arrow/cpp/src/generated/feather_generated.h
deleted file mode 100644
index b925eb2bc6..0000000000
--- a/contrib/libs/apache/arrow/cpp/src/generated/feather_generated.h
+++ /dev/null
@@ -1,863 +0,0 @@
-// automatically generated by the FlatBuffers compiler, do not modify
-
-
-#ifndef FLATBUFFERS_GENERATED_FEATHER_ARROW_IPC_FEATHER_FBS_H_
-#define FLATBUFFERS_GENERATED_FEATHER_ARROW_IPC_FEATHER_FBS_H_
-
-#include "flatbuffers/flatbuffers.h"
-
-namespace arrow {
-namespace ipc {
-namespace feather {
-namespace fbs {
-
-struct PrimitiveArray;
-struct PrimitiveArrayBuilder;
-
-struct CategoryMetadata;
-struct CategoryMetadataBuilder;
-
-struct TimestampMetadata;
-struct TimestampMetadataBuilder;
-
-struct DateMetadata;
-struct DateMetadataBuilder;
-
-struct TimeMetadata;
-struct TimeMetadataBuilder;
-
-struct Column;
-struct ColumnBuilder;
-
-struct CTable;
-struct CTableBuilder;
-
-/// Feather is an experimental serialization format implemented using
-/// techniques from Apache Arrow. It was created as a proof-of-concept of an
-/// interoperable file format for storing data frames originating in Python or
-/// R. It enabled the developers to sidestep some of the open design questions
-/// in Arrow from early 2016 and instead create something simple and useful for
-/// the intended use cases.
-enum class Type : int8_t {
- BOOL = 0,
- INT8 = 1,
- INT16 = 2,
- INT32 = 3,
- INT64 = 4,
- UINT8 = 5,
- UINT16 = 6,
- UINT32 = 7,
- UINT64 = 8,
- FLOAT = 9,
- DOUBLE = 10,
- UTF8 = 11,
- BINARY = 12,
- CATEGORY = 13,
- TIMESTAMP = 14,
- DATE = 15,
- TIME = 16,
- LARGE_UTF8 = 17,
- LARGE_BINARY = 18,
- MIN = BOOL,
- MAX = LARGE_BINARY
-};
-
-inline const Type (&EnumValuesType())[19] {
- static const Type values[] = {
- Type::BOOL,
- Type::INT8,
- Type::INT16,
- Type::INT32,
- Type::INT64,
- Type::UINT8,
- Type::UINT16,
- Type::UINT32,
- Type::UINT64,
- Type::FLOAT,
- Type::DOUBLE,
- Type::UTF8,
- Type::BINARY,
- Type::CATEGORY,
- Type::TIMESTAMP,
- Type::DATE,
- Type::TIME,
- Type::LARGE_UTF8,
- Type::LARGE_BINARY
- };
- return values;
-}
-
-inline const char * const *EnumNamesType() {
- static const char * const names[20] = {
- "BOOL",
- "INT8",
- "INT16",
- "INT32",
- "INT64",
- "UINT8",
- "UINT16",
- "UINT32",
- "UINT64",
- "FLOAT",
- "DOUBLE",
- "UTF8",
- "BINARY",
- "CATEGORY",
- "TIMESTAMP",
- "DATE",
- "TIME",
- "LARGE_UTF8",
- "LARGE_BINARY",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameType(Type e) {
- if (flatbuffers::IsOutRange(e, Type::BOOL, Type::LARGE_BINARY)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesType()[index];
-}
-
-enum class Encoding : int8_t {
- PLAIN = 0,
- /// Data is stored dictionary-encoded
- /// dictionary size: <INT32 Dictionary size>
- /// dictionary data: <TYPE primitive array>
- /// dictionary index: <INT32 primitive array>
- ///
- /// TODO: do we care about storing the index values in a smaller typeclass
- DICTIONARY = 1,
- MIN = PLAIN,
- MAX = DICTIONARY
-};
-
-inline const Encoding (&EnumValuesEncoding())[2] {
- static const Encoding values[] = {
- Encoding::PLAIN,
- Encoding::DICTIONARY
- };
- return values;
-}
-
-inline const char * const *EnumNamesEncoding() {
- static const char * const names[3] = {
- "PLAIN",
- "DICTIONARY",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameEncoding(Encoding e) {
- if (flatbuffers::IsOutRange(e, Encoding::PLAIN, Encoding::DICTIONARY)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesEncoding()[index];
-}
-
-enum class TimeUnit : int8_t {
- SECOND = 0,
- MILLISECOND = 1,
- MICROSECOND = 2,
- NANOSECOND = 3,
- MIN = SECOND,
- MAX = NANOSECOND
-};
-
-inline const TimeUnit (&EnumValuesTimeUnit())[4] {
- static const TimeUnit values[] = {
- TimeUnit::SECOND,
- TimeUnit::MILLISECOND,
- TimeUnit::MICROSECOND,
- TimeUnit::NANOSECOND
- };
- return values;
-}
-
-inline const char * const *EnumNamesTimeUnit() {
- static const char * const names[5] = {
- "SECOND",
- "MILLISECOND",
- "MICROSECOND",
- "NANOSECOND",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameTimeUnit(TimeUnit e) {
- if (flatbuffers::IsOutRange(e, TimeUnit::SECOND, TimeUnit::NANOSECOND)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesTimeUnit()[index];
-}
-
-enum class TypeMetadata : uint8_t {
- NONE = 0,
- CategoryMetadata = 1,
- TimestampMetadata = 2,
- DateMetadata = 3,
- TimeMetadata = 4,
- MIN = NONE,
- MAX = TimeMetadata
-};
-
-inline const TypeMetadata (&EnumValuesTypeMetadata())[5] {
- static const TypeMetadata values[] = {
- TypeMetadata::NONE,
- TypeMetadata::CategoryMetadata,
- TypeMetadata::TimestampMetadata,
- TypeMetadata::DateMetadata,
- TypeMetadata::TimeMetadata
- };
- return values;
-}
-
-inline const char * const *EnumNamesTypeMetadata() {
- static const char * const names[6] = {
- "NONE",
- "CategoryMetadata",
- "TimestampMetadata",
- "DateMetadata",
- "TimeMetadata",
- nullptr
- };
- return names;
-}
-
-inline const char *EnumNameTypeMetadata(TypeMetadata e) {
- if (flatbuffers::IsOutRange(e, TypeMetadata::NONE, TypeMetadata::TimeMetadata)) return "";
- const size_t index = static_cast<size_t>(e);
- return EnumNamesTypeMetadata()[index];
-}
-
-template<typename T> struct TypeMetadataTraits {
- static const TypeMetadata enum_value = TypeMetadata::NONE;
-};
-
-template<> struct TypeMetadataTraits<arrow::ipc::feather::fbs::CategoryMetadata> {
- static const TypeMetadata enum_value = TypeMetadata::CategoryMetadata;
-};
-
-template<> struct TypeMetadataTraits<arrow::ipc::feather::fbs::TimestampMetadata> {
- static const TypeMetadata enum_value = TypeMetadata::TimestampMetadata;
-};
-
-template<> struct TypeMetadataTraits<arrow::ipc::feather::fbs::DateMetadata> {
- static const TypeMetadata enum_value = TypeMetadata::DateMetadata;
-};
-
-template<> struct TypeMetadataTraits<arrow::ipc::feather::fbs::TimeMetadata> {
- static const TypeMetadata enum_value = TypeMetadata::TimeMetadata;
-};
-
-bool VerifyTypeMetadata(flatbuffers::Verifier &verifier, const void *obj, TypeMetadata type);
-bool VerifyTypeMetadataVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
-
-struct PrimitiveArray FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef PrimitiveArrayBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_TYPE = 4,
- VT_ENCODING = 6,
- VT_OFFSET = 8,
- VT_LENGTH = 10,
- VT_NULL_COUNT = 12,
- VT_TOTAL_BYTES = 14
- };
- arrow::ipc::feather::fbs::Type type() const {
- return static_cast<arrow::ipc::feather::fbs::Type>(GetField<int8_t>(VT_TYPE, 0));
- }
- arrow::ipc::feather::fbs::Encoding encoding() const {
- return static_cast<arrow::ipc::feather::fbs::Encoding>(GetField<int8_t>(VT_ENCODING, 0));
- }
- /// Relative memory offset of the start of the array data excluding the size
- /// of the metadata
- int64_t offset() const {
- return GetField<int64_t>(VT_OFFSET, 0);
- }
- /// The number of logical values in the array
- int64_t length() const {
- return GetField<int64_t>(VT_LENGTH, 0);
- }
- /// The number of observed nulls
- int64_t null_count() const {
- return GetField<int64_t>(VT_NULL_COUNT, 0);
- }
- /// The total size of the actual data in the file
- int64_t total_bytes() const {
- return GetField<int64_t>(VT_TOTAL_BYTES, 0);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int8_t>(verifier, VT_TYPE) &&
- VerifyField<int8_t>(verifier, VT_ENCODING) &&
- VerifyField<int64_t>(verifier, VT_OFFSET) &&
- VerifyField<int64_t>(verifier, VT_LENGTH) &&
- VerifyField<int64_t>(verifier, VT_NULL_COUNT) &&
- VerifyField<int64_t>(verifier, VT_TOTAL_BYTES) &&
- verifier.EndTable();
- }
-};
-
-struct PrimitiveArrayBuilder {
- typedef PrimitiveArray Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_type(arrow::ipc::feather::fbs::Type type) {
- fbb_.AddElement<int8_t>(PrimitiveArray::VT_TYPE, static_cast<int8_t>(type), 0);
- }
- void add_encoding(arrow::ipc::feather::fbs::Encoding encoding) {
- fbb_.AddElement<int8_t>(PrimitiveArray::VT_ENCODING, static_cast<int8_t>(encoding), 0);
- }
- void add_offset(int64_t offset) {
- fbb_.AddElement<int64_t>(PrimitiveArray::VT_OFFSET, offset, 0);
- }
- void add_length(int64_t length) {
- fbb_.AddElement<int64_t>(PrimitiveArray::VT_LENGTH, length, 0);
- }
- void add_null_count(int64_t null_count) {
- fbb_.AddElement<int64_t>(PrimitiveArray::VT_NULL_COUNT, null_count, 0);
- }
- void add_total_bytes(int64_t total_bytes) {
- fbb_.AddElement<int64_t>(PrimitiveArray::VT_TOTAL_BYTES, total_bytes, 0);
- }
- explicit PrimitiveArrayBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- PrimitiveArrayBuilder &operator=(const PrimitiveArrayBuilder &);
- flatbuffers::Offset<PrimitiveArray> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<PrimitiveArray>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<PrimitiveArray> CreatePrimitiveArray(
- flatbuffers::FlatBufferBuilder &_fbb,
- arrow::ipc::feather::fbs::Type type = arrow::ipc::feather::fbs::Type::BOOL,
- arrow::ipc::feather::fbs::Encoding encoding = arrow::ipc::feather::fbs::Encoding::PLAIN,
- int64_t offset = 0,
- int64_t length = 0,
- int64_t null_count = 0,
- int64_t total_bytes = 0) {
- PrimitiveArrayBuilder builder_(_fbb);
- builder_.add_total_bytes(total_bytes);
- builder_.add_null_count(null_count);
- builder_.add_length(length);
- builder_.add_offset(offset);
- builder_.add_encoding(encoding);
- builder_.add_type(type);
- return builder_.Finish();
-}
-
-struct CategoryMetadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef CategoryMetadataBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_LEVELS = 4,
- VT_ORDERED = 6
- };
- /// The category codes are presumed to be integers that are valid indexes into
- /// the levels array
- const arrow::ipc::feather::fbs::PrimitiveArray *levels() const {
- return GetPointer<const arrow::ipc::feather::fbs::PrimitiveArray *>(VT_LEVELS);
- }
- bool ordered() const {
- return GetField<uint8_t>(VT_ORDERED, 0) != 0;
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyOffset(verifier, VT_LEVELS) &&
- verifier.VerifyTable(levels()) &&
- VerifyField<uint8_t>(verifier, VT_ORDERED) &&
- verifier.EndTable();
- }
-};
-
-struct CategoryMetadataBuilder {
- typedef CategoryMetadata Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_levels(flatbuffers::Offset<arrow::ipc::feather::fbs::PrimitiveArray> levels) {
- fbb_.AddOffset(CategoryMetadata::VT_LEVELS, levels);
- }
- void add_ordered(bool ordered) {
- fbb_.AddElement<uint8_t>(CategoryMetadata::VT_ORDERED, static_cast<uint8_t>(ordered), 0);
- }
- explicit CategoryMetadataBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- CategoryMetadataBuilder &operator=(const CategoryMetadataBuilder &);
- flatbuffers::Offset<CategoryMetadata> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<CategoryMetadata>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<CategoryMetadata> CreateCategoryMetadata(
- flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<arrow::ipc::feather::fbs::PrimitiveArray> levels = 0,
- bool ordered = false) {
- CategoryMetadataBuilder builder_(_fbb);
- builder_.add_levels(levels);
- builder_.add_ordered(ordered);
- return builder_.Finish();
-}
-
-struct TimestampMetadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef TimestampMetadataBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_UNIT = 4,
- VT_TIMEZONE = 6
- };
- arrow::ipc::feather::fbs::TimeUnit unit() const {
- return static_cast<arrow::ipc::feather::fbs::TimeUnit>(GetField<int8_t>(VT_UNIT, 0));
- }
- /// Timestamp data is assumed to be UTC, but the time zone is stored here for
- /// presentation as localized
- const flatbuffers::String *timezone() const {
- return GetPointer<const flatbuffers::String *>(VT_TIMEZONE);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int8_t>(verifier, VT_UNIT) &&
- VerifyOffset(verifier, VT_TIMEZONE) &&
- verifier.VerifyString(timezone()) &&
- verifier.EndTable();
- }
-};
-
-struct TimestampMetadataBuilder {
- typedef TimestampMetadata Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_unit(arrow::ipc::feather::fbs::TimeUnit unit) {
- fbb_.AddElement<int8_t>(TimestampMetadata::VT_UNIT, static_cast<int8_t>(unit), 0);
- }
- void add_timezone(flatbuffers::Offset<flatbuffers::String> timezone) {
- fbb_.AddOffset(TimestampMetadata::VT_TIMEZONE, timezone);
- }
- explicit TimestampMetadataBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- TimestampMetadataBuilder &operator=(const TimestampMetadataBuilder &);
- flatbuffers::Offset<TimestampMetadata> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<TimestampMetadata>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<TimestampMetadata> CreateTimestampMetadata(
- flatbuffers::FlatBufferBuilder &_fbb,
- arrow::ipc::feather::fbs::TimeUnit unit = arrow::ipc::feather::fbs::TimeUnit::SECOND,
- flatbuffers::Offset<flatbuffers::String> timezone = 0) {
- TimestampMetadataBuilder builder_(_fbb);
- builder_.add_timezone(timezone);
- builder_.add_unit(unit);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<TimestampMetadata> CreateTimestampMetadataDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- arrow::ipc::feather::fbs::TimeUnit unit = arrow::ipc::feather::fbs::TimeUnit::SECOND,
- const char *timezone = nullptr) {
- auto timezone__ = timezone ? _fbb.CreateString(timezone) : 0;
- return arrow::ipc::feather::fbs::CreateTimestampMetadata(
- _fbb,
- unit,
- timezone__);
-}
-
-struct DateMetadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef DateMetadataBuilder Builder;
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- verifier.EndTable();
- }
-};
-
-struct DateMetadataBuilder {
- typedef DateMetadata Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- explicit DateMetadataBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- DateMetadataBuilder &operator=(const DateMetadataBuilder &);
- flatbuffers::Offset<DateMetadata> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<DateMetadata>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<DateMetadata> CreateDateMetadata(
- flatbuffers::FlatBufferBuilder &_fbb) {
- DateMetadataBuilder builder_(_fbb);
- return builder_.Finish();
-}
-
-struct TimeMetadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef TimeMetadataBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_UNIT = 4
- };
- arrow::ipc::feather::fbs::TimeUnit unit() const {
- return static_cast<arrow::ipc::feather::fbs::TimeUnit>(GetField<int8_t>(VT_UNIT, 0));
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyField<int8_t>(verifier, VT_UNIT) &&
- verifier.EndTable();
- }
-};
-
-struct TimeMetadataBuilder {
- typedef TimeMetadata Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_unit(arrow::ipc::feather::fbs::TimeUnit unit) {
- fbb_.AddElement<int8_t>(TimeMetadata::VT_UNIT, static_cast<int8_t>(unit), 0);
- }
- explicit TimeMetadataBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- TimeMetadataBuilder &operator=(const TimeMetadataBuilder &);
- flatbuffers::Offset<TimeMetadata> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<TimeMetadata>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<TimeMetadata> CreateTimeMetadata(
- flatbuffers::FlatBufferBuilder &_fbb,
- arrow::ipc::feather::fbs::TimeUnit unit = arrow::ipc::feather::fbs::TimeUnit::SECOND) {
- TimeMetadataBuilder builder_(_fbb);
- builder_.add_unit(unit);
- return builder_.Finish();
-}
-
-struct Column FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef ColumnBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_NAME = 4,
- VT_VALUES = 6,
- VT_METADATA_TYPE = 8,
- VT_METADATA = 10,
- VT_USER_METADATA = 12
- };
- const flatbuffers::String *name() const {
- return GetPointer<const flatbuffers::String *>(VT_NAME);
- }
- const arrow::ipc::feather::fbs::PrimitiveArray *values() const {
- return GetPointer<const arrow::ipc::feather::fbs::PrimitiveArray *>(VT_VALUES);
- }
- arrow::ipc::feather::fbs::TypeMetadata metadata_type() const {
- return static_cast<arrow::ipc::feather::fbs::TypeMetadata>(GetField<uint8_t>(VT_METADATA_TYPE, 0));
- }
- const void *metadata() const {
- return GetPointer<const void *>(VT_METADATA);
- }
- template<typename T> const T *metadata_as() const;
- const arrow::ipc::feather::fbs::CategoryMetadata *metadata_as_CategoryMetadata() const {
- return metadata_type() == arrow::ipc::feather::fbs::TypeMetadata::CategoryMetadata ? static_cast<const arrow::ipc::feather::fbs::CategoryMetadata *>(metadata()) : nullptr;
- }
- const arrow::ipc::feather::fbs::TimestampMetadata *metadata_as_TimestampMetadata() const {
- return metadata_type() == arrow::ipc::feather::fbs::TypeMetadata::TimestampMetadata ? static_cast<const arrow::ipc::feather::fbs::TimestampMetadata *>(metadata()) : nullptr;
- }
- const arrow::ipc::feather::fbs::DateMetadata *metadata_as_DateMetadata() const {
- return metadata_type() == arrow::ipc::feather::fbs::TypeMetadata::DateMetadata ? static_cast<const arrow::ipc::feather::fbs::DateMetadata *>(metadata()) : nullptr;
- }
- const arrow::ipc::feather::fbs::TimeMetadata *metadata_as_TimeMetadata() const {
- return metadata_type() == arrow::ipc::feather::fbs::TypeMetadata::TimeMetadata ? static_cast<const arrow::ipc::feather::fbs::TimeMetadata *>(metadata()) : nullptr;
- }
- /// This should (probably) be JSON
- const flatbuffers::String *user_metadata() const {
- return GetPointer<const flatbuffers::String *>(VT_USER_METADATA);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyOffset(verifier, VT_NAME) &&
- verifier.VerifyString(name()) &&
- VerifyOffset(verifier, VT_VALUES) &&
- verifier.VerifyTable(values()) &&
- VerifyField<uint8_t>(verifier, VT_METADATA_TYPE) &&
- VerifyOffset(verifier, VT_METADATA) &&
- VerifyTypeMetadata(verifier, metadata(), metadata_type()) &&
- VerifyOffset(verifier, VT_USER_METADATA) &&
- verifier.VerifyString(user_metadata()) &&
- verifier.EndTable();
- }
-};
-
-template<> inline const arrow::ipc::feather::fbs::CategoryMetadata *Column::metadata_as<arrow::ipc::feather::fbs::CategoryMetadata>() const {
- return metadata_as_CategoryMetadata();
-}
-
-template<> inline const arrow::ipc::feather::fbs::TimestampMetadata *Column::metadata_as<arrow::ipc::feather::fbs::TimestampMetadata>() const {
- return metadata_as_TimestampMetadata();
-}
-
-template<> inline const arrow::ipc::feather::fbs::DateMetadata *Column::metadata_as<arrow::ipc::feather::fbs::DateMetadata>() const {
- return metadata_as_DateMetadata();
-}
-
-template<> inline const arrow::ipc::feather::fbs::TimeMetadata *Column::metadata_as<arrow::ipc::feather::fbs::TimeMetadata>() const {
- return metadata_as_TimeMetadata();
-}
-
-struct ColumnBuilder {
- typedef Column Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_name(flatbuffers::Offset<flatbuffers::String> name) {
- fbb_.AddOffset(Column::VT_NAME, name);
- }
- void add_values(flatbuffers::Offset<arrow::ipc::feather::fbs::PrimitiveArray> values) {
- fbb_.AddOffset(Column::VT_VALUES, values);
- }
- void add_metadata_type(arrow::ipc::feather::fbs::TypeMetadata metadata_type) {
- fbb_.AddElement<uint8_t>(Column::VT_METADATA_TYPE, static_cast<uint8_t>(metadata_type), 0);
- }
- void add_metadata(flatbuffers::Offset<void> metadata) {
- fbb_.AddOffset(Column::VT_METADATA, metadata);
- }
- void add_user_metadata(flatbuffers::Offset<flatbuffers::String> user_metadata) {
- fbb_.AddOffset(Column::VT_USER_METADATA, user_metadata);
- }
- explicit ColumnBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- ColumnBuilder &operator=(const ColumnBuilder &);
- flatbuffers::Offset<Column> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<Column>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<Column> CreateColumn(
- flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<flatbuffers::String> name = 0,
- flatbuffers::Offset<arrow::ipc::feather::fbs::PrimitiveArray> values = 0,
- arrow::ipc::feather::fbs::TypeMetadata metadata_type = arrow::ipc::feather::fbs::TypeMetadata::NONE,
- flatbuffers::Offset<void> metadata = 0,
- flatbuffers::Offset<flatbuffers::String> user_metadata = 0) {
- ColumnBuilder builder_(_fbb);
- builder_.add_user_metadata(user_metadata);
- builder_.add_metadata(metadata);
- builder_.add_values(values);
- builder_.add_name(name);
- builder_.add_metadata_type(metadata_type);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<Column> CreateColumnDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- const char *name = nullptr,
- flatbuffers::Offset<arrow::ipc::feather::fbs::PrimitiveArray> values = 0,
- arrow::ipc::feather::fbs::TypeMetadata metadata_type = arrow::ipc::feather::fbs::TypeMetadata::NONE,
- flatbuffers::Offset<void> metadata = 0,
- const char *user_metadata = nullptr) {
- auto name__ = name ? _fbb.CreateString(name) : 0;
- auto user_metadata__ = user_metadata ? _fbb.CreateString(user_metadata) : 0;
- return arrow::ipc::feather::fbs::CreateColumn(
- _fbb,
- name__,
- values,
- metadata_type,
- metadata,
- user_metadata__);
-}
-
-struct CTable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- typedef CTableBuilder Builder;
- enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
- VT_DESCRIPTION = 4,
- VT_NUM_ROWS = 6,
- VT_COLUMNS = 8,
- VT_VERSION = 10,
- VT_METADATA = 12
- };
- /// Some text (or a name) metadata about what the file is, optional
- const flatbuffers::String *description() const {
- return GetPointer<const flatbuffers::String *>(VT_DESCRIPTION);
- }
- int64_t num_rows() const {
- return GetField<int64_t>(VT_NUM_ROWS, 0);
- }
- const flatbuffers::Vector<flatbuffers::Offset<arrow::ipc::feather::fbs::Column>> *columns() const {
- return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<arrow::ipc::feather::fbs::Column>> *>(VT_COLUMNS);
- }
- /// Version number of the Feather format
- ///
- /// Internal versions 0, 1, and 2: Implemented in Apache Arrow <= 0.16.0 and
- /// wesm/feather. Uses "custom" metadata defined in this file.
- int32_t version() const {
- return GetField<int32_t>(VT_VERSION, 0);
- }
- /// Table metadata (likely JSON), not yet used
- const flatbuffers::String *metadata() const {
- return GetPointer<const flatbuffers::String *>(VT_METADATA);
- }
- bool Verify(flatbuffers::Verifier &verifier) const {
- return VerifyTableStart(verifier) &&
- VerifyOffset(verifier, VT_DESCRIPTION) &&
- verifier.VerifyString(description()) &&
- VerifyField<int64_t>(verifier, VT_NUM_ROWS) &&
- VerifyOffset(verifier, VT_COLUMNS) &&
- verifier.VerifyVector(columns()) &&
- verifier.VerifyVectorOfTables(columns()) &&
- VerifyField<int32_t>(verifier, VT_VERSION) &&
- VerifyOffset(verifier, VT_METADATA) &&
- verifier.VerifyString(metadata()) &&
- verifier.EndTable();
- }
-};
-
-struct CTableBuilder {
- typedef CTable Table;
- flatbuffers::FlatBufferBuilder &fbb_;
- flatbuffers::uoffset_t start_;
- void add_description(flatbuffers::Offset<flatbuffers::String> description) {
- fbb_.AddOffset(CTable::VT_DESCRIPTION, description);
- }
- void add_num_rows(int64_t num_rows) {
- fbb_.AddElement<int64_t>(CTable::VT_NUM_ROWS, num_rows, 0);
- }
- void add_columns(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<arrow::ipc::feather::fbs::Column>>> columns) {
- fbb_.AddOffset(CTable::VT_COLUMNS, columns);
- }
- void add_version(int32_t version) {
- fbb_.AddElement<int32_t>(CTable::VT_VERSION, version, 0);
- }
- void add_metadata(flatbuffers::Offset<flatbuffers::String> metadata) {
- fbb_.AddOffset(CTable::VT_METADATA, metadata);
- }
- explicit CTableBuilder(flatbuffers::FlatBufferBuilder &_fbb)
- : fbb_(_fbb) {
- start_ = fbb_.StartTable();
- }
- CTableBuilder &operator=(const CTableBuilder &);
- flatbuffers::Offset<CTable> Finish() {
- const auto end = fbb_.EndTable(start_);
- auto o = flatbuffers::Offset<CTable>(end);
- return o;
- }
-};
-
-inline flatbuffers::Offset<CTable> CreateCTable(
- flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset<flatbuffers::String> description = 0,
- int64_t num_rows = 0,
- flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<arrow::ipc::feather::fbs::Column>>> columns = 0,
- int32_t version = 0,
- flatbuffers::Offset<flatbuffers::String> metadata = 0) {
- CTableBuilder builder_(_fbb);
- builder_.add_num_rows(num_rows);
- builder_.add_metadata(metadata);
- builder_.add_version(version);
- builder_.add_columns(columns);
- builder_.add_description(description);
- return builder_.Finish();
-}
-
-inline flatbuffers::Offset<CTable> CreateCTableDirect(
- flatbuffers::FlatBufferBuilder &_fbb,
- const char *description = nullptr,
- int64_t num_rows = 0,
- const std::vector<flatbuffers::Offset<arrow::ipc::feather::fbs::Column>> *columns = nullptr,
- int32_t version = 0,
- const char *metadata = nullptr) {
- auto description__ = description ? _fbb.CreateString(description) : 0;
- auto columns__ = columns ? _fbb.CreateVector<flatbuffers::Offset<arrow::ipc::feather::fbs::Column>>(*columns) : 0;
- auto metadata__ = metadata ? _fbb.CreateString(metadata) : 0;
- return arrow::ipc::feather::fbs::CreateCTable(
- _fbb,
- description__,
- num_rows,
- columns__,
- version,
- metadata__);
-}
-
-inline bool VerifyTypeMetadata(flatbuffers::Verifier &verifier, const void *obj, TypeMetadata type) {
- switch (type) {
- case TypeMetadata::NONE: {
- return true;
- }
- case TypeMetadata::CategoryMetadata: {
- auto ptr = reinterpret_cast<const arrow::ipc::feather::fbs::CategoryMetadata *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case TypeMetadata::TimestampMetadata: {
- auto ptr = reinterpret_cast<const arrow::ipc::feather::fbs::TimestampMetadata *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case TypeMetadata::DateMetadata: {
- auto ptr = reinterpret_cast<const arrow::ipc::feather::fbs::DateMetadata *>(obj);
- return verifier.VerifyTable(ptr);
- }
- case TypeMetadata::TimeMetadata: {
- auto ptr = reinterpret_cast<const arrow::ipc::feather::fbs::TimeMetadata *>(obj);
- return verifier.VerifyTable(ptr);
- }
- default: return true;
- }
-}
-
-inline bool VerifyTypeMetadataVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
- if (!values || !types) return !values && !types;
- if (values->size() != types->size()) return false;
- for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
- if (!VerifyTypeMetadata(
- verifier, values->Get(i), types->GetEnum<TypeMetadata>(i))) {
- return false;
- }
- }
- return true;
-}
-
-inline const arrow::ipc::feather::fbs::CTable *GetCTable(const void *buf) {
- return flatbuffers::GetRoot<arrow::ipc::feather::fbs::CTable>(buf);
-}
-
-inline const arrow::ipc::feather::fbs::CTable *GetSizePrefixedCTable(const void *buf) {
- return flatbuffers::GetSizePrefixedRoot<arrow::ipc::feather::fbs::CTable>(buf);
-}
-
-inline bool VerifyCTableBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifyBuffer<arrow::ipc::feather::fbs::CTable>(nullptr);
-}
-
-inline bool VerifySizePrefixedCTableBuffer(
- flatbuffers::Verifier &verifier) {
- return verifier.VerifySizePrefixedBuffer<arrow::ipc::feather::fbs::CTable>(nullptr);
-}
-
-inline void FinishCTableBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<arrow::ipc::feather::fbs::CTable> root) {
- fbb.Finish(root);
-}
-
-inline void FinishSizePrefixedCTableBuffer(
- flatbuffers::FlatBufferBuilder &fbb,
- flatbuffers::Offset<arrow::ipc::feather::fbs::CTable> root) {
- fbb.FinishSizePrefixed(root);
-}
-
-} // namespace fbs
-} // namespace feather
-} // namespace ipc
-} // namespace arrow
-
-#endif // FLATBUFFERS_GENERATED_FEATHER_ARROW_IPC_FEATHER_FBS_H_
diff --git a/contrib/libs/apache/arrow/ya.make b/contrib/libs/apache/arrow/ya.make
index 9986f9107c..f4ed4463d1 100644
--- a/contrib/libs/apache/arrow/ya.make
+++ b/contrib/libs/apache/arrow/ya.make
@@ -41,6 +41,7 @@ PEERDIR(
)
ADDINCL(
+ GLOBAL ${ARCADIA_BUILD_ROOT}/contrib/libs/apache/arrow/cpp/src
GLOBAL contrib/libs/apache/arrow/cpp/src
GLOBAL contrib/libs/apache/arrow/src
contrib/libs/apache/arrow/cpp/src/generated
@@ -80,6 +81,8 @@ IF (NOT OS_WINDOWS)
)
ENDIF()
+FLATC_FLAGS(--scoped-enums)
+
SRCS(
cpp/src/arrow/adapters/orc/adapter.cc
cpp/src/arrow/adapters/orc/adapter_util.cc
@@ -249,6 +252,12 @@ SRCS(
cpp/src/arrow/vendored/datetime/tz.cpp
cpp/src/arrow/vendored/musl/strptime.c
cpp/src/arrow/visitor.cc
+ cpp/src/generated/File.fbs
+ cpp/src/generated/Message.fbs
+ cpp/src/generated/Schema.fbs
+ cpp/src/generated/SparseTensor.fbs
+ cpp/src/generated/Tensor.fbs
+ cpp/src/generated/feather.fbs
cpp/src/generated/parquet_constants.cpp
cpp/src/generated/parquet_types.cpp
cpp/src/parquet/arrow/path_internal.cc
diff --git a/contrib/libs/flatbuffers/CMakeLists.darwin-x86_64.txt b/contrib/libs/flatbuffers/CMakeLists.darwin-x86_64.txt
new file mode 100644
index 0000000000..69394c43b6
--- /dev/null
+++ b/contrib/libs/flatbuffers/CMakeLists.darwin-x86_64.txt
@@ -0,0 +1,27 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+add_subdirectory(flatc)
+
+add_library(contrib-libs-flatbuffers)
+target_compile_options(contrib-libs-flatbuffers PRIVATE
+ -DFLATBUFFERS_LOCALE_INDEPENDENT=1
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(contrib-libs-flatbuffers PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/include
+)
+target_link_libraries(contrib-libs-flatbuffers PUBLIC
+ contrib-libs-cxxsupp
+)
+target_sources(contrib-libs-flatbuffers PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_parser.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/reflection.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/util.cpp
+)
diff --git a/contrib/libs/flatbuffers/CMakeLists.linux-aarch64.txt b/contrib/libs/flatbuffers/CMakeLists.linux-aarch64.txt
new file mode 100644
index 0000000000..a176d50a06
--- /dev/null
+++ b/contrib/libs/flatbuffers/CMakeLists.linux-aarch64.txt
@@ -0,0 +1,28 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+add_subdirectory(flatc)
+
+add_library(contrib-libs-flatbuffers)
+target_compile_options(contrib-libs-flatbuffers PRIVATE
+ -DFLATBUFFERS_LOCALE_INDEPENDENT=1
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(contrib-libs-flatbuffers PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/include
+)
+target_link_libraries(contrib-libs-flatbuffers PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-cxxsupp
+)
+target_sources(contrib-libs-flatbuffers PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_parser.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/reflection.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/util.cpp
+)
diff --git a/contrib/libs/flatbuffers/CMakeLists.linux-x86_64.txt b/contrib/libs/flatbuffers/CMakeLists.linux-x86_64.txt
new file mode 100644
index 0000000000..a176d50a06
--- /dev/null
+++ b/contrib/libs/flatbuffers/CMakeLists.linux-x86_64.txt
@@ -0,0 +1,28 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+add_subdirectory(flatc)
+
+add_library(contrib-libs-flatbuffers)
+target_compile_options(contrib-libs-flatbuffers PRIVATE
+ -DFLATBUFFERS_LOCALE_INDEPENDENT=1
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(contrib-libs-flatbuffers PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/include
+)
+target_link_libraries(contrib-libs-flatbuffers PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-cxxsupp
+)
+target_sources(contrib-libs-flatbuffers PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_parser.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/reflection.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/util.cpp
+)
diff --git a/contrib/libs/flatbuffers/CMakeLists.txt b/contrib/libs/flatbuffers/CMakeLists.txt
new file mode 100644
index 0000000000..f8b31df0c1
--- /dev/null
+++ b/contrib/libs/flatbuffers/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND NOT HAVE_CUDA)
+ include(CMakeLists.linux-aarch64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
+ include(CMakeLists.darwin-x86_64.txt)
+elseif (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" AND NOT HAVE_CUDA)
+ include(CMakeLists.windows-x86_64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT HAVE_CUDA)
+ include(CMakeLists.linux-x86_64.txt)
+endif()
diff --git a/contrib/libs/flatbuffers/CMakeLists.windows-x86_64.txt b/contrib/libs/flatbuffers/CMakeLists.windows-x86_64.txt
new file mode 100644
index 0000000000..69394c43b6
--- /dev/null
+++ b/contrib/libs/flatbuffers/CMakeLists.windows-x86_64.txt
@@ -0,0 +1,27 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+add_subdirectory(flatc)
+
+add_library(contrib-libs-flatbuffers)
+target_compile_options(contrib-libs-flatbuffers PRIVATE
+ -DFLATBUFFERS_LOCALE_INDEPENDENT=1
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(contrib-libs-flatbuffers PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/include
+)
+target_link_libraries(contrib-libs-flatbuffers PUBLIC
+ contrib-libs-cxxsupp
+)
+target_sources(contrib-libs-flatbuffers PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_parser.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/reflection.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/util.cpp
+)
diff --git a/contrib/libs/flatbuffers/CONTRIBUTING.md b/contrib/libs/flatbuffers/CONTRIBUTING.md
new file mode 100644
index 0000000000..17428add54
--- /dev/null
+++ b/contrib/libs/flatbuffers/CONTRIBUTING.md
@@ -0,0 +1,42 @@
+Contributing {#contributing}
+============
+
+Want to contribute? Great! First, read this page (including the small print at
+the end).
+
+# Before you contribute
+Before we can use your code, you must sign the
+[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1)
+(CLA), which you can do online. The CLA is necessary mainly because you own the
+copyright to your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code. We also
+need to be sure of various other things—for instance that you'll tell us if you
+know that your code infringes on other people's patents. You don't have to sign
+the CLA until after you've submitted your code for review and a member has
+approved it, but you must do it before we can put your code into our codebase.
+Before you start working on a larger contribution, you should get in touch with
+us first through the issue tracker with your idea so that we can help out and
+possibly guide you. Coordinating up front makes it much easier to avoid
+frustration later on.
+
+# Code reviews
+All submissions, including submissions by project members, require review. We
+use Github pull requests for this purpose.
+
+Some tips for good pull requests:
+* Use our code
+ [style guide](https://google.github.io/styleguide/cppguide.html).
+ When in doubt, try to stay true to the existing code of the project.
+* Write a descriptive commit message. What problem are you solving and what
+ are the consequences? Where and what did you test? Some good tips:
+ [here](http://robots.thoughtbot.com/5-useful-tips-for-a-better-commit-message)
+ and [here](https://www.kernel.org/doc/Documentation/SubmittingPatches).
+* If your PR consists of multiple commits which are successive improvements /
+ fixes to your first commit, consider squashing them into a single commit
+ (`git rebase -i`) such that your PR is a single commit on top of the current
+ HEAD. This make reviewing the code so much easier, and our history more
+ readable.
+
+# The small print
+Contributions made by corporations are covered by a different agreement than
+the one above, the Software Grant and Corporate Contributor License Agreement.
diff --git a/contrib/libs/flatbuffers/LICENSE.txt b/contrib/libs/flatbuffers/LICENSE.txt
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/contrib/libs/flatbuffers/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/contrib/libs/flatbuffers/flatc/CMakeLists.darwin-x86_64.txt b/contrib/libs/flatbuffers/flatc/CMakeLists.darwin-x86_64.txt
new file mode 100644
index 0000000000..ee54cbf098
--- /dev/null
+++ b/contrib/libs/flatbuffers/flatc/CMakeLists.darwin-x86_64.txt
@@ -0,0 +1,52 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(libs-flatbuffers-flatc)
+target_compile_options(libs-flatbuffers-flatc PRIVATE
+ -DFLATBUFFERS_LOCALE_INDEPENDENT=1
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(libs-flatbuffers-flatc PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/include
+)
+target_link_libraries(libs-flatbuffers-flatc PUBLIC
+ contrib-libs-cxxsupp
+)
+target_sources(libs-flatbuffers-flatc PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/code_generators.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/flatc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_dart.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_go.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_java.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_lua.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_php.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_python.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_rust.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_swift.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_ts.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_parser.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/reflection.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/util.cpp
+)
diff --git a/contrib/libs/flatbuffers/flatc/CMakeLists.linux-aarch64.txt b/contrib/libs/flatbuffers/flatc/CMakeLists.linux-aarch64.txt
new file mode 100644
index 0000000000..cae0280fd9
--- /dev/null
+++ b/contrib/libs/flatbuffers/flatc/CMakeLists.linux-aarch64.txt
@@ -0,0 +1,53 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(libs-flatbuffers-flatc)
+target_compile_options(libs-flatbuffers-flatc PRIVATE
+ -DFLATBUFFERS_LOCALE_INDEPENDENT=1
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(libs-flatbuffers-flatc PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/include
+)
+target_link_libraries(libs-flatbuffers-flatc PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-cxxsupp
+)
+target_sources(libs-flatbuffers-flatc PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/code_generators.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/flatc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_dart.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_go.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_java.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_lua.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_php.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_python.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_rust.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_swift.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_ts.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_parser.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/reflection.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/util.cpp
+)
diff --git a/contrib/libs/flatbuffers/flatc/CMakeLists.linux-x86_64.txt b/contrib/libs/flatbuffers/flatc/CMakeLists.linux-x86_64.txt
new file mode 100644
index 0000000000..cae0280fd9
--- /dev/null
+++ b/contrib/libs/flatbuffers/flatc/CMakeLists.linux-x86_64.txt
@@ -0,0 +1,53 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(libs-flatbuffers-flatc)
+target_compile_options(libs-flatbuffers-flatc PRIVATE
+ -DFLATBUFFERS_LOCALE_INDEPENDENT=1
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(libs-flatbuffers-flatc PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/include
+)
+target_link_libraries(libs-flatbuffers-flatc PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-cxxsupp
+)
+target_sources(libs-flatbuffers-flatc PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/code_generators.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/flatc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_dart.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_go.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_java.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_lua.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_php.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_python.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_rust.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_swift.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_ts.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_parser.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/reflection.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/util.cpp
+)
diff --git a/contrib/libs/flatbuffers/flatc/CMakeLists.txt b/contrib/libs/flatbuffers/flatc/CMakeLists.txt
new file mode 100644
index 0000000000..f8b31df0c1
--- /dev/null
+++ b/contrib/libs/flatbuffers/flatc/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND NOT HAVE_CUDA)
+ include(CMakeLists.linux-aarch64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
+ include(CMakeLists.darwin-x86_64.txt)
+elseif (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" AND NOT HAVE_CUDA)
+ include(CMakeLists.windows-x86_64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT HAVE_CUDA)
+ include(CMakeLists.linux-x86_64.txt)
+endif()
diff --git a/contrib/libs/flatbuffers/flatc/CMakeLists.windows-x86_64.txt b/contrib/libs/flatbuffers/flatc/CMakeLists.windows-x86_64.txt
new file mode 100644
index 0000000000..ee54cbf098
--- /dev/null
+++ b/contrib/libs/flatbuffers/flatc/CMakeLists.windows-x86_64.txt
@@ -0,0 +1,52 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(libs-flatbuffers-flatc)
+target_compile_options(libs-flatbuffers-flatc PRIVATE
+ -DFLATBUFFERS_LOCALE_INDEPENDENT=1
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(libs-flatbuffers-flatc PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/include
+)
+target_link_libraries(libs-flatbuffers-flatc PUBLIC
+ contrib-libs-cxxsupp
+)
+target_sources(libs-flatbuffers-flatc PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/code_generators.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/flatc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_dart.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_go.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_java.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_lua.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_php.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_python.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_rust.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_swift.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_text.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_gen_ts.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/idl_parser.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/reflection.cpp
+ ${CMAKE_SOURCE_DIR}/contrib/libs/flatbuffers/src/util.cpp
+)
diff --git a/contrib/libs/flatbuffers/flatc/ya.make b/contrib/libs/flatbuffers/flatc/ya.make
new file mode 100644
index 0000000000..7186851a35
--- /dev/null
+++ b/contrib/libs/flatbuffers/flatc/ya.make
@@ -0,0 +1,56 @@
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+WITHOUT_LICENSE_TEXTS()
+
+LICENSE(Apache-2.0)
+
+ADDINCL(
+ contrib/libs/flatbuffers/grpc
+ contrib/libs/flatbuffers/include
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+CFLAGS(
+ -DFLATBUFFERS_LOCALE_INDEPENDENT=1
+)
+
+SRCDIR(contrib/libs/flatbuffers)
+
+SRCS(
+ grpc/src/compiler/cpp_generator.cc
+ grpc/src/compiler/go_generator.cc
+ grpc/src/compiler/java_generator.cc
+ grpc/src/compiler/python_generator.cc
+ grpc/src/compiler/swift_generator.cc
+ grpc/src/compiler/ts_generator.cc
+ src/code_generators.cpp
+ src/flatc.cpp
+ src/idl_gen_cpp.cpp
+ src/idl_gen_cpp_yandex_maps_iter.cpp
+ src/idl_gen_csharp.cpp
+ src/idl_gen_dart.cpp
+ src/idl_gen_fbs.cpp
+ src/idl_gen_go.cpp
+ src/idl_gen_grpc.cpp
+ src/idl_gen_java.cpp
+ src/idl_gen_json_schema.cpp
+ src/idl_gen_kotlin.cpp
+ src/idl_gen_lobster.cpp
+ src/idl_gen_lua.cpp
+ src/idl_gen_php.cpp
+ src/idl_gen_python.cpp
+ src/idl_gen_rust.cpp
+ src/idl_gen_swift.cpp
+ src/idl_gen_text.cpp
+ src/idl_gen_ts.cpp
+ src/idl_parser.cpp
+ src/reflection.cpp
+ src/util.cpp
+)
+
+END()
diff --git a/contrib/libs/flatbuffers/grpc/README.md b/contrib/libs/flatbuffers/grpc/README.md
new file mode 100644
index 0000000000..685003f92b
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/README.md
@@ -0,0 +1,43 @@
+GRPC implementation and test
+============================
+
+NOTE: files in `src/` are shared with the GRPC project, and maintained there
+(any changes should be submitted to GRPC instead). These files are copied
+from GRPC, and work with both the Protobuf and FlatBuffers code generator.
+
+`tests/` contains a GRPC specific test, you need to have built and installed
+the GRPC libraries for this to compile. This test will build using the
+`FLATBUFFERS_BUILD_GRPCTEST` option to the main FlatBuffers CMake project.
+
+## Building Flatbuffers with gRPC
+
+### Linux
+
+1. Download, build and install gRPC. See [instructions](https://github.com/grpc/grpc/tree/master/src/cpp).
+ * Lets say your gRPC clone is at `/your/path/to/grpc_repo`.
+ * Install gRPC in a custom directory by running `make install prefix=/your/path/to/grpc_repo/install`.
+2. `export GRPC_INSTALL_PATH=/your/path/to/grpc_repo/install`
+3. `export PROTOBUF_DOWNLOAD_PATH=/your/path/to/grpc_repo/third_party/protobuf`
+4. `mkdir build ; cd build`
+5. `cmake -DFLATBUFFERS_BUILD_GRPCTEST=ON -DGRPC_INSTALL_PATH=${GRPC_INSTALL_PATH} -DPROTOBUF_DOWNLOAD_PATH=${PROTOBUF_DOWNLOAD_PATH} ..`
+6. `make`
+
+For Bazel users:
+
+```shell
+$bazel test src/compiler/...
+```
+
+## Running FlatBuffer gRPC tests
+
+### Linux
+
+1. `ln -s ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.6 ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.1`
+2. `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${GRPC_INSTALL_PATH}/lib`
+3. `make test ARGS=-V`
+
+For Bazel users:
+
+```shell
+$bazel test tests/...
+``` \ No newline at end of file
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/config.h b/contrib/libs/flatbuffers/grpc/src/compiler/config.h
new file mode 100644
index 0000000000..4adc594377
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/config.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef SRC_COMPILER_CONFIG_H
+#define SRC_COMPILER_CONFIG_H
+
+// This file is here only because schema_interface.h, which is copied from gRPC,
+// includes it. There is nothing for Flatbuffers to configure.
+
+#endif // SRC_COMPILER_CONFIG_H
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
new file mode 100644
index 0000000000..8dd408830c
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc
@@ -0,0 +1,1780 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <map>
+
+#include "src/compiler/cpp_generator.h"
+#include "flatbuffers/util.h"
+
+#include <sstream>
+
+namespace grpc_cpp_generator {
+namespace {
+
+grpc::string message_header_ext() { return "_generated.h"; }
+grpc::string service_header_ext() { return ".grpc.fb.h"; }
+
+template <class T>
+grpc::string as_string(T x) {
+ std::ostringstream out;
+ out << x;
+ return out.str();
+}
+
+inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
+ return method->ClientStreaming() && !method->ServerStreaming();
+}
+
+inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
+ return !method->ClientStreaming() && method->ServerStreaming();
+}
+
+grpc::string FilenameIdentifier(const grpc::string &filename) {
+ grpc::string result;
+ for (unsigned i = 0; i < filename.size(); i++) {
+ char c = filename[i];
+ if (isalnum(c)) {
+ result.push_back(c);
+ } else {
+ static char hex[] = "0123456789abcdef";
+ result.push_back('_');
+ result.push_back(hex[(c >> 4) & 0xf]);
+ result.push_back(hex[c & 0xf]);
+ }
+ }
+ return result;
+}
+} // namespace
+
+template <class T, size_t N>
+T *array_end(T (&array)[N]) {
+ return array + N;
+}
+
+void PrintIncludes(grpc_generator::Printer *printer,
+ const std::vector<grpc::string> &headers,
+ const Parameters &params) {
+ std::map<grpc::string, grpc::string> vars;
+
+ vars["l"] = params.use_system_headers ? '<' : '"';
+ vars["r"] = params.use_system_headers ? '>' : '"';
+
+ auto &s = params.grpc_search_path;
+ if (!s.empty()) {
+ vars["l"] += s;
+ if (s[s.size() - 1] != '/') {
+ vars["l"] += '/';
+ }
+ }
+
+ for (auto i = headers.begin(); i != headers.end(); i++) {
+ vars["h"] = *i;
+ printer->Print(vars, "#include $l$$h$$r$\n");
+ }
+}
+
+grpc::string GetHeaderPrologue(grpc_generator::File *file,
+ const Parameters & /*params*/) {
+ grpc::string output;
+ {
+ // Scope the output stream so it closes and finalizes output to the string.
+ auto printer = file->CreatePrinter(&output);
+ std::map<grpc::string, grpc::string> vars;
+
+ vars["filename"] = file->filename();
+ vars["filename_identifier"] = FilenameIdentifier(file->filename());
+ vars["filename_base"] = file->filename_without_ext();
+ vars["message_header_ext"] = message_header_ext();
+
+ printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
+ printer->Print(vars,
+ "// If you make any local change, they will be lost.\n");
+ printer->Print(vars, "// source: $filename$\n");
+ grpc::string leading_comments = file->GetLeadingComments("//");
+ if (!leading_comments.empty()) {
+ printer->Print(vars, "// Original file comments:\n");
+ printer->Print(leading_comments.c_str());
+ }
+ printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
+ printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
+ printer->Print(vars, "\n");
+ printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
+ printer->Print(vars, file->additional_headers().c_str());
+ printer->Print(vars, "\n");
+ }
+ return output;
+}
+
+grpc::string GetHeaderIncludes(grpc_generator::File *file,
+ const Parameters &params) {
+ grpc::string output;
+ {
+ // Scope the output stream so it closes and finalizes output to the string.
+ auto printer = file->CreatePrinter(&output);
+ std::map<grpc::string, grpc::string> vars;
+
+ static const char *headers_strs[] = {
+ "grpcpp/impl/codegen/async_stream.h",
+ "grpcpp/impl/codegen/async_unary_call.h",
+ "grpcpp/impl/codegen/method_handler.h",
+ "grpcpp/impl/codegen/proto_utils.h",
+ "grpcpp/impl/codegen/rpc_method.h",
+ "grpcpp/impl/codegen/service_type.h",
+ "grpcpp/impl/codegen/status.h",
+ "grpcpp/impl/codegen/stub_options.h",
+ "grpcpp/impl/codegen/sync_stream.h"};
+ std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
+ PrintIncludes(printer.get(), headers, params);
+ printer->Print(vars, "\n");
+ printer->Print(vars, "namespace grpc {\n");
+ printer->Print(vars, "class CompletionQueue;\n");
+ printer->Print(vars, "class Channel;\n");
+ printer->Print(vars, "class ServerCompletionQueue;\n");
+ printer->Print(vars, "class ServerContext;\n");
+ printer->Print(vars, "} // namespace grpc\n\n");
+
+ if (!file->package().empty()) {
+ std::vector<grpc::string> parts = file->package_parts();
+
+ for (auto part = parts.begin(); part != parts.end(); part++) {
+ vars["part"] = *part;
+ printer->Print(vars, "namespace $part$ {\n");
+ }
+ printer->Print(vars, "\n");
+ }
+ }
+ return output;
+}
+
+void PrintHeaderClientMethodInterfaces(
+ grpc_generator::Printer *printer, const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars, bool is_public) {
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+
+ struct {
+ grpc::string prefix;
+ grpc::string method_params; // extra arguments to method
+ grpc::string raw_args; // extra arguments to raw version of method
+ } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
+ {"PrepareAsync", "", ""}};
+
+ if (is_public) {
+ if (method->NoStreaming()) {
+ printer->Print(
+ *vars,
+ "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
+ "const $Request$& request, $Response$* response) = 0;\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ printer->Print(
+ *vars,
+ "std::unique_ptr< "
+ "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
+ "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+ "const $Request$& request, "
+ "::grpc::CompletionQueue* cq) {\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "return std::unique_ptr< "
+ "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
+ "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
+ " $Method$("
+ "::grpc::ClientContext* context, $Response$* response) {\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
+ "($Method$Raw(context, response));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+ printer->Print(
+ *vars,
+ "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
+ " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+ "$Response$* "
+ "response, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+ printer->Indent();
+ printer->Print(*vars,
+ "return std::unique_ptr< "
+ "::grpc::ClientAsyncWriterInterface< $Request$>>("
+ "$AsyncPrefix$$Method$Raw(context, response, "
+ "cq$AsyncRawArgs$));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
+ " $Method$(::grpc::ClientContext* context, const $Request$& request)"
+ " {\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
+ "($Method$Raw(context, request));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+ printer->Print(
+ *vars,
+ "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
+ "$AsyncPrefix$$Method$("
+ "::grpc::ClientContext* context, const $Request$& request, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "return std::unique_ptr< "
+ "::grpc::ClientAsyncReaderInterface< $Response$>>("
+ "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ } else if (method->BidiStreaming()) {
+ printer->Print(*vars,
+ "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
+ "$Request$, $Response$>> "
+ "$Method$(::grpc::ClientContext* context) {\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "return std::unique_ptr< "
+ "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
+ "$Method$Raw(context));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+ printer->Print(
+ *vars,
+ "std::unique_ptr< "
+ "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
+ "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "return std::unique_ptr< "
+ "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
+ "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ }
+ } else {
+ if (method->NoStreaming()) {
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ printer->Print(
+ *vars,
+ "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
+ "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
+ "const $Request$& request, "
+ "::grpc::CompletionQueue* cq) = 0;\n");
+ }
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "virtual ::grpc::ClientWriterInterface< $Request$>*"
+ " $Method$Raw("
+ "::grpc::ClientContext* context, $Response$* response) = 0;\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ printer->Print(
+ *vars,
+ "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
+ " $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
+ "$Response$* response, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
+ }
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "virtual ::grpc::ClientReaderInterface< $Response$>* "
+ "$Method$Raw("
+ "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ printer->Print(
+ *vars,
+ "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
+ "$AsyncPrefix$$Method$Raw("
+ "::grpc::ClientContext* context, const $Request$& request, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
+ }
+ } else if (method->BidiStreaming()) {
+ printer->Print(*vars,
+ "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
+ "$Response$>* "
+ "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ printer->Print(
+ *vars,
+ "virtual ::grpc::ClientAsyncReaderWriterInterface< "
+ "$Request$, $Response$>* "
+ "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
+ }
+ }
+ }
+}
+
+void PrintHeaderClientMethod(grpc_generator::Printer *printer,
+ const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars,
+ bool is_public) {
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ struct {
+ grpc::string prefix;
+ grpc::string method_params; // extra arguments to method
+ grpc::string raw_args; // extra arguments to raw version of method
+ } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
+ {"PrepareAsync", "", ""}};
+
+ if (is_public) {
+ if (method->NoStreaming()) {
+ printer->Print(
+ *vars,
+ "::grpc::Status $Method$(::grpc::ClientContext* context, "
+ "const $Request$& request, $Response$* response) override;\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ printer->Print(
+ *vars,
+ "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
+ "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+ "const $Request$& request, "
+ "::grpc::CompletionQueue* cq) {\n");
+ printer->Indent();
+ printer->Print(*vars,
+ "return std::unique_ptr< "
+ "::grpc::ClientAsyncResponseReader< $Response$>>("
+ "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
+ " $Method$("
+ "::grpc::ClientContext* context, $Response$* response) {\n");
+ printer->Indent();
+ printer->Print(*vars,
+ "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
+ "($Method$Raw(context, response));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+ printer->Print(*vars,
+ "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
+ " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+ "$Response$* response, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
+ "$AsyncPrefix$$Method$Raw(context, response, "
+ "cq$AsyncRawArgs$));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
+ " $Method$(::grpc::ClientContext* context, const $Request$& request)"
+ " {\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
+ "($Method$Raw(context, request));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+ printer->Print(
+ *vars,
+ "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
+ "$AsyncPrefix$$Method$("
+ "::grpc::ClientContext* context, const $Request$& request, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
+ "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ } else if (method->BidiStreaming()) {
+ printer->Print(
+ *vars,
+ "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
+ " $Method$(::grpc::ClientContext* context) {\n");
+ printer->Indent();
+ printer->Print(*vars,
+ "return std::unique_ptr< "
+ "::grpc::ClientReaderWriter< $Request$, $Response$>>("
+ "$Method$Raw(context));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+ printer->Print(*vars,
+ "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
+ "$Request$, $Response$>> "
+ "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "return std::unique_ptr< "
+ "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
+ "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ }
+ } else {
+ if (method->NoStreaming()) {
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ printer->Print(
+ *vars,
+ "::grpc::ClientAsyncResponseReader< $Response$>* "
+ "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
+ "const $Request$& request, "
+ "::grpc::CompletionQueue* cq) override;\n");
+ }
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(*vars,
+ "::grpc::ClientWriter< $Request$>* $Method$Raw("
+ "::grpc::ClientContext* context, $Response$* response) "
+ "override;\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+ printer->Print(
+ *vars,
+ "::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
+ "::grpc::ClientContext* context, $Response$* response, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
+ }
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(*vars,
+ "::grpc::ClientReader< $Response$>* $Method$Raw("
+ "::grpc::ClientContext* context, const $Request$& request)"
+ " override;\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+ printer->Print(
+ *vars,
+ "::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
+ "::grpc::ClientContext* context, const $Request$& request, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
+ }
+ } else if (method->BidiStreaming()) {
+ printer->Print(*vars,
+ "::grpc::ClientReaderWriter< $Request$, $Response$>* "
+ "$Method$Raw(::grpc::ClientContext* context) override;\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
+ printer->Print(
+ *vars,
+ "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
+ "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
+ }
+ }
+ }
+}
+
+void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
+ const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Method"] = method->name();
+ printer->Print(*vars,
+ "const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
+}
+
+void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
+ const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ printer->Print(method->GetLeadingComments("//").c_str());
+ if (method->NoStreaming()) {
+ printer->Print(*vars,
+ "virtual ::grpc::Status $Method$("
+ "::grpc::ServerContext* context, const $Request$* request, "
+ "$Response$* response);\n");
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(*vars,
+ "virtual ::grpc::Status $Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerReader< $Request$>* reader, "
+ "$Response$* response);\n");
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(*vars,
+ "virtual ::grpc::Status $Method$("
+ "::grpc::ServerContext* context, const $Request$* request, "
+ "::grpc::ServerWriter< $Response$>* writer);\n");
+ } else if (method->BidiStreaming()) {
+ printer->Print(
+ *vars,
+ "virtual ::grpc::Status $Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
+ "\n");
+ }
+ printer->Print(method->GetTrailingComments("//").c_str());
+}
+
+void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
+ const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ printer->Print(*vars, "template <class BaseClass>\n");
+ printer->Print(*vars,
+ "class WithAsyncMethod_$Method$ : public BaseClass {\n");
+ printer->Print(
+ " private:\n"
+ " void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
+ printer->Print(" public:\n");
+ printer->Indent();
+ printer->Print(*vars,
+ "WithAsyncMethod_$Method$() {\n"
+ " ::grpc::Service::MarkMethodAsync($Idx$);\n"
+ "}\n");
+ printer->Print(*vars,
+ "~WithAsyncMethod_$Method$() override {\n"
+ " BaseClassMustBeDerivedFromService(this);\n"
+ "}\n");
+ if (method->NoStreaming()) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, const $Request$* request, "
+ "$Response$* response) final override {\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ printer->Print(
+ *vars,
+ "void Request$Method$("
+ "::grpc::ServerContext* context, $Request$* request, "
+ "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
+ "::grpc::CompletionQueue* new_call_cq, "
+ "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
+ printer->Print(*vars,
+ " ::grpc::Service::RequestAsyncUnary($Idx$, context, "
+ "request, response, new_call_cq, notification_cq, tag);\n");
+ printer->Print("}\n");
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerReader< $Request$>* reader, "
+ "$Response$* response) final override {\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ printer->Print(
+ *vars,
+ "void Request$Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
+ "::grpc::CompletionQueue* new_call_cq, "
+ "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
+ printer->Print(*vars,
+ " ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
+ "context, reader, new_call_cq, notification_cq, tag);\n");
+ printer->Print("}\n");
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, const $Request$* request, "
+ "::grpc::ServerWriter< $Response$>* writer) final override "
+ "{\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ printer->Print(
+ *vars,
+ "void Request$Method$("
+ "::grpc::ServerContext* context, $Request$* request, "
+ "::grpc::ServerAsyncWriter< $Response$>* writer, "
+ "::grpc::CompletionQueue* new_call_cq, "
+ "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
+ printer->Print(
+ *vars,
+ " ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
+ "context, request, writer, new_call_cq, notification_cq, tag);\n");
+ printer->Print("}\n");
+ } else if (method->BidiStreaming()) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
+ "final override {\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ printer->Print(
+ *vars,
+ "void Request$Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
+ "::grpc::CompletionQueue* new_call_cq, "
+ "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
+ printer->Print(*vars,
+ " ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
+ "context, stream, new_call_cq, notification_cq, tag);\n");
+ printer->Print("}\n");
+ }
+ printer->Outdent();
+ printer->Print(*vars, "};\n");
+}
+
+void PrintHeaderServerMethodStreamedUnary(
+ grpc_generator::Printer *printer, const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ if (method->NoStreaming()) {
+ printer->Print(*vars, "template <class BaseClass>\n");
+ printer->Print(*vars,
+ "class WithStreamedUnaryMethod_$Method$ : "
+ "public BaseClass {\n");
+ printer->Print(
+ " private:\n"
+ " void BaseClassMustBeDerivedFromService(const Service *service) "
+ "{}\n");
+ printer->Print(" public:\n");
+ printer->Indent();
+ printer->Print(*vars,
+ "WithStreamedUnaryMethod_$Method$() {\n"
+ " ::grpc::Service::MarkMethodStreamed($Idx$,\n"
+ " new ::grpc::internal::StreamedUnaryHandler< $Request$, "
+ "$Response$>(std::bind"
+ "(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
+ "Streamed$Method$, this, std::placeholders::_1, "
+ "std::placeholders::_2)));\n"
+ "}\n");
+ printer->Print(*vars,
+ "~WithStreamedUnaryMethod_$Method$() override {\n"
+ " BaseClassMustBeDerivedFromService(this);\n"
+ "}\n");
+ printer->Print(
+ *vars,
+ "// disable regular version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, const $Request$* request, "
+ "$Response$* response) final override {\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ printer->Print(*vars,
+ "// replace default version of method with streamed unary\n"
+ "virtual ::grpc::Status Streamed$Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerUnaryStreamer< "
+ "$Request$,$Response$>* server_unary_streamer)"
+ " = 0;\n");
+ printer->Outdent();
+ printer->Print(*vars, "};\n");
+ }
+}
+
+void PrintHeaderServerMethodSplitStreaming(
+ grpc_generator::Printer *printer, const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ if (ServerOnlyStreaming(method)) {
+ printer->Print(*vars, "template <class BaseClass>\n");
+ printer->Print(*vars,
+ "class WithSplitStreamingMethod_$Method$ : "
+ "public BaseClass {\n");
+ printer->Print(
+ " private:\n"
+ " void BaseClassMustBeDerivedFromService(const Service *service) "
+ "{}\n");
+ printer->Print(" public:\n");
+ printer->Indent();
+ printer->Print(
+ *vars,
+ "WithSplitStreamingMethod_$Method$() {\n"
+ " ::grpc::Service::MarkMethodStreamed($Idx$,\n"
+ " new ::grpc::internal::SplitServerStreamingHandler< $Request$, "
+ "$Response$>(std::bind"
+ "(&WithSplitStreamingMethod_$Method$<BaseClass>::"
+ "Streamed$Method$, this, std::placeholders::_1, "
+ "std::placeholders::_2)));\n"
+ "}\n");
+ printer->Print(*vars,
+ "~WithSplitStreamingMethod_$Method$() override {\n"
+ " BaseClassMustBeDerivedFromService(this);\n"
+ "}\n");
+ printer->Print(
+ *vars,
+ "// disable regular version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, const $Request$* request, "
+ "::grpc::ServerWriter< $Response$>* writer) final override "
+ "{\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ printer->Print(*vars,
+ "// replace default version of method with split streamed\n"
+ "virtual ::grpc::Status Streamed$Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerSplitStreamer< "
+ "$Request$,$Response$>* server_split_streamer)"
+ " = 0;\n");
+ printer->Outdent();
+ printer->Print(*vars, "};\n");
+ }
+}
+
+void PrintHeaderServerMethodGeneric(
+ grpc_generator::Printer *printer, const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ printer->Print(*vars, "template <class BaseClass>\n");
+ printer->Print(*vars,
+ "class WithGenericMethod_$Method$ : public BaseClass {\n");
+ printer->Print(
+ " private:\n"
+ " void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
+ printer->Print(" public:\n");
+ printer->Indent();
+ printer->Print(*vars,
+ "WithGenericMethod_$Method$() {\n"
+ " ::grpc::Service::MarkMethodGeneric($Idx$);\n"
+ "}\n");
+ printer->Print(*vars,
+ "~WithGenericMethod_$Method$() override {\n"
+ " BaseClassMustBeDerivedFromService(this);\n"
+ "}\n");
+ if (method->NoStreaming()) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, const $Request$* request, "
+ "$Response$* response) final override {\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerReader< $Request$>* reader, "
+ "$Response$* response) final override {\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, const $Request$* request, "
+ "::grpc::ServerWriter< $Response$>* writer) final override "
+ "{\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ } else if (method->BidiStreaming()) {
+ printer->Print(
+ *vars,
+ "// disable synchronous version of this method\n"
+ "::grpc::Status $Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
+ "final override {\n"
+ " abort();\n"
+ " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
+ "}\n");
+ }
+ printer->Outdent();
+ printer->Print(*vars, "};\n");
+}
+
+void PrintHeaderService(grpc_generator::Printer *printer,
+ const grpc_generator::Service *service,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Service"] = service->name();
+
+ printer->Print(service->GetLeadingComments("//").c_str());
+ printer->Print(*vars,
+ "class $Service$ final {\n"
+ " public:\n");
+ printer->Indent();
+
+ // Service metadata
+ printer->Print(*vars,
+ "static constexpr char const* service_full_name() {\n"
+ " return \"$Package$$Service$\";\n"
+ "}\n");
+
+ // Client side
+ printer->Print(
+ "class StubInterface {\n"
+ " public:\n");
+ printer->Indent();
+ printer->Print("virtual ~StubInterface() {}\n");
+ for (int i = 0; i < service->method_count(); ++i) {
+ printer->Print(service->method(i)->GetLeadingComments("//").c_str());
+ PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
+ true);
+ printer->Print(service->method(i)->GetTrailingComments("//").c_str());
+ }
+ printer->Outdent();
+ printer->Print("private:\n");
+ printer->Indent();
+ for (int i = 0; i < service->method_count(); ++i) {
+ PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
+ false);
+ }
+ printer->Outdent();
+ printer->Print("};\n");
+ printer->Print(
+ "class Stub final : public StubInterface"
+ " {\n public:\n");
+ printer->Indent();
+ printer->Print(
+ "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
+ "channel);\n");
+ for (int i = 0; i < service->method_count(); ++i) {
+ PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
+ }
+ printer->Outdent();
+ printer->Print("\n private:\n");
+ printer->Indent();
+ printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
+ for (int i = 0; i < service->method_count(); ++i) {
+ PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
+ }
+ for (int i = 0; i < service->method_count(); ++i) {
+ PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
+ }
+ printer->Outdent();
+ printer->Print("};\n");
+ printer->Print(
+ "static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
+ "::grpc::ChannelInterface>& channel, "
+ "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
+
+ printer->Print("\n");
+
+ // Server side - base
+ printer->Print(
+ "class Service : public ::grpc::Service {\n"
+ " public:\n");
+ printer->Indent();
+ printer->Print("Service();\n");
+ printer->Print("virtual ~Service();\n");
+ for (int i = 0; i < service->method_count(); ++i) {
+ PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
+ }
+ printer->Outdent();
+ printer->Print("};\n");
+
+ // Server side - Asynchronous
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["Idx"] = as_string(i);
+ PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
+ }
+
+ printer->Print("typedef ");
+
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["method_name"] = service->method(i).get()->name();
+ printer->Print(*vars, "WithAsyncMethod_$method_name$<");
+ }
+ printer->Print("Service");
+ for (int i = 0; i < service->method_count(); ++i) {
+ printer->Print(" >");
+ }
+ printer->Print(" AsyncService;\n");
+
+ // Server side - Generic
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["Idx"] = as_string(i);
+ PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
+ }
+
+ // Server side - Streamed Unary
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["Idx"] = as_string(i);
+ PrintHeaderServerMethodStreamedUnary(printer, service->method(i).get(),
+ vars);
+ }
+
+ printer->Print("typedef ");
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["method_name"] = service->method(i).get()->name();
+ if (service->method(i)->NoStreaming()) {
+ printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
+ }
+ }
+ printer->Print("Service");
+ for (int i = 0; i < service->method_count(); ++i) {
+ if (service->method(i)->NoStreaming()) {
+ printer->Print(" >");
+ }
+ }
+ printer->Print(" StreamedUnaryService;\n");
+
+ // Server side - controlled server-side streaming
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["Idx"] = as_string(i);
+ PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(),
+ vars);
+ }
+
+ printer->Print("typedef ");
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["method_name"] = service->method(i).get()->name();
+ auto method = service->method(i);
+ if (ServerOnlyStreaming(method.get())) {
+ printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
+ }
+ }
+ printer->Print("Service");
+ for (int i = 0; i < service->method_count(); ++i) {
+ auto method = service->method(i);
+ if (ServerOnlyStreaming(method.get())) {
+ printer->Print(" >");
+ }
+ }
+ printer->Print(" SplitStreamedService;\n");
+
+ // Server side - typedef for controlled both unary and server-side streaming
+ printer->Print("typedef ");
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["method_name"] = service->method(i).get()->name();
+ auto method = service->method(i);
+ if (ServerOnlyStreaming(method.get())) {
+ printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
+ }
+ if (service->method(i)->NoStreaming()) {
+ printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
+ }
+ }
+ printer->Print("Service");
+ for (int i = 0; i < service->method_count(); ++i) {
+ auto method = service->method(i);
+ if (service->method(i)->NoStreaming() ||
+ ServerOnlyStreaming(method.get())) {
+ printer->Print(" >");
+ }
+ }
+ printer->Print(" StreamedService;\n");
+
+ printer->Outdent();
+ printer->Print("};\n");
+ printer->Print(service->GetTrailingComments("//").c_str());
+}
+
+grpc::string GetHeaderServices(grpc_generator::File *file,
+ const Parameters &params) {
+ grpc::string output;
+ {
+ // Scope the output stream so it closes and finalizes output to the string.
+ auto printer = file->CreatePrinter(&output);
+ std::map<grpc::string, grpc::string> vars;
+ // Package string is empty or ends with a dot. It is used to fully qualify
+ // method names.
+ vars["Package"] = file->package();
+ if (!file->package().empty()) {
+ vars["Package"].append(".");
+ }
+
+ if (!params.services_namespace.empty()) {
+ vars["services_namespace"] = params.services_namespace;
+ printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
+ }
+
+ for (int i = 0; i < file->service_count(); ++i) {
+ PrintHeaderService(printer.get(), file->service(i).get(), &vars);
+ printer->Print("\n");
+ }
+
+ if (!params.services_namespace.empty()) {
+ printer->Print(vars, "} // namespace $services_namespace$\n\n");
+ }
+ }
+ return output;
+}
+
+grpc::string GetHeaderEpilogue(grpc_generator::File *file,
+ const Parameters & /*params*/) {
+ grpc::string output;
+ {
+ // Scope the output stream so it closes and finalizes output to the string.
+ auto printer = file->CreatePrinter(&output);
+ std::map<grpc::string, grpc::string> vars;
+
+ vars["filename"] = file->filename();
+ vars["filename_identifier"] = FilenameIdentifier(file->filename());
+
+ if (!file->package().empty()) {
+ std::vector<grpc::string> parts = file->package_parts();
+
+ for (auto part = parts.rbegin(); part != parts.rend(); part++) {
+ vars["part"] = *part;
+ printer->Print(vars, "} // namespace $part$\n");
+ }
+ printer->Print(vars, "\n");
+ }
+
+ printer->Print(vars, "\n");
+ printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n");
+
+ printer->Print(file->GetTrailingComments("//").c_str());
+ }
+ return output;
+}
+
+grpc::string GetSourcePrologue(grpc_generator::File *file,
+ const Parameters & /*params*/) {
+ grpc::string output;
+ {
+ // Scope the output stream so it closes and finalizes output to the string.
+ auto printer = file->CreatePrinter(&output);
+ std::map<grpc::string, grpc::string> vars;
+
+ vars["filename"] = file->filename();
+ vars["filename_base"] = file->filename_without_ext();
+ vars["message_header_ext"] = message_header_ext();
+ vars["service_header_ext"] = service_header_ext();
+
+ printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
+ printer->Print(vars,
+ "// If you make any local change, they will be lost.\n");
+ printer->Print(vars, "// source: $filename$\n\n");
+
+ printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
+ printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
+ printer->Print(vars, "\n");
+ }
+ return output;
+}
+
+grpc::string GetSourceIncludes(grpc_generator::File *file,
+ const Parameters &params) {
+ grpc::string output;
+ {
+ // Scope the output stream so it closes and finalizes output to the string.
+ auto printer = file->CreatePrinter(&output);
+ std::map<grpc::string, grpc::string> vars;
+
+ static const char *headers_strs[] = {
+ "grpcpp/impl/codegen/async_stream.h",
+ "grpcpp/impl/codegen/async_unary_call.h",
+ "grpcpp/impl/codegen/channel_interface.h",
+ "grpcpp/impl/codegen/client_unary_call.h",
+ "grpcpp/impl/codegen/method_handler.h",
+ "grpcpp/impl/codegen/rpc_service_method.h",
+ "grpcpp/impl/codegen/service_type.h",
+ "grpcpp/impl/codegen/sync_stream.h"};
+ std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
+ PrintIncludes(printer.get(), headers, params);
+
+ if (!file->package().empty()) {
+ std::vector<grpc::string> parts = file->package_parts();
+
+ for (auto part = parts.begin(); part != parts.end(); part++) {
+ vars["part"] = *part;
+ printer->Print(vars, "namespace $part$ {\n");
+ }
+ }
+
+ printer->Print(vars, "\n");
+ }
+ return output;
+}
+
+void PrintSourceClientMethod(grpc_generator::Printer *printer,
+ const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ struct {
+ grpc::string prefix;
+ grpc::string start; // bool literal expressed as string
+ grpc::string method_params; // extra arguments to method
+ grpc::string create_args; // extra arguments to creator
+ } async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"},
+ {"PrepareAsync", "false", "", ", nullptr"}};
+ if (method->NoStreaming()) {
+ printer->Print(*vars,
+ "::grpc::Status $ns$$Service$::Stub::$Method$("
+ "::grpc::ClientContext* context, "
+ "const $Request$& request, $Response$* response) {\n");
+ printer->Print(*vars,
+ " return ::grpc::internal::BlockingUnaryCall"
+ "(channel_.get(), rpcmethod_$Method$_, "
+ "context, request, response);\n}\n\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncStart"] = async_prefix.start;
+ printer->Print(*vars,
+ "::grpc::ClientAsyncResponseReader< $Response$>* "
+ "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
+ "ClientContext* context, "
+ "const $Request$& request, "
+ "::grpc::CompletionQueue* cq) {\n");
+ printer->Print(
+ *vars,
+ " return "
+ "::grpc::internal::ClientAsyncResponseReaderFactory< $Response$>"
+ "::Create(channel_.get(), cq, "
+ "rpcmethod_$Method$_, "
+ "context, request, $AsyncStart$);\n"
+ "}\n\n");
+ }
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(*vars,
+ "::grpc::ClientWriter< $Request$>* "
+ "$ns$$Service$::Stub::$Method$Raw("
+ "::grpc::ClientContext* context, $Response$* response) {\n");
+ printer->Print(
+ *vars,
+ " return ::grpc::internal::ClientWriterFactory< $Request$>::Create("
+ "channel_.get(), "
+ "rpcmethod_$Method$_, "
+ "context, response);\n"
+ "}\n\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncStart"] = async_prefix.start;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
+ printer->Print(*vars,
+ "::grpc::ClientAsyncWriter< $Request$>* "
+ "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
+ "::grpc::ClientContext* context, $Response$* response, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+ printer->Print(
+ *vars,
+ " return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
+ "::Create(channel_.get(), cq, "
+ "rpcmethod_$Method$_, "
+ "context, response, $AsyncStart$$AsyncCreateArgs$);\n"
+ "}\n\n");
+ }
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "::grpc::ClientReader< $Response$>* "
+ "$ns$$Service$::Stub::$Method$Raw("
+ "::grpc::ClientContext* context, const $Request$& request) {\n");
+ printer->Print(
+ *vars,
+ " return ::grpc::internal::ClientReaderFactory< $Response$>::Create("
+ "channel_.get(), "
+ "rpcmethod_$Method$_, "
+ "context, request);\n"
+ "}\n\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncStart"] = async_prefix.start;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
+ printer->Print(
+ *vars,
+ "::grpc::ClientAsyncReader< $Response$>* "
+ "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
+ "::grpc::ClientContext* context, const $Request$& request, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+ printer->Print(
+ *vars,
+ " return ::grpc::internal::ClientAsyncReaderFactory< $Response$>"
+ "::Create(channel_.get(), cq, "
+ "rpcmethod_$Method$_, "
+ "context, request, $AsyncStart$$AsyncCreateArgs$);\n"
+ "}\n\n");
+ }
+ } else if (method->BidiStreaming()) {
+ printer->Print(
+ *vars,
+ "::grpc::ClientReaderWriter< $Request$, $Response$>* "
+ "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
+ printer->Print(*vars,
+ " return ::grpc::internal::ClientReaderWriterFactory< "
+ "$Request$, $Response$>::Create("
+ "channel_.get(), "
+ "rpcmethod_$Method$_, "
+ "context);\n"
+ "}\n\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncStart"] = async_prefix.start;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
+ printer->Print(*vars,
+ "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
+ "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
+ "ClientContext* context, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
+ printer->Print(*vars,
+ " return "
+ "::grpc::internal::ClientAsyncReaderWriterFactory< "
+ "$Request$, $Response$>::Create("
+ "channel_.get(), cq, "
+ "rpcmethod_$Method$_, "
+ "context, $AsyncStart$$AsyncCreateArgs$);\n"
+ "}\n\n");
+ }
+ }
+}
+
+void PrintSourceServerMethod(grpc_generator::Printer *printer,
+ const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ if (method->NoStreaming()) {
+ printer->Print(*vars,
+ "::grpc::Status $ns$$Service$::Service::$Method$("
+ "::grpc::ServerContext* context, "
+ "const $Request$* request, $Response$* response) {\n");
+ printer->Print(" (void) context;\n");
+ printer->Print(" (void) request;\n");
+ printer->Print(" (void) response;\n");
+ printer->Print(
+ " return ::grpc::Status("
+ "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
+ printer->Print("}\n\n");
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(*vars,
+ "::grpc::Status $ns$$Service$::Service::$Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerReader< $Request$>* reader, "
+ "$Response$* response) {\n");
+ printer->Print(" (void) context;\n");
+ printer->Print(" (void) reader;\n");
+ printer->Print(" (void) response;\n");
+ printer->Print(
+ " return ::grpc::Status("
+ "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
+ printer->Print("}\n\n");
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(*vars,
+ "::grpc::Status $ns$$Service$::Service::$Method$("
+ "::grpc::ServerContext* context, "
+ "const $Request$* request, "
+ "::grpc::ServerWriter< $Response$>* writer) {\n");
+ printer->Print(" (void) context;\n");
+ printer->Print(" (void) request;\n");
+ printer->Print(" (void) writer;\n");
+ printer->Print(
+ " return ::grpc::Status("
+ "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
+ printer->Print("}\n\n");
+ } else if (method->BidiStreaming()) {
+ printer->Print(*vars,
+ "::grpc::Status $ns$$Service$::Service::$Method$("
+ "::grpc::ServerContext* context, "
+ "::grpc::ServerReaderWriter< $Response$, $Request$>* "
+ "stream) {\n");
+ printer->Print(" (void) context;\n");
+ printer->Print(" (void) stream;\n");
+ printer->Print(
+ " return ::grpc::Status("
+ "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
+ printer->Print("}\n\n");
+ }
+}
+
+void PrintSourceService(grpc_generator::Printer *printer,
+ const grpc_generator::Service *service,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Service"] = service->name();
+
+ if (service->method_count() > 0) {
+ printer->Print(*vars,
+ "static const char* $prefix$$Service$_method_names[] = {\n");
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["Method"] = service->method(i).get()->name();
+ printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
+ }
+ printer->Print(*vars, "};\n\n");
+ }
+
+ printer->Print(*vars,
+ "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
+ "const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
+ "const ::grpc::StubOptions& options) {\n"
+ " std::unique_ptr< $ns$$Service$::Stub> stub(new "
+ "$ns$$Service$::Stub(channel));\n"
+ " return stub;\n"
+ "}\n\n");
+ printer->Print(*vars,
+ "$ns$$Service$::Stub::Stub(const std::shared_ptr< "
+ "::grpc::ChannelInterface>& channel)\n");
+ printer->Indent();
+ printer->Print(": channel_(channel)");
+ for (int i = 0; i < service->method_count(); ++i) {
+ auto method = service->method(i);
+ (*vars)["Method"] = method->name();
+ (*vars)["Idx"] = as_string(i);
+ if (method->NoStreaming()) {
+ (*vars)["StreamingType"] = "NORMAL_RPC";
+ // NOTE: There is no reason to consider streamed-unary as a separate
+ // category here since this part is setting up the client-side stub
+ // and this appears as a NORMAL_RPC from the client-side.
+ } else if (ClientOnlyStreaming(method.get())) {
+ (*vars)["StreamingType"] = "CLIENT_STREAMING";
+ } else if (ServerOnlyStreaming(method.get())) {
+ (*vars)["StreamingType"] = "SERVER_STREAMING";
+ } else {
+ (*vars)["StreamingType"] = "BIDI_STREAMING";
+ }
+ printer->Print(*vars,
+ ", rpcmethod_$Method$_("
+ "$prefix$$Service$_method_names[$Idx$], "
+ "::grpc::internal::RpcMethod::$StreamingType$, "
+ "channel"
+ ")\n");
+ }
+ printer->Print("{}\n\n");
+ printer->Outdent();
+
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["Idx"] = as_string(i);
+ PrintSourceClientMethod(printer, service->method(i).get(), vars);
+ }
+
+ printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
+ printer->Indent();
+ for (int i = 0; i < service->method_count(); ++i) {
+ auto method = service->method(i);
+ (*vars)["Idx"] = as_string(i);
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+ if (method->NoStreaming()) {
+ printer->Print(
+ *vars,
+ "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+ " $prefix$$Service$_method_names[$Idx$],\n"
+ " ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
+ " new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
+ "$Request$, "
+ "$Response$>(\n"
+ " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
+ } else if (ClientOnlyStreaming(method.get())) {
+ printer->Print(
+ *vars,
+ "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+ " $prefix$$Service$_method_names[$Idx$],\n"
+ " ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
+ " new ::grpc::internal::ClientStreamingHandler< "
+ "$ns$$Service$::Service, $Request$, $Response$>(\n"
+ " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
+ } else if (ServerOnlyStreaming(method.get())) {
+ printer->Print(
+ *vars,
+ "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+ " $prefix$$Service$_method_names[$Idx$],\n"
+ " ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
+ " new ::grpc::internal::ServerStreamingHandler< "
+ "$ns$$Service$::Service, $Request$, $Response$>(\n"
+ " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
+ } else if (method->BidiStreaming()) {
+ printer->Print(
+ *vars,
+ "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
+ " $prefix$$Service$_method_names[$Idx$],\n"
+ " ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
+ " new ::grpc::internal::BidiStreamingHandler< "
+ "$ns$$Service$::Service, $Request$, $Response$>(\n"
+ " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
+ }
+ }
+ printer->Outdent();
+ printer->Print(*vars, "}\n\n");
+ printer->Print(*vars,
+ "$ns$$Service$::Service::~Service() {\n"
+ "}\n\n");
+ for (int i = 0; i < service->method_count(); ++i) {
+ (*vars)["Idx"] = as_string(i);
+ PrintSourceServerMethod(printer, service->method(i).get(), vars);
+ }
+}
+
+grpc::string GetSourceServices(grpc_generator::File *file,
+ const Parameters &params) {
+ grpc::string output;
+ {
+ // Scope the output stream so it closes and finalizes output to the string.
+ auto printer = file->CreatePrinter(&output);
+ std::map<grpc::string, grpc::string> vars;
+ // Package string is empty or ends with a dot. It is used to fully qualify
+ // method names.
+ vars["Package"] = file->package();
+ if (!file->package().empty()) {
+ vars["Package"].append(".");
+ }
+ if (!params.services_namespace.empty()) {
+ vars["ns"] = params.services_namespace + "::";
+ vars["prefix"] = params.services_namespace;
+ } else {
+ vars["ns"] = "";
+ vars["prefix"] = "";
+ }
+
+ for (int i = 0; i < file->service_count(); ++i) {
+ PrintSourceService(printer.get(), file->service(i).get(), &vars);
+ printer->Print("\n");
+ }
+ }
+ return output;
+}
+
+grpc::string GetSourceEpilogue(grpc_generator::File *file,
+ const Parameters & /*params*/) {
+ grpc::string temp;
+
+ if (!file->package().empty()) {
+ std::vector<grpc::string> parts = file->package_parts();
+
+ for (auto part = parts.begin(); part != parts.end(); part++) {
+ temp.append("} // namespace ");
+ temp.append(*part);
+ temp.append("\n");
+ }
+ temp.append("\n");
+ }
+
+ return temp;
+}
+
+// TODO(mmukhi): Make sure we need parameters or not.
+grpc::string GetMockPrologue(grpc_generator::File *file,
+ const Parameters & /*params*/) {
+ grpc::string output;
+ {
+ // Scope the output stream so it closes and finalizes output to the string.
+ auto printer = file->CreatePrinter(&output);
+ std::map<grpc::string, grpc::string> vars;
+
+ vars["filename"] = file->filename();
+ vars["filename_base"] = file->filename_without_ext();
+ vars["message_header_ext"] = message_header_ext();
+ vars["service_header_ext"] = service_header_ext();
+
+ printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
+ printer->Print(vars,
+ "// If you make any local change, they will be lost.\n");
+ printer->Print(vars, "// source: $filename$\n\n");
+
+ printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
+ printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
+ printer->Print(vars, file->additional_headers().c_str());
+ printer->Print(vars, "\n");
+ }
+ return output;
+}
+
+// TODO(mmukhi): Add client-stream and completion-queue headers.
+grpc::string GetMockIncludes(grpc_generator::File *file,
+ const Parameters &params) {
+ grpc::string output;
+ {
+ // Scope the output stream so it closes and finalizes output to the string.
+ auto printer = file->CreatePrinter(&output);
+ std::map<grpc::string, grpc::string> vars;
+
+ static const char *headers_strs[] = {
+ "grpcpp/impl/codegen/async_stream.h",
+ "grpcpp/impl/codegen/sync_stream.h",
+ "gmock/gmock.h",
+ };
+ std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
+ PrintIncludes(printer.get(), headers, params);
+
+ if (!file->package().empty()) {
+ std::vector<grpc::string> parts = file->package_parts();
+
+ for (auto part = parts.begin(); part != parts.end(); part++) {
+ vars["part"] = *part;
+ printer->Print(vars, "namespace $part$ {\n");
+ }
+ }
+
+ printer->Print(vars, "\n");
+ }
+ return output;
+}
+
+void PrintMockClientMethods(grpc_generator::Printer *printer,
+ const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Method"] = method->name();
+ (*vars)["Request"] = method->input_type_name();
+ (*vars)["Response"] = method->output_type_name();
+
+ struct {
+ grpc::string prefix;
+ grpc::string method_params; // extra arguments to method
+ int extra_method_param_count;
+ } async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
+
+ if (method->NoStreaming()) {
+ printer->Print(
+ *vars,
+ "MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
+ "const $Request$& request, $Response$* response));\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ printer->Print(
+ *vars,
+ "MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
+ "::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
+ "(::grpc::ClientContext* context, const $Request$& request, "
+ "::grpc::CompletionQueue* cq));\n");
+ }
+ } else if (ClientOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "MOCK_METHOD2($Method$Raw, "
+ "::grpc::ClientWriterInterface< $Request$>*"
+ "(::grpc::ClientContext* context, $Response$* response));\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["MockArgs"] =
+ flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
+ printer->Print(*vars,
+ "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
+ "::grpc::ClientAsyncWriterInterface< $Request$>*"
+ "(::grpc::ClientContext* context, $Response$* response, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
+ }
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(
+ *vars,
+ "MOCK_METHOD2($Method$Raw, "
+ "::grpc::ClientReaderInterface< $Response$>*"
+ "(::grpc::ClientContext* context, const $Request$& request));\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["MockArgs"] =
+ flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
+ printer->Print(
+ *vars,
+ "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
+ "::grpc::ClientAsyncReaderInterface< $Response$>*"
+ "(::grpc::ClientContext* context, const $Request$& request, "
+ "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
+ }
+ } else if (method->BidiStreaming()) {
+ printer->Print(
+ *vars,
+ "MOCK_METHOD1($Method$Raw, "
+ "::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
+ "(::grpc::ClientContext* context));\n");
+ for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
+ auto& async_prefix = async_prefixes[i];
+ (*vars)["AsyncPrefix"] = async_prefix.prefix;
+ (*vars)["AsyncMethodParams"] = async_prefix.method_params;
+ (*vars)["MockArgs"] =
+ flatbuffers::NumToString(2 + async_prefix.extra_method_param_count);
+ printer->Print(
+ *vars,
+ "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
+ "::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
+ "(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
+ "$AsyncMethodParams$));\n");
+ }
+ }
+}
+
+void PrintMockService(grpc_generator::Printer *printer,
+ const grpc_generator::Service *service,
+ std::map<grpc::string, grpc::string> *vars) {
+ (*vars)["Service"] = service->name();
+
+ printer->Print(*vars,
+ "class Mock$Service$Stub : public $Service$::StubInterface {\n"
+ " public:\n");
+ printer->Indent();
+ for (int i = 0; i < service->method_count(); ++i) {
+ PrintMockClientMethods(printer, service->method(i).get(), vars);
+ }
+ printer->Outdent();
+ printer->Print("};\n");
+}
+
+grpc::string GetMockServices(grpc_generator::File *file,
+ const Parameters &params) {
+ grpc::string output;
+ {
+ // Scope the output stream so it closes and finalizes output to the string.
+ auto printer = file->CreatePrinter(&output);
+ std::map<grpc::string, grpc::string> vars;
+ // Package string is empty or ends with a dot. It is used to fully qualify
+ // method names.
+ vars["Package"] = file->package();
+ if (!file->package().empty()) {
+ vars["Package"].append(".");
+ }
+
+ if (!params.services_namespace.empty()) {
+ vars["services_namespace"] = params.services_namespace;
+ printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
+ }
+
+ for (int i = 0; i < file->service_count(); i++) {
+ PrintMockService(printer.get(), file->service(i).get(), &vars);
+ printer->Print("\n");
+ }
+
+ if (!params.services_namespace.empty()) {
+ printer->Print(vars, "} // namespace $services_namespace$\n\n");
+ }
+ }
+ return output;
+}
+
+grpc::string GetMockEpilogue(grpc_generator::File *file,
+ const Parameters & /*params*/) {
+ grpc::string temp;
+
+ if (!file->package().empty()) {
+ std::vector<grpc::string> parts = file->package_parts();
+
+ for (auto part = parts.begin(); part != parts.end(); part++) {
+ temp.append("} // namespace ");
+ temp.append(*part);
+ temp.append("\n");
+ }
+ temp.append("\n");
+ }
+
+ return temp;
+}
+
+} // namespace grpc_cpp_generator
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h
new file mode 100644
index 0000000000..6119ebe289
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h
@@ -0,0 +1,138 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H
+#define GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H
+
+// cpp_generator.h/.cc do not directly depend on GRPC/ProtoBuf, such that they
+// can be used to generate code for other serialization systems, such as
+// FlatBuffers.
+
+#include <memory>
+#include <vector>
+
+#include "src/compiler/config.h"
+#include "src/compiler/schema_interface.h"
+
+#ifndef GRPC_CUSTOM_STRING
+#include <string>
+#define GRPC_CUSTOM_STRING std::string
+#endif
+
+namespace grpc {
+
+typedef GRPC_CUSTOM_STRING string;
+
+} // namespace grpc
+
+namespace grpc_cpp_generator {
+
+// Contains all the parameters that are parsed from the command line.
+struct Parameters {
+ // Puts the service into a namespace
+ grpc::string services_namespace;
+ // Use system includes (<>) or local includes ("")
+ bool use_system_headers;
+ // Prefix to any grpc include
+ grpc::string grpc_search_path;
+ // Generate GMOCK code to facilitate unit testing.
+ bool generate_mock_code;
+};
+
+// Return the prologue of the generated header file.
+grpc::string GetHeaderPrologue(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the includes needed for generated header file.
+grpc::string GetHeaderIncludes(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the includes needed for generated source file.
+grpc::string GetSourceIncludes(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the epilogue of the generated header file.
+grpc::string GetHeaderEpilogue(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the prologue of the generated source file.
+grpc::string GetSourcePrologue(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the services for generated header file.
+grpc::string GetHeaderServices(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the services for generated source file.
+grpc::string GetSourceServices(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the epilogue of the generated source file.
+grpc::string GetSourceEpilogue(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the prologue of the generated mock file.
+grpc::string GetMockPrologue(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the includes needed for generated mock file.
+grpc::string GetMockIncludes(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the services for generated mock file.
+grpc::string GetMockServices(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the epilogue of generated mock file.
+grpc::string GetMockEpilogue(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the prologue of the generated mock file.
+grpc::string GetMockPrologue(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the includes needed for generated mock file.
+grpc::string GetMockIncludes(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the services for generated mock file.
+grpc::string GetMockServices(grpc_generator::File *file,
+ const Parameters &params);
+
+// Return the epilogue of generated mock file.
+grpc::string GetMockEpilogue(grpc_generator::File *file,
+ const Parameters &params);
+
+} // namespace grpc_cpp_generator
+
+#endif // GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc
new file mode 100644
index 0000000000..d646451aa6
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc
@@ -0,0 +1,501 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation AN/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <map>
+#include <cctype>
+#include <sstream>
+
+#include "src/compiler/go_generator.h"
+
+template <class T>
+grpc::string as_string(T x) {
+ std::ostringstream out;
+ out << x;
+ return out.str();
+}
+
+inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
+ return method->ClientStreaming() && !method->ServerStreaming();
+}
+
+inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
+ return !method->ClientStreaming() && method->ServerStreaming();
+}
+
+namespace grpc_go_generator {
+
+// Returns string with first letter to lowerCase
+grpc::string unexportName(grpc::string s) {
+ if (s.empty())
+ return s;
+ s[0] = static_cast<char>(std::tolower(s[0]));
+ return s;
+}
+
+// Returns string with first letter to uppercase
+grpc::string exportName(grpc::string s) {
+ if (s.empty())
+ return s;
+ s[0] = static_cast<char>(std::toupper(s[0]));
+ return s;
+}
+
+void GenerateError(grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> vars,
+ const bool multiple_return = true) {
+ printer->Print(vars, "if $Error_Check$ {\n");
+ printer->Indent();
+ vars["Return"] = multiple_return ? "nil, err" : "err";
+ printer->Print(vars, "return $Return$\n");
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+// Generates imports for the service
+void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> vars) {
+ vars["filename"] = file->filename();
+ printer->Print("//Generated by gRPC Go plugin\n");
+ printer->Print("//If you make any local changes, they will be lost\n");
+ printer->Print(vars, "//source: $filename$\n\n");
+ printer->Print(vars, "package $Package$\n\n");
+ printer->Print("import (\n");
+ printer->Indent();
+ printer->Print(vars, "$context$ \"context\"\n");
+ printer->Print("flatbuffers \"github.com/google/flatbuffers/go\"\n");
+ printer->Print(vars, "$grpc$ \"google.golang.org/grpc\"\n");
+ printer->Print("\"google.golang.org/grpc/codes\"\n");
+ printer->Print("\"google.golang.org/grpc/status\"\n");
+ printer->Outdent();
+ printer->Print(")\n\n");
+}
+
+// Generates Server method signature source
+void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> vars) {
+ vars["Method"] = exportName(method->name());
+ vars["Request"] = method->get_input_type_name();
+ vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
+ if (method->NoStreaming()) {
+ printer->Print(vars, "$Method$($context$.Context, *$Request$) (*$Response$, error)$Ending$");
+ } else if (ServerOnlyStreaming(method)) {
+ printer->Print(vars, "$Method$(*$Request$, $Service$_$Method$Server) error$Ending$");
+ } else {
+ printer->Print(vars, "$Method$($Service$_$Method$Server) error$Ending$");
+ }
+}
+
+void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> vars) {
+ vars["Method"] = exportName(method->name());
+ vars["Request"] = method->get_input_type_name();
+ vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
+ vars["FullMethodName"] = "/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"];
+ vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
+ if (method->NoStreaming()) {
+ printer->Print(vars, "func $Handler$(srv interface{}, ctx $context$.Context,\n\tdec func(interface{}) error, interceptor $grpc$.UnaryServerInterceptor) (interface{}, error) {\n");
+ printer->Indent();
+ printer->Print(vars, "in := new($Request$)\n");
+ vars["Error_Check"] = "err := dec(in); err != nil";
+ GenerateError(printer, vars);
+ printer->Print("if interceptor == nil {\n");
+ printer->Indent();
+ printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, in)\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print(vars, "info := &$grpc$.UnaryServerInfo{\n");
+ printer->Indent();
+ printer->Print("Server: srv,\n");
+ printer->Print(vars, "FullMethod: \"$FullMethodName$\",\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Outdent();
+ printer->Print("\n");
+ printer->Indent();
+ printer->Print(vars, "handler := func(ctx $context$.Context, req interface{}) (interface{}, error) {\n");
+ printer->Indent();
+ printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, req.(*$Request$))\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("return interceptor(ctx, in, info, handler)\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ return;
+ }
+ vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Server";
+ printer->Print(vars, "func $Handler$(srv interface{}, stream $grpc$.ServerStream) error {\n");
+ printer->Indent();
+ if (ServerOnlyStreaming(method)) {
+ printer->Print(vars, "m := new($Request$)\n");
+ vars["Error_Check"] = "err := stream.RecvMsg(m); err != nil";
+ GenerateError(printer, vars, false);
+ printer->Print(vars, "return srv.($Service$Server).$Method$(m, &$StreamType${stream})\n");
+ } else {
+ printer->Print(vars, "return srv.($Service$Server).$Method$(&$StreamType${stream})\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ bool genSend = method->BidiStreaming() || ServerOnlyStreaming(method);
+ bool genRecv = method->BidiStreaming() || ClientOnlyStreaming(method);
+ bool genSendAndClose = ClientOnlyStreaming(method);
+
+ printer->Print(vars, "type $Service$_$Method$Server interface {\n");
+ printer->Indent();
+ if (genSend) {
+ printer->Print(vars, "Send(*$Response$) error\n");
+ }
+ if (genRecv) {
+ printer->Print(vars, "Recv() (*$Request$, error)\n");
+ }
+ if (genSendAndClose) {
+ printer->Print(vars, "SendAndClose(*$Response$) error\n");
+ }
+ printer->Print(vars, "$grpc$.ServerStream\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ printer->Print(vars, "type $StreamType$ struct {\n");
+ printer->Indent();
+ printer->Print(vars, "$grpc$.ServerStream\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ if (genSend) {
+ printer->Print(vars, "func (x *$StreamType$) Send(m *$Response$) error {\n");
+ printer->Indent();
+ printer->Print("return x.ServerStream.SendMsg(m)\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+ if (genRecv) {
+ printer->Print(vars, "func (x *$StreamType$) Recv() (*$Request$, error) {\n");
+ printer->Indent();
+ printer->Print(vars, "m := new($Request$)\n");
+ vars["Error_Check"] = "err := x.ServerStream.RecvMsg(m); err != nil";
+ GenerateError(printer, vars);
+ printer->Print("return m, nil\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+ if (genSendAndClose) {
+ printer->Print(vars, "func (x *$StreamType$) SendAndClose(m *$Response$) error {\n");
+ printer->Indent();
+ printer->Print("return x.ServerStream.SendMsg(m)\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+
+}
+
+// Generates Client method signature source
+void GenerateClientMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> vars) {
+ vars["Method"] = exportName(method->name());
+ vars["Request"] = ", in *" + ((vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"]);
+ if (ClientOnlyStreaming(method) || method->BidiStreaming()) {
+ vars["Request"] = "";
+ }
+ vars["Response"] = "*" + method->get_output_type_name();
+ if (ClientOnlyStreaming(method) || method->BidiStreaming() || ServerOnlyStreaming(method)) {
+ vars["Response"] = vars["Service"] + "_" + vars["Method"] + "Client" ;
+ }
+ printer->Print(vars, "$Method$(ctx $context$.Context$Request$,\n\topts ...$grpc$.CallOption) ($Response$, error)$Ending$");
+}
+
+// Generates Client method source
+void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> vars) {
+ printer->Print(vars, "func (c *$ServiceUnexported$Client) ");
+ vars["Ending"] = " {\n";
+ GenerateClientMethodSignature(method, printer, vars);
+ printer->Indent();
+ vars["Method"] = exportName(method->name());
+ vars["Request"] = (vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"];
+ vars["Response"] = method->get_output_type_name();
+ vars["FullMethodName"] = "/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"];
+ if (method->NoStreaming()) {
+ printer->Print(vars, "out := new($Response$)\n");
+ printer->Print(vars, "err := c.cc.Invoke(ctx, \"$FullMethodName$\", in, out, opts...)\n");
+ vars["Error_Check"] = "err != nil";
+ GenerateError(printer, vars);
+ printer->Print("return out, nil\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+ return;
+ }
+ vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Client";
+ printer->Print(vars, "stream, err := c.cc.NewStream(ctx, &$MethodDesc$, \"$FullMethodName$\", opts...)\n");
+ vars["Error_Check"] = "err != nil";
+ GenerateError(printer, vars);
+
+ printer->Print(vars, "x := &$StreamType${stream}\n");
+ if (ServerOnlyStreaming(method)) {
+ vars["Error_Check"] = "err := x.ClientStream.SendMsg(in); err != nil";
+ GenerateError(printer, vars);
+ vars["Error_Check"] = "err := x.ClientStream.CloseSend(); err != nil";
+ GenerateError(printer, vars);
+ }
+ printer->Print("return x, nil\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ bool genSend = method->BidiStreaming() || ClientOnlyStreaming(method);
+ bool genRecv = method->BidiStreaming() || ServerOnlyStreaming(method);
+ bool genCloseAndRecv = ClientOnlyStreaming(method);
+
+ //Stream interface
+ printer->Print(vars, "type $Service$_$Method$Client interface {\n");
+ printer->Indent();
+ if (genSend) {
+ printer->Print(vars, "Send(*$Request$) error\n");
+ }
+ if (genRecv) {
+ printer->Print(vars, "Recv() (*$Response$, error)\n");
+ }
+ if (genCloseAndRecv) {
+ printer->Print(vars, "CloseAndRecv() (*$Response$, error)\n");
+ }
+ printer->Print(vars, "$grpc$.ClientStream\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ //Stream Client
+ printer->Print(vars, "type $StreamType$ struct {\n");
+ printer->Indent();
+ printer->Print(vars, "$grpc$.ClientStream\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ if (genSend) {
+ printer->Print(vars, "func (x *$StreamType$) Send(m *$Request$) error {\n");
+ printer->Indent();
+ printer->Print("return x.ClientStream.SendMsg(m)\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+
+ if (genRecv) {
+ printer->Print(vars, "func (x *$StreamType$) Recv() (*$Response$, error) {\n");
+ printer->Indent();
+ printer->Print(vars, "m := new($Response$)\n");
+ vars["Error_Check"] = "err := x.ClientStream.RecvMsg(m); err != nil";
+ GenerateError(printer, vars);
+ printer->Print("return m, nil\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+
+ if (genCloseAndRecv) {
+ printer->Print(vars, "func (x *$StreamType$) CloseAndRecv() (*$Response$, error) {\n");
+ printer->Indent();
+ vars["Error_Check"] = "err := x.ClientStream.CloseSend(); err != nil";
+ GenerateError(printer, vars);
+ printer->Print(vars, "m := new($Response$)\n");
+ vars["Error_Check"] = "err := x.ClientStream.RecvMsg(m); err != nil";
+ GenerateError(printer, vars);
+ printer->Print("return m, nil\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+ }
+}
+
+// Generates client API for the service
+void GenerateService(const grpc_generator::Service *service, grpc_generator::Printer* printer,
+ std::map<grpc::string, grpc::string> vars) {
+ vars["Service"] = exportName(service->name());
+ // Client Interface
+ printer->Print(vars, "// Client API for $Service$ service\n");
+ printer->Print(vars, "type $Service$Client interface {\n");
+ printer->Indent();
+ vars["Ending"] = "\n";
+ for (int i = 0; i < service->method_count(); i++) {
+ GenerateClientMethodSignature(service->method(i).get(), printer, vars);
+ }
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ // Client structure
+ vars["ServiceUnexported"] = unexportName(vars["Service"]);
+ printer->Print(vars, "type $ServiceUnexported$Client struct {\n");
+ printer->Indent();
+ printer->Print(vars, "cc $grpc$.ClientConnInterface\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ // NewClient
+ printer->Print(vars, "func New$Service$Client(cc $grpc$.ClientConnInterface) $Service$Client {\n");
+ printer->Indent();
+ printer->Print(vars, "return &$ServiceUnexported$Client{cc}");
+ printer->Outdent();
+ printer->Print("\n}\n\n");
+
+ int unary_methods = 0, streaming_methods = 0;
+ vars["ServiceDesc"] = "_" + vars["Service"] + "_serviceDesc";
+ for (int i = 0; i < service->method_count(); i++) {
+ auto method = service->method(i);
+ if (method->NoStreaming()) {
+ vars["MethodDesc"] = vars["ServiceDesc"] + ".Method[" + as_string(unary_methods) + "]";
+ unary_methods++;
+ } else {
+ vars["MethodDesc"] = vars["ServiceDesc"] + ".Streams[" + as_string(streaming_methods) + "]";
+ streaming_methods++;
+ }
+ GenerateClientMethod(method.get(), printer, vars);
+ }
+
+ //Server Interface
+ printer->Print(vars, "// Server API for $Service$ service\n");
+ printer->Print(vars, "type $Service$Server interface {\n");
+ printer->Indent();
+ vars["Ending"] = "\n";
+ for (int i = 0; i < service->method_count(); i++) {
+ GenerateServerMethodSignature(service->method(i).get(), printer, vars);
+ }
+ printer->Print(vars, "mustEmbedUnimplemented$Service$Server()\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ printer->Print(vars, "type Unimplemented$Service$Server struct {\n");
+ printer->Print("}\n\n");
+
+ vars["Ending"] = " {\n";
+ for (int i = 0; i < service->method_count(); i++) {
+ auto method = service->method(i);
+ vars["Method"] = exportName(method->name());
+ vars["Nil"] = method->NoStreaming() ? "nil, " : "";
+ printer->Print(vars, "func (Unimplemented$Service$Server) ");
+ GenerateServerMethodSignature(method.get(), printer, vars);
+ printer->Indent();
+ printer->Print(vars, "return $Nil$status.Errorf(codes.Unimplemented, \"method $Method$ not implemented\")\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("\n");
+ }
+
+ printer->Print(vars, "func (Unimplemented$Service$Server) mustEmbedUnimplemented$Service$Server() {}");
+ printer->Print("\n\n");
+
+ printer->Print(vars, "type Unsafe$Service$Server interface {\n");
+ printer->Indent();
+ printer->Print(vars, "mustEmbedUnimplemented$Service$Server()\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+ // Server registration.
+ printer->Print(vars, "func Register$Service$Server(s $grpc$.ServiceRegistrar, srv $Service$Server) {\n");
+ printer->Indent();
+ printer->Print(vars, "s.RegisterService(&$ServiceDesc$, srv)\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+
+ for (int i = 0; i < service->method_count(); i++) {
+ GenerateServerMethod(service->method(i).get(), printer, vars);
+ }
+
+
+ //Service Descriptor
+ printer->Print(vars, "var $ServiceDesc$ = $grpc$.ServiceDesc{\n");
+ printer->Indent();
+ printer->Print(vars, "ServiceName: \"$ServicePrefix$$Service$\",\n");
+ printer->Print(vars, "HandlerType: (*$Service$Server)(nil),\n");
+ printer->Print(vars, "Methods: []$grpc$.MethodDesc{\n");
+ printer->Indent();
+ for (int i = 0; i < service->method_count(); i++) {
+ auto method = service->method(i);
+ vars["Method"] = exportName(method->name());
+ vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
+ if (method->NoStreaming()) {
+ printer->Print("{\n");
+ printer->Indent();
+ printer->Print(vars, "MethodName: \"$Method$\",\n");
+ printer->Print(vars, "Handler: $Handler$,\n");
+ printer->Outdent();
+ printer->Print("},\n");
+ }
+ }
+ printer->Outdent();
+ printer->Print("},\n");
+ printer->Print(vars, "Streams: []$grpc$.StreamDesc{\n");
+ printer->Indent();
+ for (int i = 0; i < service->method_count(); i++) {
+ auto method = service->method(i);
+ vars["Method"] = exportName(method->name());
+ vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
+ if (!method->NoStreaming()) {
+ printer->Print("{\n");
+ printer->Indent();
+ printer->Print(vars, "StreamName: \"$Method$\",\n");
+ printer->Print(vars, "Handler: $Handler$,\n");
+ if (ClientOnlyStreaming(method.get())) {
+ printer->Print("ClientStreams: true,\n");
+ } else if (ServerOnlyStreaming(method.get())) {
+ printer->Print("ServerStreams: true,\n");
+ } else {
+ printer->Print("ServerStreams: true,\n");
+ printer->Print("ClientStreams: true,\n");
+ }
+ printer->Outdent();
+ printer->Print("},\n");
+ }
+ }
+ printer->Outdent();
+ printer->Print("},\n");
+ printer->Outdent();
+ printer->Print("}\n");
+
+}
+
+
+// Returns source for the service
+grpc::string GenerateServiceSource(grpc_generator::File *file,
+ const grpc_generator::Service *service,
+ grpc_go_generator::Parameters *parameters) {
+ grpc::string out;
+ auto p = file->CreatePrinter(&out, '\t');
+ p->SetIndentationSize(1);
+ auto printer = p.get();
+ std::map<grpc::string, grpc::string> vars;
+ vars["Package"] = parameters->package_name;
+ vars["ServicePrefix"] = parameters->service_prefix;
+ if (!parameters->service_prefix.empty())
+ vars["ServicePrefix"].append(".");
+ vars["grpc"] = "grpc";
+ vars["context"] = "context";
+ GenerateImports(file, printer, vars);
+ if (parameters->custom_method_io_type != "") {
+ vars["CustomMethodIO"] = parameters->custom_method_io_type;
+ }
+ GenerateService(service, printer, vars);
+ return out;
+}
+}// Namespace grpc_go_generator
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.h
new file mode 100644
index 0000000000..baa94e0599
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.h
@@ -0,0 +1,64 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_COMPILER_GO_GENERATOR_H
+#define GRPC_INTERNAL_COMPILER_GO_GENERATOR_H
+
+//go generator is used to generate GRPC code for serialization system, such as flatbuffers
+#include <memory>
+#include <vector>
+
+#include "src/compiler/schema_interface.h"
+
+namespace grpc_go_generator {
+
+struct Parameters {
+ //Defines the custom parameter types for methods
+ //eg: flatbuffers uses flatbuffers.Builder as input for the client and output for the server
+ grpc::string custom_method_io_type;
+
+ //Package name for the service
+ grpc::string package_name;
+
+ //Prefix for RPC Calls
+ grpc::string service_prefix;
+};
+
+// Return the source of the generated service file.
+grpc::string GenerateServiceSource(grpc_generator::File *file,
+ const grpc_generator::Service *service,
+ grpc_go_generator::Parameters *parameters);
+
+}
+
+#endif // GRPC_INTERNAL_COMPILER_GO_GENERATOR_H
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc
new file mode 100644
index 0000000000..d2cf5ccc14
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc
@@ -0,0 +1,1135 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#include "src/compiler/java_generator.h"
+
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <map>
+#include <utility>
+#include <vector>
+
+// just to get flatbuffer_version_string()
+#include <flatbuffers/flatbuffers.h>
+#include <flatbuffers/util.h>
+#define to_string flatbuffers::NumToString
+
+// Stringify helpers used solely to cast GRPC_VERSION
+#ifndef STR
+#define STR(s) #s
+#endif
+
+#ifndef XSTR
+#define XSTR(s) STR(s)
+#endif
+
+
+typedef grpc_generator::Printer Printer;
+typedef std::map<grpc::string, grpc::string> VARS;
+typedef grpc_generator::Service ServiceDescriptor;
+typedef grpc_generator::CommentHolder
+ DescriptorType; // base class of all 'descriptors'
+typedef grpc_generator::Method MethodDescriptor;
+
+namespace grpc_java_generator {
+typedef std::string string;
+// Generates imports for the service
+void GenerateImports(grpc_generator::File* file,
+ grpc_generator::Printer* printer, VARS& vars) {
+ vars["filename"] = file->filename();
+ printer->Print(
+ vars,
+ "//Generated by flatc compiler (version $flatc_version$)\n");
+ printer->Print("//If you make any local changes, they will be lost\n");
+ printer->Print(vars, "//source: $filename$.fbs\n\n");
+ printer->Print(vars, "package $Package$;\n\n");
+ vars["Package"] = vars["Package"] + ".";
+ if (!file->additional_headers().empty()) {
+ printer->Print(file->additional_headers().c_str());
+ printer->Print("\n\n");
+ }
+}
+
+// Adjust a method name prefix identifier to follow the JavaBean spec:
+// - decapitalize the first letter
+// - remove embedded underscores & capitalize the following letter
+static string MixedLower(const string& word) {
+ string w;
+ w += static_cast<string::value_type>(tolower(word[0]));
+ bool after_underscore = false;
+ for (size_t i = 1; i < word.length(); ++i) {
+ if (word[i] == '_') {
+ after_underscore = true;
+ } else {
+ w += after_underscore ? static_cast<string::value_type>(toupper(word[i]))
+ : word[i];
+ after_underscore = false;
+ }
+ }
+ return w;
+}
+
+// Converts to the identifier to the ALL_UPPER_CASE format.
+// - An underscore is inserted where a lower case letter is followed by an
+// upper case letter.
+// - All letters are converted to upper case
+static string ToAllUpperCase(const string& word) {
+ string w;
+ for (size_t i = 0; i < word.length(); ++i) {
+ w += static_cast<string::value_type>(toupper(word[i]));
+ if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) {
+ w += '_';
+ }
+ }
+ return w;
+}
+
+static inline string LowerMethodName(const MethodDescriptor* method) {
+ return MixedLower(method->name());
+}
+
+static inline string MethodPropertiesFieldName(const MethodDescriptor* method) {
+ return "METHOD_" + ToAllUpperCase(method->name());
+}
+
+static inline string MethodPropertiesGetterName(
+ const MethodDescriptor* method) {
+ return MixedLower("get_" + method->name() + "_method");
+}
+
+static inline string MethodIdFieldName(const MethodDescriptor* method) {
+ return "METHODID_" + ToAllUpperCase(method->name());
+}
+
+static inline string JavaClassName(VARS& vars, const string& name) {
+ // string name = google::protobuf::compiler::java::ClassName(desc);
+ return vars["Package"] + name;
+}
+
+static inline string ServiceClassName(const string& service_name) {
+ return service_name + "Grpc";
+}
+
+// TODO(nmittler): Remove once protobuf includes javadoc methods in
+// distribution.
+template <typename ITR>
+static void GrpcSplitStringToIteratorUsing(const string& full,
+ const char* delim, ITR& result) {
+ // Optimize the common case where delim is a single character.
+ if (delim[0] != '\0' && delim[1] == '\0') {
+ char c = delim[0];
+ const char* p = full.data();
+ const char* end = p + full.size();
+ while (p != end) {
+ if (*p == c) {
+ ++p;
+ } else {
+ const char* start = p;
+ while (++p != end && *p != c)
+ ;
+ *result++ = string(start, p - start);
+ }
+ }
+ return;
+ }
+
+ string::size_type begin_index, end_index;
+ begin_index = full.find_first_not_of(delim);
+ while (begin_index != string::npos) {
+ end_index = full.find_first_of(delim, begin_index);
+ if (end_index == string::npos) {
+ *result++ = full.substr(begin_index);
+ return;
+ }
+ *result++ = full.substr(begin_index, (end_index - begin_index));
+ begin_index = full.find_first_not_of(delim, end_index);
+ }
+}
+
+static void GrpcSplitStringUsing(const string& full, const char* delim,
+ std::vector<string>* result) {
+ std::back_insert_iterator<std::vector<string>> it(*result);
+ GrpcSplitStringToIteratorUsing(full, delim, it);
+}
+
+static std::vector<string> GrpcSplit(const string& full, const char* delim) {
+ std::vector<string> result;
+ GrpcSplitStringUsing(full, delim, &result);
+ return result;
+}
+
+// TODO(nmittler): Remove once protobuf includes javadoc methods in
+// distribution.
+static string GrpcEscapeJavadoc(const string& input) {
+ string result;
+ result.reserve(input.size() * 2);
+
+ char prev = '*';
+
+ for (string::size_type i = 0; i < input.size(); i++) {
+ char c = input[i];
+ switch (c) {
+ case '*':
+ // Avoid "/*".
+ if (prev == '/') {
+ result.append("&#42;");
+ } else {
+ result.push_back(c);
+ }
+ break;
+ case '/':
+ // Avoid "*/".
+ if (prev == '*') {
+ result.append("&#47;");
+ } else {
+ result.push_back(c);
+ }
+ break;
+ case '@':
+ // '@' starts javadoc tags including the @deprecated tag, which will
+ // cause a compile-time error if inserted before a declaration that
+ // does not have a corresponding @Deprecated annotation.
+ result.append("&#64;");
+ break;
+ case '<':
+ // Avoid interpretation as HTML.
+ result.append("&lt;");
+ break;
+ case '>':
+ // Avoid interpretation as HTML.
+ result.append("&gt;");
+ break;
+ case '&':
+ // Avoid interpretation as HTML.
+ result.append("&amp;");
+ break;
+ case '\\':
+ // Java interprets Unicode escape sequences anywhere!
+ result.append("&#92;");
+ break;
+ default:
+ result.push_back(c);
+ break;
+ }
+
+ prev = c;
+ }
+
+ return result;
+}
+
+static std::vector<string> GrpcGetDocLines(const string& comments) {
+ if (!comments.empty()) {
+ // TODO(kenton): Ideally we should parse the comment text as Markdown and
+ // write it back as HTML, but this requires a Markdown parser. For now
+ // we just use <pre> to get fixed-width text formatting.
+
+ // If the comment itself contains block comment start or end markers,
+ // HTML-escape them so that they don't accidentally close the doc comment.
+ string escapedComments = GrpcEscapeJavadoc(comments);
+
+ std::vector<string> lines = GrpcSplit(escapedComments, "\n");
+ while (!lines.empty() && lines.back().empty()) {
+ lines.pop_back();
+ }
+ return lines;
+ }
+ return std::vector<string>();
+}
+
+static std::vector<string> GrpcGetDocLinesForDescriptor(
+ const DescriptorType* descriptor) {
+ return descriptor->GetAllComments();
+ // return GrpcGetDocLines(descriptor->GetLeadingComments("///"));
+}
+
+static void GrpcWriteDocCommentBody(Printer* printer, VARS& vars,
+ const std::vector<string>& lines,
+ bool surroundWithPreTag) {
+ if (!lines.empty()) {
+ if (surroundWithPreTag) {
+ printer->Print(" * <pre>\n");
+ }
+
+ for (size_t i = 0; i < lines.size(); i++) {
+ // Most lines should start with a space. Watch out for lines that start
+ // with a /, since putting that right after the leading asterisk will
+ // close the comment.
+ vars["line"] = lines[i];
+ if (!lines[i].empty() && lines[i][0] == '/') {
+ printer->Print(vars, " * $line$\n");
+ } else {
+ printer->Print(vars, " *$line$\n");
+ }
+ }
+
+ if (surroundWithPreTag) {
+ printer->Print(" * </pre>\n");
+ }
+ }
+}
+
+static void GrpcWriteDocComment(Printer* printer, VARS& vars,
+ const string& comments) {
+ printer->Print("/**\n");
+ std::vector<string> lines = GrpcGetDocLines(comments);
+ GrpcWriteDocCommentBody(printer, vars, lines, false);
+ printer->Print(" */\n");
+}
+
+static void GrpcWriteServiceDocComment(Printer* printer, VARS& vars,
+ const ServiceDescriptor* service) {
+ printer->Print("/**\n");
+ std::vector<string> lines = GrpcGetDocLinesForDescriptor(service);
+ GrpcWriteDocCommentBody(printer, vars, lines, true);
+ printer->Print(" */\n");
+}
+
+void GrpcWriteMethodDocComment(Printer* printer, VARS& vars,
+ const MethodDescriptor* method) {
+ printer->Print("/**\n");
+ std::vector<string> lines = GrpcGetDocLinesForDescriptor(method);
+ GrpcWriteDocCommentBody(printer, vars, lines, true);
+ printer->Print(" */\n");
+}
+
+//outputs static singleton extractor for type stored in "extr_type" and "extr_type_name" vars
+static void PrintTypeExtractor(Printer* p, VARS& vars) {
+ p->Print(
+ vars,
+ "private static volatile FlatbuffersUtils.FBExtactor<$extr_type$> "
+ "extractorOf$extr_type_name$;\n"
+ "private static FlatbuffersUtils.FBExtactor<$extr_type$> "
+ "getExtractorOf$extr_type_name$() {\n"
+ " if (extractorOf$extr_type_name$ != null) return "
+ "extractorOf$extr_type_name$;\n"
+ " synchronized ($service_class_name$.class) {\n"
+ " if (extractorOf$extr_type_name$ != null) return "
+ "extractorOf$extr_type_name$;\n"
+ " extractorOf$extr_type_name$ = new "
+ "FlatbuffersUtils.FBExtactor<$extr_type$>() {\n"
+ " public $extr_type$ extract (ByteBuffer buffer) {\n"
+ " return "
+ "$extr_type$.getRootAs$extr_type_name$(buffer);\n"
+ " }\n"
+ " };\n"
+ " return extractorOf$extr_type_name$;\n"
+ " }\n"
+ "}\n\n");
+}
+static void PrintMethodFields(Printer* p, VARS& vars,
+ const ServiceDescriptor* service) {
+ p->Print("// Static method descriptors that strictly reflect the proto.\n");
+ vars["service_name"] = service->name();
+
+ //set of names of rpc input- and output- types that were already encountered.
+ //this is needed to avoid duplicating type extractor since it's possible that
+ //the same type is used as an input or output type of more than a single RPC method
+ std::set<std::string> encounteredTypes;
+
+ for (int i = 0; i < service->method_count(); ++i) {
+ auto method = service->method(i);
+ vars["arg_in_id"] = to_string(2L * i); //trying to make msvc 10 happy
+ vars["arg_out_id"] = to_string(2L * i + 1);
+ vars["method_name"] = method->name();
+ vars["input_type_name"] = method->get_input_type_name();
+ vars["output_type_name"] = method->get_output_type_name();
+ vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
+ vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
+ vars["method_field_name"] = MethodPropertiesFieldName(method.get());
+ vars["method_new_field_name"] = MethodPropertiesGetterName(method.get());
+ vars["method_method_name"] = MethodPropertiesGetterName(method.get());
+ bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
+ bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
+ if (client_streaming) {
+ if (server_streaming) {
+ vars["method_type"] = "BIDI_STREAMING";
+ } else {
+ vars["method_type"] = "CLIENT_STREAMING";
+ }
+ } else {
+ if (server_streaming) {
+ vars["method_type"] = "SERVER_STREAMING";
+ } else {
+ vars["method_type"] = "UNARY";
+ }
+ }
+
+ p->Print(
+ vars,
+ "@$ExperimentalApi$(\"https://github.com/grpc/grpc-java/issues/"
+ "1901\")\n"
+ "@$Deprecated$ // Use {@link #$method_method_name$()} instead. \n"
+ "public static final $MethodDescriptor$<$input_type$,\n"
+ " $output_type$> $method_field_name$ = $method_method_name$();\n"
+ "\n"
+ "private static volatile $MethodDescriptor$<$input_type$,\n"
+ " $output_type$> $method_new_field_name$;\n"
+ "\n");
+
+ if (encounteredTypes.insert(vars["input_type_name"]).second) {
+ vars["extr_type"] = vars["input_type"];
+ vars["extr_type_name"] = vars["input_type_name"];
+ PrintTypeExtractor(p, vars);
+ }
+
+ if (encounteredTypes.insert(vars["output_type_name"]).second) {
+ vars["extr_type"] = vars["output_type"];
+ vars["extr_type_name"] = vars["output_type_name"];
+ PrintTypeExtractor(p, vars);
+ }
+
+ p->Print(
+ vars,
+ "@$ExperimentalApi$(\"https://github.com/grpc/grpc-java/issues/"
+ "1901\")\n"
+ "public static $MethodDescriptor$<$input_type$,\n"
+ " $output_type$> $method_method_name$() {\n"
+ " $MethodDescriptor$<$input_type$, $output_type$> "
+ "$method_new_field_name$;\n"
+ " if (($method_new_field_name$ = "
+ "$service_class_name$.$method_new_field_name$) == null) {\n"
+ " synchronized ($service_class_name$.class) {\n"
+ " if (($method_new_field_name$ = "
+ "$service_class_name$.$method_new_field_name$) == null) {\n"
+ " $service_class_name$.$method_new_field_name$ = "
+ "$method_new_field_name$ = \n"
+ " $MethodDescriptor$.<$input_type$, "
+ "$output_type$>newBuilder()\n"
+ " .setType($MethodType$.$method_type$)\n"
+ " .setFullMethodName(generateFullMethodName(\n"
+ " \"$Package$$service_name$\", \"$method_name$\"))\n"
+ " .setSampledToLocalTracing(true)\n"
+ " .setRequestMarshaller(FlatbuffersUtils.marshaller(\n"
+ " $input_type$.class, "
+ "getExtractorOf$input_type_name$()))\n"
+ " .setResponseMarshaller(FlatbuffersUtils.marshaller(\n"
+ " $output_type$.class, "
+ "getExtractorOf$output_type_name$()))\n");
+
+ // vars["proto_method_descriptor_supplier"] = service->name() +
+ // "MethodDescriptorSupplier";
+ p->Print(vars, " .setSchemaDescriptor(null)\n");
+ //" .setSchemaDescriptor(new
+ //$proto_method_descriptor_supplier$(\"$method_name$\"))\n");
+
+ p->Print(vars, " .build();\n");
+ p->Print(vars,
+ " }\n"
+ " }\n"
+ " }\n"
+ " return $method_new_field_name$;\n"
+ "}\n");
+
+ p->Print("\n");
+ }
+}
+enum StubType {
+ ASYNC_INTERFACE = 0,
+ BLOCKING_CLIENT_INTERFACE = 1,
+ FUTURE_CLIENT_INTERFACE = 2,
+ BLOCKING_SERVER_INTERFACE = 3,
+ ASYNC_CLIENT_IMPL = 4,
+ BLOCKING_CLIENT_IMPL = 5,
+ FUTURE_CLIENT_IMPL = 6,
+ ABSTRACT_CLASS = 7,
+};
+
+enum CallType { ASYNC_CALL = 0, BLOCKING_CALL = 1, FUTURE_CALL = 2 };
+
+static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
+ const ServiceDescriptor* service);
+
+// Prints a client interface or implementation class, or a server interface.
+static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
+ StubType type) {
+ const string service_name = service->name();
+ vars["service_name"] = service_name;
+ vars["abstract_name"] = service_name + "ImplBase";
+ string stub_name = service_name;
+ string client_name = service_name;
+ CallType call_type = ASYNC_CALL;
+ bool impl_base = false;
+ bool interface = false;
+ switch (type) {
+ case ABSTRACT_CLASS:
+ call_type = ASYNC_CALL;
+ impl_base = true;
+ break;
+ case ASYNC_CLIENT_IMPL:
+ call_type = ASYNC_CALL;
+ stub_name += "Stub";
+ break;
+ case BLOCKING_CLIENT_INTERFACE:
+ interface = true;
+ FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BLOCKING_CLIENT_IMPL:
+ call_type = BLOCKING_CALL;
+ stub_name += "BlockingStub";
+ client_name += "BlockingClient";
+ break;
+ case FUTURE_CLIENT_INTERFACE:
+ interface = true;
+ FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case FUTURE_CLIENT_IMPL:
+ call_type = FUTURE_CALL;
+ stub_name += "FutureStub";
+ client_name += "FutureClient";
+ break;
+ case ASYNC_INTERFACE:
+ call_type = ASYNC_CALL;
+ interface = true;
+ break;
+ default:
+ GRPC_CODEGEN_FAIL << "Cannot determine class name for StubType: " << type;
+ }
+ vars["stub_name"] = stub_name;
+ vars["client_name"] = client_name;
+
+ // Class head
+ if (!interface) {
+ GrpcWriteServiceDocComment(p, vars, service);
+ }
+ if (impl_base) {
+ p->Print(vars,
+ "public static abstract class $abstract_name$ implements "
+ "$BindableService$ {\n");
+ } else {
+ p->Print(vars,
+ "public static final class $stub_name$ extends "
+ "$AbstractStub$<$stub_name$> {\n");
+ }
+ p->Indent();
+
+ // Constructor and build() method
+ if (!impl_base && !interface) {
+ p->Print(vars, "private $stub_name$($Channel$ channel) {\n");
+ p->Indent();
+ p->Print("super(channel);\n");
+ p->Outdent();
+ p->Print("}\n\n");
+ p->Print(vars,
+ "private $stub_name$($Channel$ channel,\n"
+ " $CallOptions$ callOptions) {\n");
+ p->Indent();
+ p->Print("super(channel, callOptions);\n");
+ p->Outdent();
+ p->Print("}\n\n");
+ p->Print(vars,
+ "@$Override$\n"
+ "protected $stub_name$ build($Channel$ channel,\n"
+ " $CallOptions$ callOptions) {\n");
+ p->Indent();
+ p->Print(vars, "return new $stub_name$(channel, callOptions);\n");
+ p->Outdent();
+ p->Print("}\n");
+ }
+
+ // RPC methods
+ for (int i = 0; i < service->method_count(); ++i) {
+ auto method = service->method(i);
+ vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
+ vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
+ vars["lower_method_name"] = LowerMethodName(&*method);
+ vars["method_method_name"] = MethodPropertiesGetterName(&*method);
+ bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
+ bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
+
+ if (call_type == BLOCKING_CALL && client_streaming) {
+ // Blocking client interface with client streaming is not available
+ continue;
+ }
+
+ if (call_type == FUTURE_CALL && (client_streaming || server_streaming)) {
+ // Future interface doesn't support streaming.
+ continue;
+ }
+
+ // Method signature
+ p->Print("\n");
+ // TODO(nmittler): Replace with WriteMethodDocComment once included by the
+ // protobuf distro.
+ if (!interface) {
+ GrpcWriteMethodDocComment(p, vars, &*method);
+ }
+ p->Print("public ");
+ switch (call_type) {
+ case BLOCKING_CALL:
+ GRPC_CODEGEN_CHECK(!client_streaming)
+ << "Blocking client interface with client streaming is unavailable";
+ if (server_streaming) {
+ // Server streaming
+ p->Print(vars,
+ "$Iterator$<$output_type$> $lower_method_name$(\n"
+ " $input_type$ request)");
+ } else {
+ // Simple RPC
+ p->Print(vars,
+ "$output_type$ $lower_method_name$($input_type$ request)");
+ }
+ break;
+ case ASYNC_CALL:
+ if (client_streaming) {
+ // Bidirectional streaming or client streaming
+ p->Print(vars,
+ "$StreamObserver$<$input_type$> $lower_method_name$(\n"
+ " $StreamObserver$<$output_type$> responseObserver)");
+ } else {
+ // Server streaming or simple RPC
+ p->Print(vars,
+ "void $lower_method_name$($input_type$ request,\n"
+ " $StreamObserver$<$output_type$> responseObserver)");
+ }
+ break;
+ case FUTURE_CALL:
+ GRPC_CODEGEN_CHECK(!client_streaming && !server_streaming)
+ << "Future interface doesn't support streaming. "
+ << "client_streaming=" << client_streaming << ", "
+ << "server_streaming=" << server_streaming;
+ p->Print(vars,
+ "$ListenableFuture$<$output_type$> $lower_method_name$(\n"
+ " $input_type$ request)");
+ break;
+ }
+
+ if (interface) {
+ p->Print(";\n");
+ continue;
+ }
+ // Method body.
+ p->Print(" {\n");
+ p->Indent();
+ if (impl_base) {
+ switch (call_type) {
+ // NB: Skipping validation of service methods. If something is wrong,
+ // we wouldn't get to this point as compiler would return errors when
+ // generating service interface.
+ case ASYNC_CALL:
+ if (client_streaming) {
+ p->Print(vars,
+ "return "
+ "asyncUnimplementedStreamingCall($method_method_name$(), "
+ "responseObserver);\n");
+ } else {
+ p->Print(vars,
+ "asyncUnimplementedUnaryCall($method_method_name$(), "
+ "responseObserver);\n");
+ }
+ break;
+ default:
+ break;
+ }
+ } else if (!interface) {
+ switch (call_type) {
+ case BLOCKING_CALL:
+ GRPC_CODEGEN_CHECK(!client_streaming)
+ << "Blocking client streaming interface is not available";
+ if (server_streaming) {
+ vars["calls_method"] = "blockingServerStreamingCall";
+ vars["params"] = "request";
+ } else {
+ vars["calls_method"] = "blockingUnaryCall";
+ vars["params"] = "request";
+ }
+ p->Print(vars,
+ "return $calls_method$(\n"
+ " getChannel(), $method_method_name$(), "
+ "getCallOptions(), $params$);\n");
+ break;
+ case ASYNC_CALL:
+ if (server_streaming) {
+ if (client_streaming) {
+ vars["calls_method"] = "asyncBidiStreamingCall";
+ vars["params"] = "responseObserver";
+ } else {
+ vars["calls_method"] = "asyncServerStreamingCall";
+ vars["params"] = "request, responseObserver";
+ }
+ } else {
+ if (client_streaming) {
+ vars["calls_method"] = "asyncClientStreamingCall";
+ vars["params"] = "responseObserver";
+ } else {
+ vars["calls_method"] = "asyncUnaryCall";
+ vars["params"] = "request, responseObserver";
+ }
+ }
+ vars["last_line_prefix"] = client_streaming ? "return " : "";
+ p->Print(vars,
+ "$last_line_prefix$$calls_method$(\n"
+ " getChannel().newCall($method_method_name$(), "
+ "getCallOptions()), $params$);\n");
+ break;
+ case FUTURE_CALL:
+ GRPC_CODEGEN_CHECK(!client_streaming && !server_streaming)
+ << "Future interface doesn't support streaming. "
+ << "client_streaming=" << client_streaming << ", "
+ << "server_streaming=" << server_streaming;
+ vars["calls_method"] = "futureUnaryCall";
+ p->Print(vars,
+ "return $calls_method$(\n"
+ " getChannel().newCall($method_method_name$(), "
+ "getCallOptions()), request);\n");
+ break;
+ }
+ }
+ p->Outdent();
+ p->Print("}\n");
+ }
+
+ if (impl_base) {
+ p->Print("\n");
+ p->Print(
+ vars,
+ "@$Override$ public final $ServerServiceDefinition$ bindService() {\n");
+ vars["instance"] = "this";
+ PrintBindServiceMethodBody(p, vars, service);
+ p->Print("}\n");
+ }
+
+ p->Outdent();
+ p->Print("}\n\n");
+}
+
+static bool CompareMethodClientStreaming(
+ const std::unique_ptr<const grpc_generator::Method>& method1,
+ const std::unique_ptr<const grpc_generator::Method>& method2) {
+ return method1->ClientStreaming() < method2->ClientStreaming();
+}
+
+// Place all method invocations into a single class to reduce memory footprint
+// on Android.
+static void PrintMethodHandlerClass(Printer* p, VARS& vars,
+ const ServiceDescriptor* service) {
+ // Sort method ids based on ClientStreaming() so switch tables are compact.
+ std::vector<std::unique_ptr<const grpc_generator::Method>> sorted_methods(
+ service->method_count());
+ for (int i = 0; i < service->method_count(); ++i) {
+ sorted_methods[i] = service->method(i);
+ }
+ stable_sort(sorted_methods.begin(), sorted_methods.end(),
+ CompareMethodClientStreaming);
+ for (size_t i = 0; i < sorted_methods.size(); i++) {
+ auto& method = sorted_methods[i];
+ vars["method_id"] = to_string(i);
+ vars["method_id_name"] = MethodIdFieldName(&*method);
+ p->Print(vars,
+ "private static final int $method_id_name$ = $method_id$;\n");
+ }
+ p->Print("\n");
+ vars["service_name"] = service->name() + "ImplBase";
+ p->Print(vars,
+ "private static final class MethodHandlers<Req, Resp> implements\n"
+ " io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,\n"
+ " io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,\n"
+ " io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,\n"
+ " io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {\n"
+ " private final $service_name$ serviceImpl;\n"
+ " private final int methodId;\n"
+ "\n"
+ " MethodHandlers($service_name$ serviceImpl, int methodId) {\n"
+ " this.serviceImpl = serviceImpl;\n"
+ " this.methodId = methodId;\n"
+ " }\n\n");
+ p->Indent();
+ p->Print(vars,
+ "@$Override$\n"
+ "@java.lang.SuppressWarnings(\"unchecked\")\n"
+ "public void invoke(Req request, $StreamObserver$<Resp> "
+ "responseObserver) {\n"
+ " switch (methodId) {\n");
+ p->Indent();
+ p->Indent();
+
+ for (int i = 0; i < service->method_count(); ++i) {
+ auto method = service->method(i);
+ if (method->ClientStreaming() || method->BidiStreaming()) {
+ continue;
+ }
+ vars["method_id_name"] = MethodIdFieldName(&*method);
+ vars["lower_method_name"] = LowerMethodName(&*method);
+ vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
+ vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
+ p->Print(vars,
+ "case $method_id_name$:\n"
+ " serviceImpl.$lower_method_name$(($input_type$) request,\n"
+ " ($StreamObserver$<$output_type$>) responseObserver);\n"
+ " break;\n");
+ }
+ p->Print(
+ "default:\n"
+ " throw new AssertionError();\n");
+
+ p->Outdent();
+ p->Outdent();
+ p->Print(
+ " }\n"
+ "}\n\n");
+
+ p->Print(vars,
+ "@$Override$\n"
+ "@java.lang.SuppressWarnings(\"unchecked\")\n"
+ "public $StreamObserver$<Req> invoke(\n"
+ " $StreamObserver$<Resp> responseObserver) {\n"
+ " switch (methodId) {\n");
+ p->Indent();
+ p->Indent();
+
+ for (int i = 0; i < service->method_count(); ++i) {
+ auto method = service->method(i);
+ if (!(method->ClientStreaming() || method->BidiStreaming())) {
+ continue;
+ }
+ vars["method_id_name"] = MethodIdFieldName(&*method);
+ vars["lower_method_name"] = LowerMethodName(&*method);
+ vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
+ vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
+ p->Print(
+ vars,
+ "case $method_id_name$:\n"
+ " return ($StreamObserver$<Req>) serviceImpl.$lower_method_name$(\n"
+ " ($StreamObserver$<$output_type$>) responseObserver);\n");
+ }
+ p->Print(
+ "default:\n"
+ " throw new AssertionError();\n");
+
+ p->Outdent();
+ p->Outdent();
+ p->Print(
+ " }\n"
+ "}\n");
+
+ p->Outdent();
+ p->Print("}\n\n");
+}
+
+static void PrintGetServiceDescriptorMethod(Printer* p, VARS& vars,
+ const ServiceDescriptor* service) {
+ vars["service_name"] = service->name();
+ // vars["proto_base_descriptor_supplier"] = service->name() +
+ // "BaseDescriptorSupplier"; vars["proto_file_descriptor_supplier"] =
+ // service->name() + "FileDescriptorSupplier";
+ // vars["proto_method_descriptor_supplier"] = service->name() +
+ // "MethodDescriptorSupplier"; vars["proto_class_name"] =
+ // google::protobuf::compiler::java::ClassName(service->file());
+ // p->Print(
+ // vars,
+ // "private static abstract class
+ // $proto_base_descriptor_supplier$\n" " implements
+ // $ProtoFileDescriptorSupplier$,
+ // $ProtoServiceDescriptorSupplier$ {\n" "
+ // $proto_base_descriptor_supplier$() {}\n"
+ // "\n"
+ // " @$Override$\n"
+ // " public com.google.protobuf.Descriptors.FileDescriptor
+ // getFileDescriptor() {\n" " return
+ // $proto_class_name$.getDescriptor();\n" " }\n"
+ // "\n"
+ // " @$Override$\n"
+ // " public com.google.protobuf.Descriptors.ServiceDescriptor
+ // getServiceDescriptor() {\n" " return
+ // getFileDescriptor().findServiceByName(\"$service_name$\");\n"
+ // " }\n"
+ // "}\n"
+ // "\n"
+ // "private static final class
+ // $proto_file_descriptor_supplier$\n" " extends
+ // $proto_base_descriptor_supplier$ {\n" "
+ // $proto_file_descriptor_supplier$() {}\n"
+ // "}\n"
+ // "\n"
+ // "private static final class
+ // $proto_method_descriptor_supplier$\n" " extends
+ // $proto_base_descriptor_supplier$\n" " implements
+ // $ProtoMethodDescriptorSupplier$ {\n" " private final
+ // String methodName;\n"
+ // "\n"
+ // " $proto_method_descriptor_supplier$(String methodName)
+ // {\n" " this.methodName = methodName;\n" " }\n"
+ // "\n"
+ // " @$Override$\n"
+ // " public com.google.protobuf.Descriptors.MethodDescriptor
+ // getMethodDescriptor() {\n" " return
+ // getServiceDescriptor().findMethodByName(methodName);\n" "
+ // }\n"
+ // "}\n\n");
+
+ p->Print(
+ vars,
+ "private static volatile $ServiceDescriptor$ serviceDescriptor;\n\n");
+
+ p->Print(vars,
+ "public static $ServiceDescriptor$ getServiceDescriptor() {\n");
+ p->Indent();
+ p->Print(vars, "$ServiceDescriptor$ result = serviceDescriptor;\n");
+ p->Print("if (result == null) {\n");
+ p->Indent();
+ p->Print(vars, "synchronized ($service_class_name$.class) {\n");
+ p->Indent();
+ p->Print("result = serviceDescriptor;\n");
+ p->Print("if (result == null) {\n");
+ p->Indent();
+
+ p->Print(vars,
+ "serviceDescriptor = result = "
+ "$ServiceDescriptor$.newBuilder(SERVICE_NAME)");
+ p->Indent();
+ p->Indent();
+ p->Print(vars, "\n.setSchemaDescriptor(null)");
+ for (int i = 0; i < service->method_count(); ++i) {
+ auto method = service->method(i);
+ vars["method_method_name"] = MethodPropertiesGetterName(&*method);
+ p->Print(vars, "\n.addMethod($method_method_name$())");
+ }
+ p->Print("\n.build();\n");
+ p->Outdent();
+ p->Outdent();
+
+ p->Outdent();
+ p->Print("}\n");
+ p->Outdent();
+ p->Print("}\n");
+ p->Outdent();
+ p->Print("}\n");
+ p->Print("return result;\n");
+ p->Outdent();
+ p->Print("}\n");
+}
+
+static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
+ const ServiceDescriptor* service) {
+ vars["service_name"] = service->name();
+ p->Indent();
+ p->Print(vars,
+ "return "
+ "$ServerServiceDefinition$.builder(getServiceDescriptor())\n");
+ p->Indent();
+ p->Indent();
+ for (int i = 0; i < service->method_count(); ++i) {
+ auto method = service->method(i);
+ vars["lower_method_name"] = LowerMethodName(&*method);
+ vars["method_method_name"] = MethodPropertiesGetterName(&*method);
+ vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
+ vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
+ vars["method_id_name"] = MethodIdFieldName(&*method);
+ bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
+ bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
+ if (client_streaming) {
+ if (server_streaming) {
+ vars["calls_method"] = "asyncBidiStreamingCall";
+ } else {
+ vars["calls_method"] = "asyncClientStreamingCall";
+ }
+ } else {
+ if (server_streaming) {
+ vars["calls_method"] = "asyncServerStreamingCall";
+ } else {
+ vars["calls_method"] = "asyncUnaryCall";
+ }
+ }
+ p->Print(vars, ".addMethod(\n");
+ p->Indent();
+ p->Print(vars,
+ "$method_method_name$(),\n"
+ "$calls_method$(\n");
+ p->Indent();
+ p->Print(vars,
+ "new MethodHandlers<\n"
+ " $input_type$,\n"
+ " $output_type$>(\n"
+ " $instance$, $method_id_name$)))\n");
+ p->Outdent();
+ p->Outdent();
+ }
+ p->Print(".build();\n");
+ p->Outdent();
+ p->Outdent();
+ p->Outdent();
+}
+
+static void PrintService(Printer* p, VARS& vars,
+ const ServiceDescriptor* service,
+ bool disable_version) {
+ vars["service_name"] = service->name();
+ vars["service_class_name"] = ServiceClassName(service->name());
+ vars["grpc_version"] = "";
+#ifdef GRPC_VERSION
+ if (!disable_version) {
+ vars["grpc_version"] = " (version " XSTR(GRPC_VERSION) ")";
+ }
+#else
+ (void)disable_version;
+#endif
+ // TODO(nmittler): Replace with WriteServiceDocComment once included by
+ // protobuf distro.
+ GrpcWriteServiceDocComment(p, vars, service);
+ p->Print(vars,
+ "@$Generated$(\n"
+ " value = \"by gRPC proto compiler$grpc_version$\",\n"
+ " comments = \"Source: $file_name$.fbs\")\n"
+ "public final class $service_class_name$ {\n\n");
+ p->Indent();
+ p->Print(vars, "private $service_class_name$() {}\n\n");
+
+ p->Print(vars,
+ "public static final String SERVICE_NAME = "
+ "\"$Package$$service_name$\";\n\n");
+
+ PrintMethodFields(p, vars, service);
+
+ // TODO(nmittler): Replace with WriteDocComment once included by protobuf
+ // distro.
+ GrpcWriteDocComment(
+ p, vars,
+ " Creates a new async stub that supports all call types for the service");
+ p->Print(vars,
+ "public static $service_name$Stub newStub($Channel$ channel) {\n");
+ p->Indent();
+ p->Print(vars, "return new $service_name$Stub(channel);\n");
+ p->Outdent();
+ p->Print("}\n\n");
+
+ // TODO(nmittler): Replace with WriteDocComment once included by protobuf
+ // distro.
+ GrpcWriteDocComment(
+ p, vars,
+ " Creates a new blocking-style stub that supports unary and streaming "
+ "output calls on the service");
+ p->Print(vars,
+ "public static $service_name$BlockingStub newBlockingStub(\n"
+ " $Channel$ channel) {\n");
+ p->Indent();
+ p->Print(vars, "return new $service_name$BlockingStub(channel);\n");
+ p->Outdent();
+ p->Print("}\n\n");
+
+ // TODO(nmittler): Replace with WriteDocComment once included by protobuf
+ // distro.
+ GrpcWriteDocComment(
+ p, vars,
+ " Creates a new ListenableFuture-style stub that supports unary calls "
+ "on the service");
+ p->Print(vars,
+ "public static $service_name$FutureStub newFutureStub(\n"
+ " $Channel$ channel) {\n");
+ p->Indent();
+ p->Print(vars, "return new $service_name$FutureStub(channel);\n");
+ p->Outdent();
+ p->Print("}\n\n");
+
+ PrintStub(p, vars, service, ABSTRACT_CLASS);
+ PrintStub(p, vars, service, ASYNC_CLIENT_IMPL);
+ PrintStub(p, vars, service, BLOCKING_CLIENT_IMPL);
+ PrintStub(p, vars, service, FUTURE_CLIENT_IMPL);
+
+ PrintMethodHandlerClass(p, vars, service);
+ PrintGetServiceDescriptorMethod(p, vars, service);
+ p->Outdent();
+ p->Print("}\n");
+}
+
+void PrintStaticImports(Printer* p) {
+ p->Print(
+ "import java.nio.ByteBuffer;\n"
+ "import static "
+ "io.grpc.MethodDescriptor.generateFullMethodName;\n"
+ "import static "
+ "io.grpc.stub.ClientCalls.asyncBidiStreamingCall;\n"
+ "import static "
+ "io.grpc.stub.ClientCalls.asyncClientStreamingCall;\n"
+ "import static "
+ "io.grpc.stub.ClientCalls.asyncServerStreamingCall;\n"
+ "import static "
+ "io.grpc.stub.ClientCalls.asyncUnaryCall;\n"
+ "import static "
+ "io.grpc.stub.ClientCalls.blockingServerStreamingCall;\n"
+ "import static "
+ "io.grpc.stub.ClientCalls.blockingUnaryCall;\n"
+ "import static "
+ "io.grpc.stub.ClientCalls.futureUnaryCall;\n"
+ "import static "
+ "io.grpc.stub.ServerCalls.asyncBidiStreamingCall;\n"
+ "import static "
+ "io.grpc.stub.ServerCalls.asyncClientStreamingCall;\n"
+ "import static "
+ "io.grpc.stub.ServerCalls.asyncServerStreamingCall;\n"
+ "import static "
+ "io.grpc.stub.ServerCalls.asyncUnaryCall;\n"
+ "import static "
+ "io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;\n"
+ "import static "
+ "io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n\n");
+}
+
+void GenerateService(const grpc_generator::Service* service,
+ grpc_generator::Printer* printer, VARS& vars,
+ bool disable_version) {
+ // All non-generated classes must be referred by fully qualified names to
+ // avoid collision with generated classes.
+ vars["String"] = "java.lang.String";
+ vars["Deprecated"] = "java.lang.Deprecated";
+ vars["Override"] = "java.lang.Override";
+ vars["Channel"] = "io.grpc.Channel";
+ vars["CallOptions"] = "io.grpc.CallOptions";
+ vars["MethodType"] = "io.grpc.MethodDescriptor.MethodType";
+ vars["ServerMethodDefinition"] = "io.grpc.ServerMethodDefinition";
+ vars["BindableService"] = "io.grpc.BindableService";
+ vars["ServerServiceDefinition"] = "io.grpc.ServerServiceDefinition";
+ vars["ServiceDescriptor"] = "io.grpc.ServiceDescriptor";
+ vars["ProtoFileDescriptorSupplier"] =
+ "io.grpc.protobuf.ProtoFileDescriptorSupplier";
+ vars["ProtoServiceDescriptorSupplier"] =
+ "io.grpc.protobuf.ProtoServiceDescriptorSupplier";
+ vars["ProtoMethodDescriptorSupplier"] =
+ "io.grpc.protobuf.ProtoMethodDescriptorSupplier";
+ vars["AbstractStub"] = "io.grpc.stub.AbstractStub";
+ vars["MethodDescriptor"] = "io.grpc.MethodDescriptor";
+ vars["NanoUtils"] = "io.grpc.protobuf.nano.NanoUtils";
+ vars["StreamObserver"] = "io.grpc.stub.StreamObserver";
+ vars["Iterator"] = "java.util.Iterator";
+ vars["Generated"] = "javax.annotation.Generated";
+ vars["ListenableFuture"] =
+ "com.google.common.util.concurrent.ListenableFuture";
+ vars["ExperimentalApi"] = "io.grpc.ExperimentalApi";
+
+ PrintStaticImports(printer);
+
+ PrintService(printer, vars, service, disable_version);
+}
+
+grpc::string GenerateServiceSource(
+ grpc_generator::File* file, const grpc_generator::Service* service,
+ grpc_java_generator::Parameters* parameters) {
+ grpc::string out;
+ auto printer = file->CreatePrinter(&out);
+ VARS vars;
+ vars["flatc_version"] = grpc::string(
+ FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "." FLATBUFFERS_STRING(
+ FLATBUFFERS_VERSION_MINOR) "." FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION));
+
+ vars["file_name"] = file->filename();
+
+ if (!parameters->package_name.empty()) {
+ vars["Package"] = parameters->package_name; // ServiceJavaPackage(service);
+ }
+ GenerateImports(file, &*printer, vars);
+ GenerateService(service, &*printer, vars, false);
+ return out;
+}
+
+} // namespace grpc_java_generator
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.h
new file mode 100644
index 0000000000..b101fbf565
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef NET_GRPC_COMPILER_JAVA_GENERATOR_H_
+#define NET_GRPC_COMPILER_JAVA_GENERATOR_H_
+
+#include <stdlib.h> // for abort()
+#include <iostream>
+#include <map>
+#include <string>
+
+#include "src/compiler/schema_interface.h"
+
+class LogMessageVoidify {
+ public:
+ LogMessageVoidify() {}
+ // This has to be an operator with a precedence lower than << but
+ // higher than ?:
+ void operator&(std::ostream&) {}
+};
+
+class LogHelper {
+ std::ostream* os_;
+
+ public:
+ LogHelper(std::ostream* os) : os_(os) {}
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning( \
+ disable : 4722) // the flow of control terminates in a destructor
+ // (needed to compile ~LogHelper where destructor emits abort intentionally -
+ // inherited from grpc/java code generator).
+#endif
+ ~LogHelper() {
+ *os_ << std::endl;
+ ::abort();
+ }
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+ std::ostream& get_os() const { return *os_; }
+};
+
+// Abort the program after logging the mesage if the given condition is not
+// true. Otherwise, do nothing.
+#define GRPC_CODEGEN_CHECK(x) \
+ (x) ? (void)0 \
+ : LogMessageVoidify() & LogHelper(&std::cerr).get_os() \
+ << "CHECK FAILED: " << __FILE__ << ":" \
+ << __LINE__ << ": "
+
+// Abort the program after logging the mesage.
+#define GRPC_CODEGEN_FAIL GRPC_CODEGEN_CHECK(false)
+
+namespace grpc_java_generator {
+struct Parameters {
+ // //Defines the custom parameter types for methods
+ // //eg: flatbuffers uses flatbuffers.Builder as input for the client
+ // and output for the server grpc::string custom_method_io_type;
+
+ // Package name for the service
+ grpc::string package_name;
+};
+
+// Return the source of the generated service file.
+grpc::string GenerateServiceSource(grpc_generator::File* file,
+ const grpc_generator::Service* service,
+ grpc_java_generator::Parameters* parameters);
+
+} // namespace grpc_java_generator
+
+#endif // NET_GRPC_COMPILER_JAVA_GENERATOR_H_
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc
new file mode 100644
index 0000000000..8108db45d5
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc
@@ -0,0 +1,149 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * 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.
+ *
+ */
+
+#include <map>
+#include <sstream>
+
+#include "flatbuffers/util.h"
+#include "src/compiler/python_generator.h"
+
+namespace grpc_python_generator {
+
+grpc::string GenerateMethodType(const grpc_generator::Method *method) {
+
+ if (method->NoStreaming())
+ return "unary_unary";
+
+ if (method->ServerStreaming())
+ return "unary_stream";
+
+ if (method->ClientStreaming())
+ return "stream_unary";
+
+ return "stream_stream";
+}
+
+grpc::string GenerateMethodInput(const grpc_generator::Method *method) {
+
+ if (method->NoStreaming() || method->ServerStreaming())
+ return "self, request, context";
+
+ return "self, request_iterator, context";
+}
+
+void GenerateStub(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars, "class $ServiceName$Stub(object):\n");
+ printer->Indent();
+ printer->Print("\"\"\" Interface exported by the server. \"\"\"");
+ printer->Print("\n\n");
+ printer->Print("def __init__(self, channel):\n");
+ printer->Indent();
+ printer->Print("\"\"\" Constructor. \n\n");
+ printer->Print("Args: \n");
+ printer->Print("channel: A grpc.Channel. \n");
+ printer->Print("\"\"\"\n\n");
+
+ for (int j = 0; j < service->method_count(); j++) {
+ auto method = service->method(j);
+ vars["MethodName"] = method->name();
+ vars["MethodType"] = GenerateMethodType(&*method);
+ printer->Print(vars, "self.$MethodName$ = channel.$MethodType$(\n");
+ printer->Indent();
+ printer->Print(vars, "\"/$PATH$$ServiceName$/$MethodName$\"\n");
+ printer->Print(")\n");
+ printer->Outdent();
+ printer->Print("\n");
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print("\n");
+}
+
+void GenerateServicer(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars, "class $ServiceName$Servicer(object):\n");
+ printer->Indent();
+ printer->Print("\"\"\" Interface exported by the server. \"\"\"");
+ printer->Print("\n\n");
+
+ for (int j = 0; j < service->method_count(); j++) {
+ auto method = service->method(j);
+ vars["MethodName"] = method->name();
+ vars["MethodInput"] = GenerateMethodInput(&*method);
+ printer->Print(vars, "def $MethodName$($MethodInput$):\n");
+ printer->Indent();
+ printer->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
+ printer->Print("context.set_details('Method not implemented!')\n");
+ printer->Print("raise NotImplementedError('Method not implemented!')\n");
+ printer->Outdent();
+ printer->Print("\n\n");
+ }
+ printer->Outdent();
+ printer->Print("\n");
+
+}
+
+void GenerateRegister(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars, "def add_$ServiceName$Servicer_to_server(servicer, server):\n");
+ printer->Indent();
+ printer->Print("rpc_method_handlers = {\n");
+ printer->Indent();
+ for (int j = 0; j < service->method_count(); j++) {
+ auto method = service->method(j);
+ vars["MethodName"] = method->name();
+ vars["MethodType"] = GenerateMethodType(&*method);
+ printer->Print(vars, "'$MethodName$': grpc.$MethodType$_rpc_method_handler(\n");
+ printer->Indent();
+ printer->Print(vars, "servicer.$MethodName$\n");
+ printer->Outdent();
+ printer->Print("),\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print(vars, "generic_handler = grpc.method_handlers_generic_handler(\n");
+ printer->Indent();
+ printer->Print(vars, "'$PATH$$ServiceName$', rpc_method_handlers)\n");
+ printer->Outdent();
+ printer->Print("server.add_generic_rpc_handlers((generic_handler,))");
+ printer->Outdent();
+ printer->Print("\n");
+}
+
+grpc::string Generate(grpc_generator::File *file,
+ const grpc_generator::Service *service) {
+ grpc::string output;
+ std::map<grpc::string, grpc::string> vars;
+ vars["PATH"] = file->package();
+ if (!file->package().empty()) { vars["PATH"].append("."); }
+ vars["ServiceName"] = service->name();
+ auto printer = file->CreatePrinter(&output);
+ GenerateStub(service, &*printer, &vars);
+ GenerateServicer(service, &*printer, &vars);
+ GenerateRegister(service, &*printer, &vars);
+ return output;
+}
+
+} // namespace grpc_python_generator
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h
new file mode 100644
index 0000000000..4f8f5cc806
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * 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.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
+#define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
+
+#include <utility>
+
+#include "src/compiler/config.h"
+#include "src/compiler/schema_interface.h"
+
+namespace grpc_python_generator {
+
+grpc::string Generate(grpc_generator::File *file,
+ const grpc_generator::Service *service);
+} // namespace grpc_python_generator
+
+#endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h b/contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h
new file mode 100644
index 0000000000..0449498198
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h
@@ -0,0 +1,120 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * 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.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
+#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
+
+#include <memory>
+#include <vector>
+
+#include "src/compiler/config.h"
+
+#ifndef GRPC_CUSTOM_STRING
+# include <string>
+# define GRPC_CUSTOM_STRING std::string
+#endif
+
+namespace grpc {
+
+typedef GRPC_CUSTOM_STRING string;
+
+} // namespace grpc
+
+namespace grpc_generator {
+
+// A common interface for objects having comments in the source.
+// Return formatted comments to be inserted in generated code.
+struct CommentHolder {
+ virtual ~CommentHolder() {}
+ virtual grpc::string GetLeadingComments(const grpc::string prefix) const = 0;
+ virtual grpc::string GetTrailingComments(const grpc::string prefix) const = 0;
+ virtual std::vector<grpc::string> GetAllComments() const = 0;
+};
+
+// An abstract interface representing a method.
+struct Method : public CommentHolder {
+ virtual ~Method() {}
+
+ virtual grpc::string name() const = 0;
+
+ virtual grpc::string input_type_name() const = 0;
+ virtual grpc::string output_type_name() const = 0;
+
+ virtual bool get_module_and_message_path_input(
+ grpc::string *str, grpc::string generator_file_name,
+ bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0;
+ virtual bool get_module_and_message_path_output(
+ grpc::string *str, grpc::string generator_file_name,
+ bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0;
+
+ virtual std::vector<grpc::string> get_input_namespace_parts() const = 0;
+ virtual grpc::string get_input_type_name() const = 0;
+ virtual std::vector<grpc::string> get_output_namespace_parts() const = 0;
+ virtual grpc::string get_output_type_name() const = 0;
+
+ virtual grpc::string get_fb_builder() const = 0;
+
+ virtual bool NoStreaming() const = 0;
+ virtual bool ClientStreaming() const = 0;
+ virtual bool ServerStreaming() const = 0;
+ virtual bool BidiStreaming() const = 0;
+};
+
+// An abstract interface representing a service.
+struct Service : public CommentHolder {
+ virtual ~Service() {}
+
+ virtual std::vector<grpc::string> namespace_parts() const = 0;
+ virtual grpc::string name() const = 0;
+ virtual bool is_internal() const = 0;
+
+ virtual int method_count() const = 0;
+ virtual std::unique_ptr<const Method> method(int i) const = 0;
+};
+
+struct Printer {
+ virtual ~Printer() {}
+
+ virtual void Print(const std::map<grpc::string, grpc::string> &vars,
+ const char *template_string) = 0;
+ virtual void Print(const char *string) = 0;
+ virtual void SetIndentationSize(const int size) = 0;
+ virtual void Indent() = 0;
+ virtual void Outdent() = 0;
+};
+
+// An interface that allows the source generated to be output using various
+// libraries/idls/serializers.
+struct File : public CommentHolder {
+ virtual ~File() {}
+
+ virtual grpc::string filename() const = 0;
+ virtual grpc::string filename_without_ext() const = 0;
+ virtual grpc::string package() const = 0;
+ virtual std::vector<grpc::string> package_parts() const = 0;
+ virtual grpc::string additional_headers() const = 0;
+
+ virtual int service_count() const = 0;
+ virtual std::unique_ptr<const Service> service(int i) const = 0;
+
+ virtual std::unique_ptr<Printer> CreatePrinter(
+ grpc::string *str, const char indentation_type = ' ') const = 0;
+};
+} // namespace grpc_generator
+
+#endif // GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc
new file mode 100644
index 0000000000..403a803ef1
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc
@@ -0,0 +1,438 @@
+/*
+ * Copyright 2020 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.
+ */
+
+/*
+ * NOTE: The following implementation is a translation for the Swift-grpc
+ * generator since flatbuffers doesnt allow plugins for now. if an issue arises
+ * please open an issue in the flatbuffers repository. This file should always
+ * be maintained according to the Swift-grpc repository
+ */
+#include <map>
+#include <sstream>
+
+#include "flatbuffers/util.h"
+#include "src/compiler/schema_interface.h"
+#include "src/compiler/swift_generator.h"
+
+namespace grpc_swift_generator {
+
+std::string WrapInNameSpace(const std::vector<std::string> &components,
+ const grpc::string &name) {
+ std::string qualified_name;
+ for (auto it = components.begin(); it != components.end(); ++it)
+ qualified_name += *it + "_";
+ return qualified_name + name;
+}
+
+grpc::string GenerateMessage(const std::vector<std::string> &components,
+ const grpc::string &name) {
+ return "Message<" + WrapInNameSpace(components, name) + ">";
+}
+
+// MARK: - Client
+
+void GenerateClientFuncName(const grpc_generator::Method *method,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ if (method->NoStreaming()) {
+ printer->Print(vars,
+ " $GenAccess$func $MethodName$(\n"
+ " _ request: $Input$\n"
+ " , callOptions: CallOptions?$isNil$\n"
+ " ) -> UnaryCall<$Input$, $Output$>");
+ return;
+ }
+
+ if (method->ServerStreaming()) {
+ printer->Print(vars,
+ " $GenAccess$func $MethodName$(\n"
+ " _ request: $Input$\n"
+ " , callOptions: CallOptions?$isNil$,\n"
+ " handler: @escaping ($Output$) -> Void\n"
+ " ) -> ServerStreamingCall<$Input$, $Output$>");
+ return;
+ }
+
+ if (method->ClientStreaming()) {
+ printer->Print(vars,
+ " $GenAccess$func $MethodName$(\n"
+ " callOptions: CallOptions?$isNil$\n"
+ " ) -> ClientStreamingCall<$Input$, $Output$>");
+ return;
+ }
+
+ printer->Print(vars,
+ " $GenAccess$func $MethodName$(\n"
+ " callOptions: CallOptions?$isNil$,\n"
+ " handler: @escaping ($Output$ ) -> Void\n"
+ " ) -> BidirectionalStreamingCall<$Input$, $Output$>");
+}
+
+void GenerateClientFuncBody(const grpc_generator::Method *method,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ vars["Interceptor"] =
+ "interceptors: self.interceptors?.make$MethodName$Interceptors() ?? []";
+ if (method->NoStreaming()) {
+ printer->Print(
+ vars,
+ " return self.makeUnaryCall(\n"
+ " path: \"/$PATH$$ServiceName$/$MethodName$\",\n"
+ " request: request,\n"
+ " callOptions: callOptions ?? self.defaultCallOptions,\n"
+ " $Interceptor$\n"
+ " )\n");
+ return;
+ }
+
+ if (method->ServerStreaming()) {
+ printer->Print(
+ vars,
+ " return self.makeServerStreamingCall(\n"
+ " path: \"/$PATH$$ServiceName$/$MethodName$\",\n"
+ " request: request,\n"
+ " callOptions: callOptions ?? self.defaultCallOptions,\n"
+ " $Interceptor$,\n"
+ " handler: handler\n"
+ " )\n");
+ return;
+ }
+
+ if (method->ClientStreaming()) {
+ printer->Print(
+ vars,
+ " return self.makeClientStreamingCall(\n"
+ " path: \"/$PATH$$ServiceName$/$MethodName$\",\n"
+ " callOptions: callOptions ?? self.defaultCallOptions,\n"
+ " $Interceptor$\n"
+ " )\n");
+ return;
+ }
+ printer->Print(vars,
+ " return self.makeBidirectionalStreamingCall(\n"
+ " path: \"/$PATH$$ServiceName$/$MethodName$\",\n"
+ " callOptions: callOptions ?? self.defaultCallOptions,\n"
+ " $Interceptor$,\n"
+ " handler: handler\n"
+ " )\n");
+}
+
+void GenerateClientProtocol(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(
+ vars,
+ "$ACCESS$ protocol $ServiceQualifiedName$ClientProtocol: GRPCClient {");
+ printer->Print("\n\n");
+ printer->Print(" var serviceName: String { get }");
+ printer->Print("\n\n");
+ printer->Print(
+ vars,
+ " var interceptors: "
+ "$ServiceQualifiedName$ClientInterceptorFactoryProtocol? { get }");
+ printer->Print("\n\n");
+
+ vars["GenAccess"] = "";
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["Input"] = GenerateMessage(method->get_input_namespace_parts(),
+ method->get_input_type_name());
+ vars["Output"] = GenerateMessage(method->get_output_namespace_parts(),
+ method->get_output_type_name());
+ vars["MethodName"] = method->name();
+ vars["isNil"] = "";
+ GenerateClientFuncName(method.get(), &*printer, &vars);
+ printer->Print("\n\n");
+ }
+ printer->Print("}\n\n");
+
+ printer->Print(vars, "extension $ServiceQualifiedName$ClientProtocol {");
+ printer->Print("\n\n");
+ printer->Print(vars,
+ " $ACCESS$ var serviceName: String { "
+ "\"$PATH$$ServiceName$\" }\n");
+
+ vars["GenAccess"] = service->is_internal() ? "internal " : "public ";
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["Input"] = GenerateMessage(method->get_input_namespace_parts(),
+ method->get_input_type_name());
+ vars["Output"] = GenerateMessage(method->get_output_namespace_parts(),
+ method->get_output_type_name());
+ vars["MethodName"] = method->name();
+ vars["isNil"] = " = nil";
+ printer->Print("\n");
+ GenerateClientFuncName(method.get(), &*printer, &vars);
+ printer->Print(" {\n");
+ GenerateClientFuncBody(method.get(), &*printer, &vars);
+ printer->Print(" }\n");
+ }
+ printer->Print("}\n\n");
+
+ printer->Print(vars,
+ "$ACCESS$ protocol "
+ "$ServiceQualifiedName$ClientInterceptorFactoryProtocol {\n");
+
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["Input"] = GenerateMessage(method->get_input_namespace_parts(),
+ method->get_input_type_name());
+ vars["Output"] = GenerateMessage(method->get_output_namespace_parts(),
+ method->get_output_type_name());
+ vars["MethodName"] = method->name();
+ printer->Print(
+ vars,
+ " /// - Returns: Interceptors to use when invoking '$MethodName$'.\n");
+ printer->Print(vars,
+ " func make$MethodName$Interceptors() -> "
+ "[ClientInterceptor<$Input$, $Output$>]\n\n");
+ }
+ printer->Print("}\n\n");
+}
+
+void GenerateClientClass(grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars,
+ "$ACCESS$ final class $ServiceQualifiedName$ServiceClient: "
+ "$ServiceQualifiedName$ClientProtocol {\n");
+ printer->Print(vars, " $ACCESS$ let channel: GRPCChannel\n");
+ printer->Print(vars, " $ACCESS$ var defaultCallOptions: CallOptions\n");
+ printer->Print(vars,
+ " $ACCESS$ var interceptors: "
+ "$ServiceQualifiedName$ClientInterceptorFactoryProtocol?\n");
+ printer->Print("\n");
+ printer->Print(
+ vars,
+ " $ACCESS$ init(\n"
+ " channel: GRPCChannel,\n"
+ " defaultCallOptions: CallOptions = CallOptions(),\n"
+ " interceptors: "
+ "$ServiceQualifiedName$ClientInterceptorFactoryProtocol? = nil\n"
+ " ) {\n");
+ printer->Print(" self.channel = channel\n");
+ printer->Print(" self.defaultCallOptions = defaultCallOptions\n");
+ printer->Print(" self.interceptors = interceptors\n");
+ printer->Print(" }");
+ printer->Print("\n");
+ printer->Print("}\n");
+}
+
+// MARK: - Server
+
+grpc::string GenerateServerFuncName(const grpc_generator::Method *method) {
+ if (method->NoStreaming()) {
+ return "func $MethodName$(request: $Input$"
+ ", context: StatusOnlyCallContext) -> EventLoopFuture<$Output$>";
+ }
+
+ if (method->ClientStreaming()) {
+ return "func $MethodName$(context: UnaryResponseCallContext<$Output$>) -> "
+ "EventLoopFuture<(StreamEvent<$Input$"
+ ">) -> Void>";
+ }
+
+ if (method->ServerStreaming()) {
+ return "func $MethodName$(request: $Input$"
+ ", context: StreamingResponseCallContext<$Output$>) -> "
+ "EventLoopFuture<GRPCStatus>";
+ }
+ return "func $MethodName$(context: StreamingResponseCallContext<$Output$>) "
+ "-> EventLoopFuture<(StreamEvent<$Input$>) -> Void>";
+}
+
+grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) {
+ grpc::string start = " case \"$MethodName$\":\n ";
+ grpc::string interceptors =
+ " interceptors: self.interceptors?.make$MethodName$Interceptors() "
+ "?? [],\n";
+ if (method->NoStreaming()) {
+ return start +
+ "return UnaryServerHandler(\n"
+ " context: context,\n"
+ " requestDeserializer: GRPCPayloadDeserializer<$Input$>(),\n"
+ " responseSerializer: GRPCPayloadSerializer<$Output$>(),\n" +
+ interceptors +
+ " userFunction: self.$MethodName$(request:context:))\n";
+ }
+ if (method->ServerStreaming()) {
+ return start +
+ "return ServerStreamingServerHandler(\n"
+ " context: context,\n"
+ " requestDeserializer: GRPCPayloadDeserializer<$Input$>(),\n"
+ " responseSerializer: GRPCPayloadSerializer<$Output$>(),\n" +
+ interceptors +
+ " userFunction: self.$MethodName$(request:context:))\n";
+ }
+ if (method->ClientStreaming()) {
+ return start +
+ "return ClientStreamingServerHandler(\n"
+ " context: context,\n"
+ " requestDeserializer: GRPCPayloadDeserializer<$Input$>(),\n"
+ " responseSerializer: GRPCPayloadSerializer<$Output$>(),\n" +
+ interceptors +
+ " observerFactory: self.$MethodName$(context:))\n";
+ }
+ if (method->BidiStreaming()) {
+ return start +
+ "return BidirectionalStreamingServerHandler(\n"
+ " context: context,\n"
+ " requestDeserializer: GRPCPayloadDeserializer<$Input$>(),\n"
+ " responseSerializer: GRPCPayloadSerializer<$Output$>(),\n" +
+ interceptors +
+ " observerFactory: self.$MethodName$(context:))\n";
+ }
+ return "";
+}
+
+void GenerateServerProtocol(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars,
+ "$ACCESS$ protocol $ServiceQualifiedName$Provider: "
+ "CallHandlerProvider {\n");
+ printer->Print(
+ vars,
+ " var interceptors: "
+ "$ServiceQualifiedName$ServerInterceptorFactoryProtocol? { get }\n");
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["Input"] = GenerateMessage(method->get_input_namespace_parts(),
+ method->get_input_type_name());
+ vars["Output"] = GenerateMessage(method->get_output_namespace_parts(),
+ method->get_output_type_name());
+ vars["MethodName"] = method->name();
+ printer->Print(" ");
+ auto func = GenerateServerFuncName(method.get());
+ printer->Print(vars, func.c_str());
+ printer->Print("\n");
+ }
+ printer->Print("}\n\n");
+
+ printer->Print(vars, "$ACCESS$ extension $ServiceQualifiedName$Provider {\n");
+ printer->Print("\n");
+ printer->Print(vars,
+ " var serviceName: Substring { return "
+ "\"$PATH$$ServiceName$\" }\n");
+ printer->Print("\n");
+ printer->Print(
+ " func handle(method name: Substring, context: "
+ "CallHandlerContext) -> GRPCServerHandlerProtocol? {\n");
+ printer->Print(" switch name {\n");
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["Input"] = GenerateMessage(method->get_input_namespace_parts(),
+ method->get_input_type_name());
+ vars["Output"] = GenerateMessage(method->get_output_namespace_parts(),
+ method->get_output_type_name());
+ vars["MethodName"] = method->name();
+ auto body = GenerateServerExtensionBody(method.get());
+ printer->Print(vars, body.c_str());
+ printer->Print("\n");
+ }
+ printer->Print(" default: return nil;\n");
+ printer->Print(" }\n");
+ printer->Print(" }\n\n");
+ printer->Print("}\n\n");
+
+ printer->Print(vars,
+ "$ACCESS$ protocol "
+ "$ServiceQualifiedName$ServerInterceptorFactoryProtocol {\n");
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["Input"] = GenerateMessage(method->get_input_namespace_parts(),
+ method->get_input_type_name());
+ vars["Output"] = GenerateMessage(method->get_output_namespace_parts(),
+ method->get_output_type_name());
+ vars["MethodName"] = method->name();
+ printer->Print(
+ vars,
+ " /// - Returns: Interceptors to use when handling '$MethodName$'.\n"
+ " /// Defaults to calling `self.makeInterceptors()`.\n");
+ printer->Print(vars,
+ " func make$MethodName$Interceptors() -> "
+ "[ServerInterceptor<$Input$, $Output$>]\n\n");
+ }
+ printer->Print("}");
+}
+
+grpc::string Generate(grpc_generator::File *file,
+ const grpc_generator::Service *service) {
+ grpc::string output;
+ std::map<grpc::string, grpc::string> vars;
+ vars["PATH"] = file->package();
+ if (!file->package().empty()) { vars["PATH"].append("."); }
+ vars["ServiceQualifiedName"] =
+ WrapInNameSpace(service->namespace_parts(), service->name());
+ vars["ServiceName"] = service->name();
+ vars["ACCESS"] = service->is_internal() ? "internal" : "public";
+ auto printer = file->CreatePrinter(&output);
+ printer->Print(
+ vars,
+ "/// Usage: instantiate $ServiceQualifiedName$ServiceClient, then call "
+ "methods of this protocol to make API calls.\n");
+ GenerateClientProtocol(service, &*printer, &vars);
+ GenerateClientClass(&*printer, &vars);
+ printer->Print("\n");
+ GenerateServerProtocol(service, &*printer, &vars);
+ return output;
+}
+
+grpc::string GenerateHeader() {
+ grpc::string code;
+ code +=
+ "/// The following code is generated by the Flatbuffers library which "
+ "might not be in sync with grpc-swift\n";
+ code +=
+ "/// in case of an issue please open github issue, though it would be "
+ "maintained\n";
+ code += "\n";
+ code += "// swiftlint:disable all\n";
+ code += "// swiftformat:disable all\n";
+ code += "\n";
+ code += "import Foundation\n";
+ code += "import GRPC\n";
+ code += "import NIO\n";
+ code += "import NIOHTTP1\n";
+ code += "import FlatBuffers\n";
+ code += "\n";
+ code +=
+ "public protocol GRPCFlatBufPayload: GRPCPayload, FlatBufferGRPCMessage "
+ "{}\n";
+
+ code += "public extension GRPCFlatBufPayload {\n";
+ code += " init(serializedByteBuffer: inout NIO.ByteBuffer) throws {\n";
+ code +=
+ " self.init(byteBuffer: FlatBuffers.ByteBuffer(contiguousBytes: "
+ "serializedByteBuffer.readableBytesView, count: "
+ "serializedByteBuffer.readableBytes))\n";
+ code += " }\n";
+
+ code += " func serialize(into buffer: inout NIO.ByteBuffer) throws {\n";
+ code +=
+ " let buf = UnsafeRawBufferPointer(start: self.rawPointer, count: "
+ "Int(self.size))\n";
+ code += " buffer.writeBytes(buf)\n";
+ code += " }\n";
+ code += "}\n";
+ code += "extension Message: GRPCFlatBufPayload {}\n";
+ return code;
+}
+} // namespace grpc_swift_generator
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h
new file mode 100644
index 0000000000..1639cb07c8
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright 2020, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <memory>
+#include <vector>
+
+#include "src/compiler/config.h"
+#include "src/compiler/schema_interface.h"
+
+#ifndef GRPC_CUSTOM_STRING
+# include <string>
+# define GRPC_CUSTOM_STRING std::string
+#endif
+
+namespace grpc {
+
+typedef GRPC_CUSTOM_STRING string;
+
+} // namespace grpc
+
+namespace grpc_swift_generator {
+grpc::string Generate(grpc_generator::File *file,
+ const grpc_generator::Service *service);
+grpc::string GenerateHeader();
+} // namespace grpc_swift_generator
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc
new file mode 100644
index 0000000000..e49fd8d925
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc
@@ -0,0 +1,523 @@
+/*
+ * Copyright 2020 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.
+ */
+
+/*
+ * NOTE: The following implementation is a translation for the Swift-grpc
+ * generator since flatbuffers doesnt allow plugins for now. if an issue arises
+ * please open an issue in the flatbuffers repository. This file should always
+ * be maintained according to the Swift-grpc repository
+ */
+
+#include <map>
+#include <sstream>
+
+#include "flatbuffers/util.h"
+#include "src/compiler/schema_interface.h"
+#include "src/compiler/ts_generator.h"
+
+namespace grpc_ts_generator {
+
+grpc::string ToDasherizedCase(const grpc::string pascal_case) {
+ std::string dasherized_case;
+ char p = 0;
+ for (size_t i = 0; i < pascal_case.length(); i++) {
+ char const &c = pascal_case[i];
+ if (flatbuffers::is_alpha_upper(c)) {
+ if (i > 0 && p != flatbuffers::kPathSeparator) dasherized_case += "-";
+ dasherized_case += flatbuffers::CharToLower(c);
+ } else {
+ dasherized_case += c;
+ }
+ p = c;
+ }
+ return dasherized_case;
+}
+
+grpc::string GenerateNamespace(const std::vector<std::string> namepsace,
+ const std::string filename,
+ const bool include_separator) {
+ grpc::string path = "";
+ if (include_separator) path += ".";
+
+ for (auto it = namepsace.begin(); it < namepsace.end(); it++) {
+ if (include_separator) path += "/";
+ path += include_separator ? ToDasherizedCase(*it) : *it + "_";
+ }
+
+ if (include_separator) path += "/";
+ path += include_separator ? ToDasherizedCase(filename) : filename;
+ return path;
+}
+
+// MARK: - Shared code
+
+void GenerateImports(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary,
+ const bool grpc_var_import) {
+ auto vars = *dictonary;
+ printer->Print(
+ "// Generated GRPC code for FlatBuffers TS *** DO NOT EDIT ***\n");
+ printer->Print("import * as flatbuffers from 'flatbuffers';\n");
+
+ std::set<grpc::string> generated_imports;
+
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ auto output = method->get_output_type_name();
+ auto input = method->get_input_type_name();
+ auto input_namespace = method->get_input_namespace_parts();
+
+ vars["OUTPUT"] = output;
+ vars["INPUT"] = input;
+
+ if (generated_imports.find(output) == generated_imports.end()) {
+ generated_imports.insert(output);
+ vars["OUTPUT_DIR"] =
+ GenerateNamespace(method->get_output_namespace_parts(), output, true);
+ vars["Output_alias"] = GenerateNamespace(
+ method->get_output_namespace_parts(), output, false);
+ printer->Print(
+ vars, "import { $OUTPUT$ as $Output_alias$ } from '$OUTPUT_DIR$';\n");
+ }
+ if (generated_imports.find(input) == generated_imports.end()) {
+ generated_imports.insert(input);
+ vars["INPUT_DIR"] =
+ GenerateNamespace(method->get_output_namespace_parts(), input, true);
+ vars["Input_alias"] =
+ GenerateNamespace(method->get_output_namespace_parts(), input, false);
+ printer->Print(
+ vars, "import { $INPUT$ as $Input_alias$ } from '$INPUT_DIR$';\n");
+ }
+ }
+ printer->Print("\n");
+ if (grpc_var_import)
+ printer->Print("var grpc = require('grpc');\n");
+ else
+ printer->Print("import * as grpc from 'grpc';\n");
+ printer->Print("\n");
+}
+
+// MARK: - Generate Main GRPC Code
+
+void GetStreamType(grpc_generator::Printer *printer,
+ const grpc_generator::Method *method,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ auto client_streaming = method->ClientStreaming() || method->BidiStreaming();
+ auto server_streaming = method->ServerStreaming() || method->BidiStreaming();
+ vars["ClientStreaming"] = client_streaming ? "true" : "false";
+ vars["ServerStreaming"] = server_streaming ? "true" : "false";
+ printer->Print(vars, "requestStream: $ClientStreaming$,\n");
+ printer->Print(vars, "responseStream: $ServerStreaming$,\n");
+}
+
+void GenerateSerializeMethod(grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars, "function serialize_$Type$(buffer_args) {\n");
+ printer->Indent();
+ printer->Print(vars, "if (!(buffer_args instanceof $Type$)) {\n");
+ printer->Indent();
+ printer->Print(vars,
+ "throw new Error('Expected argument of type $VALUE$');\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print(vars, "return buffer_args.serialize();\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void GenerateDeserializeMethod(
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars, "function deserialize_$Type$(buffer) {\n");
+ printer->Indent();
+ printer->Print(vars,
+ "return $Type$.getRootAs$VALUE$(new "
+ "flatbuffers.ByteBuffer(buffer))\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void GenerateMethods(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+
+ std::set<grpc::string> generated_functions;
+
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ auto output = method->get_output_type_name();
+ auto input = method->get_input_type_name();
+
+ if (generated_functions.find(output) == generated_functions.end()) {
+ generated_functions.insert(output);
+ vars["VALUE"] = output;
+ vars["Type"] = GenerateNamespace(method->get_output_namespace_parts(),
+ output, false);
+ GenerateSerializeMethod(printer, &vars);
+ GenerateDeserializeMethod(printer, &vars);
+ }
+ printer->Print("\n");
+ if (generated_functions.find(input) == generated_functions.end()) {
+ generated_functions.insert(input);
+ vars["VALUE"] = input;
+ vars["Type"] =
+ GenerateNamespace(method->get_input_namespace_parts(), input, false);
+ GenerateSerializeMethod(printer, &vars);
+ GenerateDeserializeMethod(printer, &vars);
+ }
+ }
+}
+
+void GenerateService(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ vars["NAME"] = service->name() + "Service";
+
+ printer->Print(vars, "var $NAME$ = exports.$NAME$ = {\n");
+ printer->Indent();
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["MethodName"] = method->name();
+ vars["OUTPUT"] = GenerateNamespace(method->get_output_namespace_parts(),
+ method->get_output_type_name(), false);
+ vars["INPUT"] = GenerateNamespace(method->get_input_namespace_parts(),
+ method->get_input_type_name(), false);
+ printer->Print(vars, "$MethodName$: {\n");
+ printer->Indent();
+ printer->Print(vars, "path: '/$PATH$$ServiceName$/$MethodName$',\n");
+ GetStreamType(printer, &*method, &vars);
+ printer->Print(vars, "requestType: flatbuffers.ByteBuffer,\n");
+ printer->Print(vars, "responseType: $OUTPUT$,\n");
+ printer->Print(vars, "requestSerialize: serialize_$INPUT$,\n");
+ printer->Print(vars, "requestDeserialize: deserialize_$INPUT$,\n");
+ printer->Print(vars, "responseSerialize: serialize_$OUTPUT$,\n");
+ printer->Print(vars, "responseDeserialize: deserialize_$OUTPUT$,\n");
+ printer->Outdent();
+ printer->Print("},\n");
+ }
+ printer->Outdent();
+ printer->Print("};\n");
+ printer->Print(vars,
+ "exports.$ServiceName$Client = "
+ "grpc.makeGenericClientConstructor($NAME$);");
+}
+
+grpc::string Generate(grpc_generator::File *file,
+ const grpc_generator::Service *service,
+ const grpc::string &filename) {
+ grpc::string output;
+ std::map<grpc::string, grpc::string> vars;
+
+ vars["PATH"] = file->package();
+
+ if (!file->package().empty()) { vars["PATH"].append("."); }
+
+ vars["ServiceName"] = service->name();
+ vars["FBSFile"] = service->name() + "_fbs";
+ vars["Filename"] = filename;
+ auto printer = file->CreatePrinter(&output);
+
+ GenerateImports(service, &*printer, &vars, true);
+ GenerateMethods(service, &*printer, &vars);
+ GenerateService(service, &*printer, &vars);
+ return output;
+}
+
+// MARK: - Generate Interface
+
+void FillInterface(grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars,
+ "interface I$ServiceName$Service_I$MethodName$ extends "
+ "grpc.MethodDefinition<$INPUT$, $OUTPUT$> {\n");
+ printer->Indent();
+ printer->Print(vars, "path: string; // /$PATH$$ServiceName$/$MethodName$\n");
+ printer->Print(vars, "requestStream: boolean; // $ClientStreaming$\n");
+ printer->Print(vars, "responseStream: boolean; // $ServerStreaming$\n");
+ printer->Print(vars, "requestSerialize: grpc.serialize<$INPUT$>;\n");
+ printer->Print(vars, "requestDeserialize: grpc.deserialize<$INPUT$>;\n");
+ printer->Print(vars, "responseSerialize: grpc.serialize<$OUTPUT$>;\n");
+ printer->Print(vars, "responseDeserialize: grpc.deserialize<$OUTPUT$>;\n");
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void GenerateInterfaces(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ auto client_streaming =
+ method->ClientStreaming() || method->BidiStreaming();
+ auto server_streaming =
+ method->ServerStreaming() || method->BidiStreaming();
+ vars["ClientStreaming"] = client_streaming ? "true" : "false";
+ vars["ServerStreaming"] = server_streaming ? "true" : "false";
+ vars["MethodName"] = method->name();
+ vars["OUTPUT"] = GenerateNamespace(method->get_output_namespace_parts(),
+ method->get_output_type_name(), false);
+ vars["INPUT"] = GenerateNamespace(method->get_input_namespace_parts(),
+ method->get_input_type_name(), false);
+ FillInterface(printer, &vars);
+ printer->Print("\n");
+ }
+}
+
+void GenerateExportedInterface(
+ const grpc_generator::Service *service, grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars, "export interface I$ServiceName$Server {\n");
+ printer->Indent();
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["Name"] = method->name();
+ vars["OUTPUT"] = GenerateNamespace(method->get_output_namespace_parts(),
+ method->get_output_type_name(), false);
+ vars["INPUT"] = GenerateNamespace(method->get_input_namespace_parts(),
+ method->get_input_type_name(), false);
+ if (method->BidiStreaming()) {
+ printer->Print(vars,
+ "$Name$: grpc.handleBidiStreamingCall<$INPUT$, "
+ "$OUTPUT$>;\n");
+ continue;
+ }
+ if (method->NoStreaming()) {
+ printer->Print(vars,
+ "$Name$: grpc.handleUnaryCall<$INPUT$, "
+ "$OUTPUT$>;\n");
+ continue;
+ }
+ if (method->ClientStreaming()) {
+ printer->Print(vars,
+ "$Name$: grpc.handleClientStreamingCall<$INPUT$, "
+ "$OUTPUT$>;\n");
+ continue;
+ }
+ if (method->ServerStreaming()) {
+ printer->Print(vars,
+ "$Name$: grpc.handleServerStreamingCall<$INPUT$, "
+ "$OUTPUT$>;\n");
+ continue;
+ }
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void GenerateMainInterface(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(
+ vars,
+ "interface I$ServiceName$Service extends "
+ "grpc.ServiceDefinition<grpc.UntypedServiceImplementation> {\n");
+ printer->Indent();
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["MethodName"] = method->name();
+ printer->Print(vars,
+ "$MethodName$: I$ServiceName$Service_I$MethodName$;\n");
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+ GenerateInterfaces(service, printer, &vars);
+ printer->Print("\n");
+ printer->Print(vars,
+ "export const $ServiceName$Service: I$ServiceName$Service;\n");
+ printer->Print("\n");
+ GenerateExportedInterface(service, printer, &vars);
+}
+
+grpc::string GenerateMetaData() { return "metadata: grpc.Metadata"; }
+
+grpc::string GenerateOptions() { return "options: Partial<grpc.CallOptions>"; }
+
+void GenerateUnaryClientInterface(
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ grpc::string main = "$ISPUBLIC$$MethodName$(request: $INPUT$, ";
+ grpc::string callback =
+ "callback: (error: grpc.ServiceError | null, response: "
+ "$OUTPUT$) => void): grpc.ClientUnaryCall;\n";
+ auto meta_data = GenerateMetaData() + ", ";
+ auto options = GenerateOptions() + ", ";
+ printer->Print(vars, (main + callback).c_str());
+ printer->Print(vars, (main + meta_data + callback).c_str());
+ printer->Print(vars, (main + meta_data + options + callback).c_str());
+}
+
+void GenerateClientWriteStreamInterface(
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ grpc::string main = "$ISPUBLIC$$MethodName$(";
+ grpc::string callback =
+ "callback: (error: grpc.ServiceError | null, response: "
+ "$INPUT$) => void): "
+ "grpc.ClientWritableStream<$OUTPUT$>;\n";
+ auto meta_data = GenerateMetaData() + ", ";
+ auto options = GenerateOptions() + ", ";
+ printer->Print(vars, (main + callback).c_str());
+ printer->Print(vars, (main + meta_data + callback).c_str());
+ printer->Print(vars, (main + options + callback).c_str());
+ printer->Print(vars, (main + meta_data + options + callback).c_str());
+}
+
+void GenerateClientReadableStreamInterface(
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ grpc::string main = "$ISPUBLIC$$MethodName$(request: $INPUT$, ";
+ grpc::string end_function = "): grpc.ClientReadableStream<$OUTPUT$>;\n";
+ auto meta_data = GenerateMetaData();
+ auto options = GenerateOptions();
+ printer->Print(vars, (main + meta_data + end_function).c_str());
+ printer->Print(vars, (main + options + end_function).c_str());
+}
+
+void GenerateDepluxStreamInterface(
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ grpc::string main = "$ISPUBLIC$$MethodName$(";
+ grpc::string end_function =
+ "): grpc.ClientDuplexStream<$INPUT$, $OUTPUT$>;\n";
+ auto meta_data = GenerateMetaData();
+ auto options = GenerateOptions();
+ printer->Print(vars, (main + end_function).c_str());
+ printer->Print(vars, (main + options + end_function).c_str());
+ printer->Print(vars, (main + meta_data +
+ ", options?: Partial<grpc.CallOptions>" + end_function)
+ .c_str());
+}
+
+void GenerateClientInterface(const grpc_generator::Service *service,
+ grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars, "export interface I$ServiceName$Client {\n");
+ printer->Indent();
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["MethodName"] = method->name();
+ vars["OUTPUT"] = GenerateNamespace(method->get_output_namespace_parts(),
+ method->get_output_type_name(), false);
+ vars["INPUT"] = GenerateNamespace(method->get_input_namespace_parts(),
+ method->get_input_type_name(), false);
+ vars["ISPUBLIC"] = "";
+
+ if (method->NoStreaming()) {
+ GenerateUnaryClientInterface(printer, &vars);
+ continue;
+ }
+ if (method->BidiStreaming()) {
+ GenerateDepluxStreamInterface(printer, &vars);
+ continue;
+ }
+
+ if (method->ClientStreaming()) {
+ GenerateClientWriteStreamInterface(printer, &vars);
+ continue;
+ }
+
+ if (method->ServerStreaming()) {
+ GenerateClientReadableStreamInterface(printer, &vars);
+ continue;
+ }
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void GenerateClientClassInterface(
+ const grpc_generator::Service *service, grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> *dictonary) {
+ auto vars = *dictonary;
+ printer->Print(vars,
+ "export class $ServiceName$Client extends grpc.Client "
+ "implements I$ServiceName$Client {\n");
+ printer->Indent();
+ printer->Print(
+ "constructor(address: string, credentials: grpc.ChannelCredentials, "
+ "options?: object);");
+ for (auto it = 0; it < service->method_count(); it++) {
+ auto method = service->method(it);
+ vars["MethodName"] = method->name();
+ vars["OUTPUT"] = GenerateNamespace(method->get_output_namespace_parts(),
+ method->get_output_type_name(), false);
+ vars["INPUT"] = GenerateNamespace(method->get_input_namespace_parts(),
+ method->get_input_type_name(), false);
+ vars["ISPUBLIC"] = "public ";
+ if (method->NoStreaming()) {
+ GenerateUnaryClientInterface(printer, &vars);
+ continue;
+ }
+ if (method->BidiStreaming()) {
+ GenerateDepluxStreamInterface(printer, &vars);
+ continue;
+ }
+
+ if (method->ClientStreaming()) {
+ GenerateClientWriteStreamInterface(printer, &vars);
+ continue;
+ }
+
+ if (method->ServerStreaming()) {
+ GenerateClientReadableStreamInterface(printer, &vars);
+ continue;
+ }
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+grpc::string GenerateInterface(grpc_generator::File *file,
+ const grpc_generator::Service *service,
+ const grpc::string &filename) {
+ grpc::string output;
+
+ std::set<grpc::string> generated_functions;
+ std::map<grpc::string, grpc::string> vars;
+
+ vars["PATH"] = file->package();
+
+ if (!file->package().empty()) { vars["PATH"].append("."); }
+
+ vars["ServiceName"] = service->name();
+ vars["FBSFile"] = service->name() + "_fbs";
+ vars["Filename"] = filename;
+ auto printer = file->CreatePrinter(&output);
+
+ GenerateImports(service, &*printer, &vars, false);
+ GenerateMainInterface(service, &*printer, &vars);
+ printer->Print("\n");
+ GenerateClientInterface(service, &*printer, &vars);
+ printer->Print("\n");
+ GenerateClientClassInterface(service, &*printer, &vars);
+ return output;
+}
+} // namespace grpc_ts_generator
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h
new file mode 100644
index 0000000000..a33bb3c5d2
--- /dev/null
+++ b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2020, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <memory>
+#include <vector>
+#include <set>
+
+#include "src/compiler/config.h"
+#include "src/compiler/schema_interface.h"
+
+#ifndef GRPC_CUSTOM_STRING
+# include <string>
+# define GRPC_CUSTOM_STRING std::string
+#endif
+
+namespace grpc {
+
+typedef GRPC_CUSTOM_STRING string;
+
+} // namespace grpc
+
+namespace grpc_ts_generator {
+grpc::string Generate(grpc_generator::File *file,
+ const grpc_generator::Service *service,
+ const grpc::string &filename);
+
+grpc::string GenerateInterface(grpc_generator::File *file,
+ const grpc_generator::Service *service,
+ const grpc::string &filename);
+} // namespace grpc_ts_generator
+
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/code_generators.h b/contrib/libs/flatbuffers/include/flatbuffers/code_generators.h
new file mode 100644
index 0000000000..09b773a468
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/code_generators.h
@@ -0,0 +1,235 @@
+/*
+ * 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.
+ */
+
+#ifndef FLATBUFFERS_CODE_GENERATORS_H_
+#define FLATBUFFERS_CODE_GENERATORS_H_
+
+#include <map>
+#include <sstream>
+
+#include "idl.h"
+
+namespace flatbuffers {
+
+// Utility class to assist in generating code through use of text templates.
+//
+// Example code:
+// CodeWriter code("\t");
+// code.SetValue("NAME", "Foo");
+// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
+// code.SetValue("NAME", "Bar");
+// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
+// std::cout << code.ToString() << std::endl;
+//
+// Output:
+// void Foo() { printf("%s", "Foo"); }
+// void Bar() { printf("%s", "Bar"); }
+class CodeWriter {
+ public:
+ CodeWriter(std::string pad = std::string())
+ : pad_(pad), cur_ident_lvl_(0), ignore_ident_(false) {}
+
+ // Clears the current "written" code.
+ void Clear() {
+ stream_.str("");
+ stream_.clear();
+ }
+
+ // Associates a key with a value. All subsequent calls to operator+=, where
+ // the specified key is contained in {{ and }} delimiters will be replaced by
+ // the given value.
+ void SetValue(const std::string &key, const std::string &value) {
+ value_map_[key] = value;
+ }
+
+ std::string GetValue(const std::string &key) const {
+ const auto it = value_map_.find(key);
+ return it == value_map_.end() ? "" : it->second;
+ }
+
+ // Appends the given text to the generated code as well as a newline
+ // character. Any text within {{ and }} delimiters is replaced by values
+ // previously stored in the CodeWriter by calling SetValue above. The newline
+ // will be suppressed if the text ends with the \\ character.
+ void operator+=(std::string text);
+
+ // Returns the current contents of the CodeWriter as a std::string.
+ std::string ToString() const { return stream_.str(); }
+
+ // Increase ident level for writing code
+ void IncrementIdentLevel() { cur_ident_lvl_++; }
+ // Decrease ident level for writing code
+ void DecrementIdentLevel() {
+ if (cur_ident_lvl_) cur_ident_lvl_--;
+ }
+
+ void SetPadding(const std::string &padding) { pad_ = padding; }
+
+ private:
+ std::map<std::string, std::string> value_map_;
+ std::stringstream stream_;
+ std::string pad_;
+ int cur_ident_lvl_;
+ bool ignore_ident_;
+
+ // Add ident padding (tab or space) based on ident level
+ void AppendIdent(std::stringstream &stream);
+};
+
+class BaseGenerator {
+ public:
+ virtual bool generate() = 0;
+
+ static std::string NamespaceDir(const Parser &parser, const std::string &path,
+ const Namespace &ns,
+ const bool dasherize = false);
+
+ static std::string ToDasherizedCase(const std::string pascal_case);
+
+ std::string GeneratedFileName(const std::string &path,
+ const std::string &file_name,
+ const IDLOptions &options) const;
+
+ protected:
+ BaseGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name, std::string qualifying_start,
+ std::string qualifying_separator, std::string default_extension)
+ : parser_(parser),
+ path_(path),
+ file_name_(file_name),
+ qualifying_start_(qualifying_start),
+ qualifying_separator_(qualifying_separator),
+ default_extension_(default_extension) {}
+ virtual ~BaseGenerator() {}
+
+ // No copy/assign.
+ BaseGenerator &operator=(const BaseGenerator &);
+ BaseGenerator(const BaseGenerator &);
+
+ std::string NamespaceDir(const Namespace &ns,
+ const bool dasherize = false) const;
+
+ static const char *FlatBuffersGeneratedWarning();
+
+ static std::string FullNamespace(const char *separator, const Namespace &ns);
+
+ static std::string LastNamespacePart(const Namespace &ns);
+
+ // tracks the current namespace for early exit in WrapInNameSpace
+ // c++, java and csharp returns a different namespace from
+ // the following default (no early exit, always fully qualify),
+ // which works for js and php
+ virtual const Namespace *CurrentNameSpace() const { return nullptr; }
+
+ // Ensure that a type is prefixed with its namespace even within
+ // its own namespace to avoid conflict between generated method
+ // names and similarly named classes or structs
+ std::string WrapInNameSpace(const Namespace *ns,
+ const std::string &name) const;
+
+ std::string WrapInNameSpace(const Definition &def) const;
+
+ std::string GetNameSpace(const Definition &def) const;
+
+ const Parser &parser_;
+ const std::string &path_;
+ const std::string &file_name_;
+ const std::string qualifying_start_;
+ const std::string qualifying_separator_;
+ const std::string default_extension_;
+};
+
+struct CommentConfig {
+ const char *first_line;
+ const char *content_line_prefix;
+ const char *last_line;
+};
+
+extern void GenComment(const std::vector<std::string> &dc,
+ std::string *code_ptr, const CommentConfig *config,
+ const char *prefix = "");
+
+class FloatConstantGenerator {
+ public:
+ virtual ~FloatConstantGenerator() {}
+ std::string GenFloatConstant(const FieldDef &field) const;
+
+ private:
+ virtual std::string Value(double v, const std::string &src) const = 0;
+ virtual std::string Inf(double v) const = 0;
+ virtual std::string NaN(double v) const = 0;
+
+ virtual std::string Value(float v, const std::string &src) const = 0;
+ virtual std::string Inf(float v) const = 0;
+ virtual std::string NaN(float v) const = 0;
+
+ template<typename T>
+ std::string GenFloatConstantImpl(const FieldDef &field) const;
+};
+
+class SimpleFloatConstantGenerator : public FloatConstantGenerator {
+ public:
+ SimpleFloatConstantGenerator(const char *nan_number,
+ const char *pos_inf_number,
+ const char *neg_inf_number);
+
+ private:
+ std::string Value(double v,
+ const std::string &src) const FLATBUFFERS_OVERRIDE;
+ std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
+ std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
+
+ std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE;
+ std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
+ std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
+
+ const std::string nan_number_;
+ const std::string pos_inf_number_;
+ const std::string neg_inf_number_;
+};
+
+// C++, C#, Java like generator.
+class TypedFloatConstantGenerator : public FloatConstantGenerator {
+ public:
+ TypedFloatConstantGenerator(const char *double_prefix,
+ const char *single_prefix, const char *nan_number,
+ const char *pos_inf_number,
+ const char *neg_inf_number = "");
+
+ private:
+ std::string Value(double v,
+ const std::string &src) const FLATBUFFERS_OVERRIDE;
+ std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
+
+ std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
+
+ std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE;
+ std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
+ std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
+
+ std::string MakeNaN(const std::string &prefix) const;
+ std::string MakeInf(bool neg, const std::string &prefix) const;
+
+ const std::string double_prefix_;
+ const std::string single_prefix_;
+ const std::string nan_number_;
+ const std::string pos_inf_number_;
+ const std::string neg_inf_number_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_CODE_GENERATORS_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h
new file mode 100644
index 0000000000..a770983dca
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h
@@ -0,0 +1,640 @@
+/*
+ * 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.
+ */
+
+#ifndef FLATBUFFERS_ITER_H_
+#define FLATBUFFERS_ITER_H_
+
+#include "flatbuffers.h"
+#include <optional>
+
+/// @file
+namespace yandex {
+namespace maps {
+namespace flatbuffers_iter {
+
+#define FLATBUFFERS_FILE_IDENTIFIER_LENGTH 4
+
+using flatbuffers::uoffset_t;
+using flatbuffers::soffset_t;
+using flatbuffers::voffset_t;
+using flatbuffers::EndianScalar;
+
+// Wrapper for uoffset_t to allow safe template specialization.
+template<typename T> struct Offset {
+ uoffset_t o;
+ Offset() : o(0) {}
+ Offset(uoffset_t _o) : o(_o) {}
+ Offset<void> Union() const { return Offset<void>(o); }
+};
+
+template<typename Iter>
+inline bool hasContiguous(const Iter& spot, uoffset_t length)
+{
+ return spot.hasContiguous(length);
+}
+
+inline bool hasContiguous(const uint8_t* /* spot */, uoffset_t /* length */)
+{
+ return true;
+}
+
+template <typename Iter>
+inline const uint8_t* getRawPointer(const Iter& spot)
+{
+ return spot.rawPointer();
+}
+
+inline const uint8_t* getRawPointer(const uint8_t* spot)
+{
+ return spot;
+}
+
+template<typename T, typename Iter>
+typename std::enable_if<sizeof(T) == 1, T>::type extractValue(const Iter& spot)
+{
+ typename std::remove_cv<T>::type ret;
+ std::memcpy(&ret, getRawPointer(spot), 1);
+ return ret;
+}
+
+template<typename T, typename Iter>
+typename std::enable_if<sizeof(T) != 1, T>::type extractValue(const Iter& spot)
+{
+ if (hasContiguous(spot, sizeof(T))) {
+ typename std::remove_cv<T>::type ret;
+ std::memcpy(&ret, getRawPointer(spot), sizeof(T));
+ return ret;
+ }
+ Iter itr = spot;
+ alignas(T) uint8_t buf[sizeof(T)];
+ for (std::size_t i = 0; i < sizeof(T); ++i) {
+ buf[i] = *itr;
+ ++itr;
+ }
+ return *reinterpret_cast<T*>(buf);
+}
+
+template<typename T, typename Iter> T ReadScalar(Iter p) {
+ return EndianScalar(extractValue<T>(p));
+}
+
+// When we read serialized data from memory, in the case of most scalars,
+// we want to just read T, but in the case of Offset, we want to actually
+// perform the indirection and return a pointer.
+// The template specialization below does just that.
+// It is wrapped in a struct since function templates can't overload on the
+// return type like this.
+// The typedef is for the convenience of callers of this function
+// (avoiding the need for a trailing return decltype)
+template<typename T> struct IndirectHelper {
+ typedef T return_type;
+ typedef T mutable_return_type;
+ static const size_t element_stride = sizeof(T);
+ template<typename Iter>
+ static return_type Read(const Iter& p, uoffset_t i) {
+ return i ? EndianScalar(extractValue<return_type>(p+sizeof(return_type)*i)) : EndianScalar(extractValue<return_type>(p));
+ }
+};
+template<typename T> struct IndirectHelper<Offset<T>> {
+ typedef std::optional<T> return_type;
+ typedef std::optional<T> mutable_return_type;
+ static const size_t element_stride = sizeof(uoffset_t);
+ template<typename Iter>
+ static return_type Read(Iter p, uoffset_t i) {
+ p += i * sizeof(uoffset_t);
+ return return_type(T(p + ReadScalar<uoffset_t>(p)));
+ }
+};
+template<typename T> struct IndirectHelper<const T *> {
+};
+
+
+// An STL compatible iterator implementation for Vector below, effectively
+// calling Get() for every element.
+template<typename T, typename IT, typename Iter>
+struct VectorIterator
+ : public std::iterator<std::random_access_iterator_tag, IT, uoffset_t> {
+
+ typedef std::iterator<std::random_access_iterator_tag, IT, uoffset_t> super_type;
+
+public:
+ VectorIterator(const Iter& data, uoffset_t i) :
+ data_(data + IndirectHelper<T>::element_stride * i) {}
+ VectorIterator(const VectorIterator &other) : data_(other.data_) {}
+ #ifndef FLATBUFFERS_CPP98_STL
+ VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {}
+ #endif
+
+ VectorIterator &operator=(const VectorIterator &other) {
+ data_ = other.data_;
+ return *this;
+ }
+
+ VectorIterator &operator=(VectorIterator &&other) {
+ data_ = other.data_;
+ return *this;
+ }
+
+ bool operator==(const VectorIterator &other) const {
+ return data_ == other.data_;
+ }
+
+ bool operator!=(const VectorIterator &other) const {
+ return data_ != other.data_;
+ }
+
+ ptrdiff_t operator-(const VectorIterator &other) const {
+ return (data_ - other.data_) / IndirectHelper<T>::element_stride;
+ }
+
+ typename super_type::value_type operator *() const {
+ return IndirectHelper<T>::Read(data_, 0);
+ }
+
+ typename super_type::value_type operator->() const {
+ return IndirectHelper<T>::Read(data_, 0);
+ }
+
+ VectorIterator &operator++() {
+ data_ += IndirectHelper<T>::element_stride;
+ return *this;
+ }
+
+ VectorIterator operator++(int) {
+ VectorIterator temp(data_, 0);
+ data_ += IndirectHelper<T>::element_stride;
+ return temp;
+ }
+
+ VectorIterator operator+(const uoffset_t &offset) {
+ return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, 0);
+ }
+
+ VectorIterator& operator+=(const uoffset_t &offset) {
+ data_ += offset * IndirectHelper<T>::element_stride;
+ return *this;
+ }
+
+ VectorIterator &operator--() {
+ data_ -= IndirectHelper<T>::element_stride;
+ return *this;
+ }
+
+ VectorIterator operator--(int) {
+ VectorIterator temp(data_, 0);
+ data_ -= IndirectHelper<T>::element_stride;
+ return temp;
+ }
+
+ VectorIterator operator-(const uoffset_t &offset) {
+ return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, 0);
+ }
+
+ VectorIterator& operator-=(const uoffset_t &offset) {
+ data_ -= offset * IndirectHelper<T>::element_stride;
+ return *this;
+ }
+
+private:
+ Iter data_;
+};
+
+// This is used as a helper type for accessing vectors.
+// Vector::data() assumes the vector elements start after the length field.
+template<typename T, typename Iter> class Vector {
+public:
+ typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type, Iter>
+ iterator;
+ typedef VectorIterator<T, typename IndirectHelper<T>::return_type, Iter>
+ const_iterator;
+
+ Vector(Iter data):
+ data_(data)
+ {}
+
+ uoffset_t size() const { return EndianScalar(extractValue<uoffset_t>(data_)); }
+
+ // Deprecated: use size(). Here for backwards compatibility.
+ uoffset_t Length() const { return size(); }
+
+ typedef typename IndirectHelper<T>::return_type return_type;
+ typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
+
+ return_type Get(uoffset_t i) const {
+ assert(i < size());
+ return IndirectHelper<T>::Read(Data(), i);
+ }
+
+ return_type operator[](uoffset_t i) const { return Get(i); }
+
+ // If this is a Vector of enums, T will be its storage type, not the enum
+ // type. This function makes it convenient to retrieve value with enum
+ // type E.
+ template<typename E> E GetEnum(uoffset_t i) const {
+ return static_cast<E>(Get(i));
+ }
+
+ const Iter GetStructFromOffset(size_t o) const {
+ return Data() + o;
+ }
+
+ iterator begin() { return iterator(Data(), 0); }
+ const_iterator begin() const { return const_iterator(Data(), 0); }
+
+ iterator end() { return iterator(Data(), size()); }
+ const_iterator end() const { return const_iterator(Data(), size()); }
+
+ // The raw data in little endian format. Use with care.
+ const Iter Data() const {
+ return data_ + sizeof(uoffset_t);
+ }
+
+ Iter Data() {
+ return data_ + sizeof(uoffset_t);
+ }
+
+ template<typename K> return_type LookupByKey(K key) const {
+ auto search_result = std::lower_bound(begin(), end(), key, KeyCompare<K>);
+
+ if (search_result == end() || (*search_result)->KeyCompareWithValue(key) != 0) {
+ return std::nullopt; // Key not found.
+ }
+
+ return *search_result;
+ }
+
+ operator Iter() const
+ {
+ return data_;
+ }
+
+protected:
+ Iter data_;
+
+private:
+ template<typename K> static int KeyCompare(const return_type& ap, const K& bp) {
+ return ap->KeyCompareWithValue(bp) < 0;
+ }
+};
+
+// Represent a vector much like the template above, but in this case we
+// don't know what the element types are (used with reflection.h).
+template <typename Iter>
+class VectorOfAny {
+public:
+ VectorOfAny(Iter data):
+ data_(data)
+ {}
+
+ uoffset_t size() const { return EndianScalar(extractValue<uoffset_t>(data_)); }
+
+ const Iter Data() const {
+ return data_;
+ }
+ Iter Data() {
+ return data_;
+ }
+protected:
+
+ Iter data_;
+};
+
+// Convenient helper function to get the length of any vector, regardless
+// of wether it is null or not (the field is not set).
+template<typename T, typename Iter> static inline size_t VectorLength(const std::optional<Vector<T, Iter>> &v) {
+ return v ? v->Length() : 0;
+}
+
+template <typename Iter> struct String : public Vector<char, Iter> {
+ using Vector<char,Iter>::Vector;
+ using Vector<char,Iter>::data_;
+
+ std::string str() const {
+ if (hasContiguous(data_, sizeof(uoffset_t) + this->Length()))
+ return std::string(reinterpret_cast<const char*>(getRawPointer(data_)) + sizeof(uoffset_t), this->Length());
+ return std::string(this->begin(), this->begin() + this->Length()); }
+
+ bool operator <(const String &o) const {
+ return str() < o.str();
+ }
+};
+
+// Converts a Field ID to a virtual table offset.
+inline voffset_t FieldIndexToOffset(voffset_t field_id) {
+ // Should correspond to what EndTable() below builds up.
+ const int fixed_fields = 2; // Vtable size and Object Size.
+ return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
+}
+
+/// @endcond
+
+/// @cond FLATBUFFERS_INTERNAL
+template<typename T, typename Iter> std::optional<T> GetMutableRoot(Iter begin) {
+ flatbuffers::EndianCheck();
+ return T(begin + EndianScalar(extractValue<uoffset_t>(begin)));
+}
+
+template<typename T, typename Iter> std::optional<T> GetRoot(Iter begin) {
+ return GetMutableRoot<T, Iter>(begin);
+}
+
+template<typename T, typename Iter> std::optional<T> GetSizePrefixedRoot(Iter buf) {
+ return GetRoot<T, Iter>(buf + sizeof(uoffset_t));
+}
+
+// Helper to see if the identifier in a buffer has the expected value.
+
+template <typename Iter> inline bool BufferHasIdentifier(const Iter& buf, const char *identifier) {
+ return std::equal(
+ identifier,
+ identifier + std::min(std::strlen(identifier) + 1, static_cast<std::size_t>(FLATBUFFERS_FILE_IDENTIFIER_LENGTH)),
+ buf + sizeof(uoffset_t));
+}
+
+// Helper class to verify the integrity of a FlatBuffer
+template <typename Iter>
+class Verifier FLATBUFFERS_FINAL_CLASS {
+ public:
+ Verifier(const Iter& buf, size_t buf_len, size_t _max_depth = 64,
+ size_t _max_tables = 1000000)
+ : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
+ num_tables_(0), max_tables_(_max_tables)
+ #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ , upper_bound_(buf)
+ #endif
+ {}
+
+ // Central location where any verification failures register.
+ bool Check(bool ok) const {
+ #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
+ assert(ok);
+ #endif
+ #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ if (!ok)
+ upper_bound_ = buf_;
+ #endif
+ return ok;
+ }
+
+ // Verify any range within the buffer.
+ bool Verify(const Iter& elem, size_t elem_len) const {
+ #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ auto upper_bound = elem + elem_len;
+ if (upper_bound_ < upper_bound)
+ upper_bound_ = upper_bound;
+ #endif
+ return Check(elem_len <= (size_t) (end_ - buf_) &&
+ elem >= buf_ &&
+ elem <= end_ - elem_len);
+ }
+
+ // Verify a range indicated by sizeof(T).
+ template<typename T> bool Verify(const Iter& elem) const {
+ return Verify(elem, sizeof(T));
+ }
+
+ template<typename T> bool VerifyTable(const std::optional<T>& table) {
+ return !table || table->Verify(*this);
+ }
+
+ template<typename T> bool Verify(const std::optional<Vector<T, Iter>>& vec) const {
+ Iter end;
+ return !vec ||
+ VerifyVector(static_cast<Iter>(*vec), sizeof(T),
+ &end);
+ }
+
+ template<typename T> bool Verify(const std::optional<Vector<const T, Iter>>& vec) const {
+ return Verify(*reinterpret_cast<const std::optional<Vector<T, Iter>> *>(&vec));
+ }
+
+ bool Verify(const std::optional<String<Iter>>& str) const {
+ Iter end;
+ return !str ||
+ (VerifyVector(static_cast<Iter>(*str), 1, &end) &&
+ Verify(end, 1) && // Must have terminator
+ Check(*end == '\0')); // Terminating byte must be 0.
+ }
+
+ // Common code between vectors and strings.
+ bool VerifyVector(const Iter& vec, size_t elem_size,
+ Iter *end) const {
+ // Check we can read the size field.
+ if (!Verify<uoffset_t>(vec)) return false;
+ // Check the whole array. If this is a string, the byte past the array
+ // must be 0.
+ auto size = ReadScalar<uoffset_t>(vec);
+ auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
+ if (!Check(size < max_elems))
+ return false; // Protect against byte_size overflowing.
+ auto byte_size = sizeof(size) + elem_size * size;
+ *end = vec + byte_size;
+ return Verify(vec, byte_size);
+ }
+
+ // Special case for string contents, after the above has been called.
+ bool VerifyVectorOfStrings(const std::optional<Vector<Offset<String<Iter>>, Iter>>& vec) const {
+ if (vec) {
+ for (uoffset_t i = 0; i < vec->size(); i++) {
+ if (!Verify(vec->Get(i))) return false;
+ }
+ }
+ return true;
+ }
+
+ // Special case for table contents, after the above has been called.
+ template<typename T> bool VerifyVectorOfTables(const std::optional<Vector<Offset<T>, Iter>>& vec) {
+ if (vec) {
+ for (uoffset_t i = 0; i < vec->size(); i++) {
+ if (!vec->Get(i)->Verify(*this)) return false;
+ }
+ }
+ return true;
+ }
+
+ template<typename T> bool VerifyBufferFromStart(const char *identifier,
+ const Iter& start) {
+ if (identifier &&
+ (static_cast<std::size_t>(end_ - start) < 2 * sizeof(flatbuffers_iter::uoffset_t) ||
+ !BufferHasIdentifier(start, identifier))) {
+ return false;
+ }
+
+ // Call T::Verify, which must be in the generated code for this type.
+ return Verify<uoffset_t>(start) &&
+ T(start + ReadScalar<uoffset_t>(start)).
+ Verify(*this)
+ #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ && GetComputedSize()
+ #endif
+ ;
+ }
+
+ // Verify this whole buffer, starting with root type T.
+ template<typename T> bool VerifyBuffer(const char *identifier) {
+ return VerifyBufferFromStart<T>(identifier, buf_);
+ }
+
+ template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
+ return Verify<uoffset_t>(buf_) &&
+ ReadScalar<uoffset_t>(buf_) == end_ - buf_ - sizeof(uoffset_t) &&
+ VerifyBufferFromStart<T>(identifier, buf_ + sizeof(uoffset_t));
+ }
+
+ // Called at the start of a table to increase counters measuring data
+ // structure depth and amount, and possibly bails out with false if
+ // limits set by the constructor have been hit. Needs to be balanced
+ // with EndTable().
+ bool VerifyComplexity() {
+ depth_++;
+ num_tables_++;
+ return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
+ }
+
+ // Called at the end of a table to pop the depth count.
+ bool EndTable() {
+ depth_--;
+ return true;
+ }
+
+ #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ // Returns the message size in bytes
+ size_t GetComputedSize() const {
+ uintptr_t size = upper_bound_ - buf_;
+ // Align the size to uoffset_t
+ size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
+ return (buf_ + size > end_) ? 0 : size;
+ }
+ #endif
+
+ private:
+ const Iter buf_;
+ const Iter end_;
+ size_t depth_;
+ size_t max_depth_;
+ size_t num_tables_;
+ size_t max_tables_;
+#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
+ mutable const Iter upper_bound_;
+#endif
+};
+
+// "structs" are flat structures that do not have an offset table, thus
+// always have all members present and do not support forwards/backwards
+// compatible extensions.
+template <typename Iter>
+class Struct FLATBUFFERS_FINAL_CLASS {
+ public:
+ template<typename T> T GetField(uoffset_t o) const {
+ return ReadScalar<T>(data_ + o);
+ }
+
+ template<typename T> T GetStruct(uoffset_t o) const {
+ return T(data_ + o);
+ }
+
+ private:
+ Iter data_;
+};
+
+// "tables" use an offset table (possibly shared) that allows fields to be
+// omitted and added at will, but uses an extra indirection to read.
+template<typename Iter>
+class Table {
+ public:
+ Table(Iter data): data_(data) {}
+
+ const Iter GetVTable() const {
+ return data_ - ReadScalar<soffset_t>(data_);
+ }
+
+ // This gets the field offset for any of the functions below it, or 0
+ // if the field was not present.
+ voffset_t GetOptionalFieldOffset(voffset_t field) const {
+ // The vtable offset is always at the start.
+ auto vtable = GetVTable();
+ // The first element is the size of the vtable (fields + type id + itself).
+ auto vtsize = ReadScalar<voffset_t>(vtable);
+ // If the field we're accessing is outside the vtable, we're reading older
+ // data, so it's the same as if the offset was 0 (not present).
+ return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
+ }
+
+ template<typename T> T GetField(voffset_t field, T defaultval) const {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
+ }
+
+ template<typename P> std::optional<P> GetPointer(voffset_t field) {
+ auto field_offset = GetOptionalFieldOffset(field);
+ auto p = data_ + field_offset;
+ return field_offset ? std::optional<P>(P(p + ReadScalar<uoffset_t>(p))) : std::nullopt;
+ }
+
+ template<typename P> std::optional<P> GetPointer(voffset_t field) const {
+ return const_cast<Table *>(this)->template GetPointer<P>(field);
+ }
+
+ template<typename P> P GetStruct(voffset_t field) const {
+ auto field_offset = GetOptionalFieldOffset(field);
+ auto p = data_ + field_offset;
+ return extractValue<P>(p);
+ }
+
+ bool CheckField(voffset_t field) const {
+ return GetOptionalFieldOffset(field) != 0;
+ }
+
+ // Verify the vtable of this table.
+ // Call this once per table, followed by VerifyField once per field.
+ bool VerifyTableStart(Verifier<Iter> &verifier) const {
+ // Check the vtable offset.
+ if (!verifier.template Verify<soffset_t>(data_)) return false;
+ auto vtable = GetVTable();
+ // Check the vtable size field, then check vtable fits in its entirety.
+ return verifier.VerifyComplexity() &&
+ verifier.template Verify<voffset_t>(vtable) &&
+ (ReadScalar<voffset_t>(vtable) & (sizeof(voffset_t) - 1)) == 0 &&
+ verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
+ }
+
+ // Verify a particular field.
+ template<typename T> bool VerifyField(const Verifier<Iter> &verifier,
+ voffset_t field) const {
+ // Calling GetOptionalFieldOffset should be safe now thanks to
+ // VerifyTable().
+ auto field_offset = GetOptionalFieldOffset(field);
+ // Check the actual field.
+ return !field_offset || verifier.template Verify<T>(data_ + field_offset);
+ }
+
+ // VerifyField for required fields.
+ template<typename T> bool VerifyFieldRequired(const Verifier<Iter> &verifier,
+ voffset_t field) const {
+ auto field_offset = GetOptionalFieldOffset(field);
+ return verifier.Check(field_offset != 0) &&
+ verifier.template Verify<T>(data_ + field_offset);
+ }
+
+ private:
+ Iter data_;
+};
+/// @endcond
+} // namespace flatbuffers_iter
+} // namespace maps
+} // namespace yandex
+
+#endif // FLATBUFFERS_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flatc.h b/contrib/libs/flatbuffers/include/flatbuffers/flatc.h
new file mode 100644
index 0000000000..1466b3651d
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/flatc.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef FLATBUFFERS_FLATC_H_
+#define FLATBUFFERS_FLATC_H_
+
+#include <functional>
+#include <limits>
+#include <string>
+
+#include "flatbuffers.h"
+#include "idl.h"
+#include "util.h"
+
+namespace flatbuffers {
+
+extern void LogCompilerWarn(const std::string &warn);
+extern void LogCompilerError(const std::string &err);
+
+class FlatCompiler {
+ public:
+ // Output generator for the various programming languages and formats we
+ // support.
+ struct Generator {
+ typedef bool (*GenerateFn)(const flatbuffers::Parser &parser,
+ const std::string &path,
+ const std::string &file_name);
+ typedef std::string (*MakeRuleFn)(const flatbuffers::Parser &parser,
+ const std::string &path,
+ const std::string &file_name);
+
+ GenerateFn generate;
+ const char *generator_opt_short;
+ const char *generator_opt_long;
+ const char *lang_name;
+ bool schema_only;
+ GenerateFn generateGRPC;
+ flatbuffers::IDLOptions::Language lang;
+ const char *generator_help;
+ MakeRuleFn make_rule;
+ };
+
+ typedef void (*WarnFn)(const FlatCompiler *flatc, const std::string &warn,
+ bool show_exe_name);
+
+ typedef void (*ErrorFn)(const FlatCompiler *flatc, const std::string &err,
+ bool usage, bool show_exe_name);
+
+ // Parameters required to initialize the FlatCompiler.
+ struct InitParams {
+ InitParams()
+ : generators(nullptr),
+ num_generators(0),
+ warn_fn(nullptr),
+ error_fn(nullptr) {}
+
+ const Generator *generators;
+ size_t num_generators;
+ WarnFn warn_fn;
+ ErrorFn error_fn;
+ };
+
+ explicit FlatCompiler(const InitParams &params) : params_(params) {}
+
+ int Compile(int argc, const char **argv);
+
+ std::string GetUsageString(const char *program_name) const;
+
+ private:
+ void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
+ const std::string &contents,
+ std::vector<const char *> &include_directories) const;
+
+ void LoadBinarySchema(Parser &parser, const std::string &filename,
+ const std::string &contents);
+
+ void Warn(const std::string &warn, bool show_exe_name = true) const;
+
+ void Error(const std::string &err, bool usage = true,
+ bool show_exe_name = true) const;
+
+ InitParams params_;
+};
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_FLATC_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h b/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h
new file mode 100644
index 0000000000..d855b67731
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h
@@ -0,0 +1,1636 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef FLATBUFFERS_FLEXBUFFERS_H_
+#define FLATBUFFERS_FLEXBUFFERS_H_
+
+#include <map>
+// Used to select STL variant.
+#include "base.h"
+// We use the basic binary writing functions from the regular FlatBuffers.
+#include "util.h"
+
+#ifdef _MSC_VER
+# include <intrin.h>
+#endif
+
+#if defined(_MSC_VER)
+# pragma warning(push)
+# pragma warning(disable : 4127) // C4127: conditional expression is constant
+#endif
+
+namespace flexbuffers {
+
+class Reference;
+class Map;
+
+// These are used in the lower 2 bits of a type field to determine the size of
+// the elements (and or size field) of the item pointed to (e.g. vector).
+enum BitWidth {
+ BIT_WIDTH_8 = 0,
+ BIT_WIDTH_16 = 1,
+ BIT_WIDTH_32 = 2,
+ BIT_WIDTH_64 = 3,
+};
+
+// These are used as the upper 6 bits of a type field to indicate the actual
+// type.
+enum Type {
+ FBT_NULL = 0,
+ FBT_INT = 1,
+ FBT_UINT = 2,
+ FBT_FLOAT = 3,
+ // Types above stored inline, types below store an offset.
+ FBT_KEY = 4,
+ FBT_STRING = 5,
+ FBT_INDIRECT_INT = 6,
+ FBT_INDIRECT_UINT = 7,
+ FBT_INDIRECT_FLOAT = 8,
+ FBT_MAP = 9,
+ FBT_VECTOR = 10, // Untyped.
+ FBT_VECTOR_INT = 11, // Typed any size (stores no type table).
+ FBT_VECTOR_UINT = 12,
+ FBT_VECTOR_FLOAT = 13,
+ FBT_VECTOR_KEY = 14,
+ // DEPRECATED, use FBT_VECTOR or FBT_VECTOR_KEY instead.
+ // Read test.cpp/FlexBuffersDeprecatedTest() for details on why.
+ FBT_VECTOR_STRING_DEPRECATED = 15,
+ FBT_VECTOR_INT2 = 16, // Typed tuple (no type table, no size field).
+ FBT_VECTOR_UINT2 = 17,
+ FBT_VECTOR_FLOAT2 = 18,
+ FBT_VECTOR_INT3 = 19, // Typed triple (no type table, no size field).
+ FBT_VECTOR_UINT3 = 20,
+ FBT_VECTOR_FLOAT3 = 21,
+ FBT_VECTOR_INT4 = 22, // Typed quad (no type table, no size field).
+ FBT_VECTOR_UINT4 = 23,
+ FBT_VECTOR_FLOAT4 = 24,
+ FBT_BLOB = 25,
+ FBT_BOOL = 26,
+ FBT_VECTOR_BOOL =
+ 36, // To Allow the same type of conversion of type to vector type
+};
+
+inline bool IsInline(Type t) { return t <= FBT_FLOAT || t == FBT_BOOL; }
+
+inline bool IsTypedVectorElementType(Type t) {
+ return (t >= FBT_INT && t <= FBT_STRING) || t == FBT_BOOL;
+}
+
+inline bool IsTypedVector(Type t) {
+ return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING_DEPRECATED) ||
+ t == FBT_VECTOR_BOOL;
+}
+
+inline bool IsFixedTypedVector(Type t) {
+ return t >= FBT_VECTOR_INT2 && t <= FBT_VECTOR_FLOAT4;
+}
+
+inline Type ToTypedVector(Type t, size_t fixed_len = 0) {
+ FLATBUFFERS_ASSERT(IsTypedVectorElementType(t));
+ switch (fixed_len) {
+ case 0: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT);
+ case 2: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT2);
+ case 3: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT3);
+ case 4: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT4);
+ default: FLATBUFFERS_ASSERT(0); return FBT_NULL;
+ }
+}
+
+inline Type ToTypedVectorElementType(Type t) {
+ FLATBUFFERS_ASSERT(IsTypedVector(t));
+ return static_cast<Type>(t - FBT_VECTOR_INT + FBT_INT);
+}
+
+inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) {
+ FLATBUFFERS_ASSERT(IsFixedTypedVector(t));
+ auto fixed_type = t - FBT_VECTOR_INT2;
+ *len = static_cast<uint8_t>(fixed_type / 3 +
+ 2); // 3 types each, starting from length 2.
+ return static_cast<Type>(fixed_type % 3 + FBT_INT);
+}
+
+// TODO: implement proper support for 8/16bit floats, or decide not to
+// support them.
+typedef int16_t half;
+typedef int8_t quarter;
+
+// TODO: can we do this without conditionals using intrinsics or inline asm
+// on some platforms? Given branch prediction the method below should be
+// decently quick, but it is the most frequently executed function.
+// We could do an (unaligned) 64-bit read if we ifdef out the platforms for
+// which that doesn't work (or where we'd read into un-owned memory).
+template<typename R, typename T1, typename T2, typename T4, typename T8>
+R ReadSizedScalar(const uint8_t *data, uint8_t byte_width) {
+ return byte_width < 4
+ ? (byte_width < 2
+ ? static_cast<R>(flatbuffers::ReadScalar<T1>(data))
+ : static_cast<R>(flatbuffers::ReadScalar<T2>(data)))
+ : (byte_width < 8
+ ? static_cast<R>(flatbuffers::ReadScalar<T4>(data))
+ : static_cast<R>(flatbuffers::ReadScalar<T8>(data)));
+}
+
+inline int64_t ReadInt64(const uint8_t *data, uint8_t byte_width) {
+ return ReadSizedScalar<int64_t, int8_t, int16_t, int32_t, int64_t>(
+ data, byte_width);
+}
+
+inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
+ // This is the "hottest" function (all offset lookups use this), so worth
+ // optimizing if possible.
+ // TODO: GCC apparently replaces memcpy by a rep movsb, but only if count is a
+ // constant, which here it isn't. Test if memcpy is still faster than
+ // the conditionals in ReadSizedScalar. Can also use inline asm.
+ // clang-format off
+ #if defined(_MSC_VER) && ((defined(_M_X64) && !defined(_M_ARM64EC)) || defined _M_IX86)
+ uint64_t u = 0;
+ __movsb(reinterpret_cast<uint8_t *>(&u),
+ reinterpret_cast<const uint8_t *>(data), byte_width);
+ return flatbuffers::EndianScalar(u);
+ #else
+ return ReadSizedScalar<uint64_t, uint8_t, uint16_t, uint32_t, uint64_t>(
+ data, byte_width);
+ #endif
+ // clang-format on
+}
+
+inline double ReadDouble(const uint8_t *data, uint8_t byte_width) {
+ return ReadSizedScalar<double, quarter, half, float, double>(data,
+ byte_width);
+}
+
+inline const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) {
+ return offset - ReadUInt64(offset, byte_width);
+}
+
+template<typename T> const uint8_t *Indirect(const uint8_t *offset) {
+ return offset - flatbuffers::ReadScalar<T>(offset);
+}
+
+inline BitWidth WidthU(uint64_t u) {
+#define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width) \
+ { \
+ if (!((u) & ~((1ULL << (width)) - 1ULL))) return BIT_WIDTH_##width; \
+ }
+ FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 8);
+ FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 16);
+ FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 32);
+#undef FLATBUFFERS_GET_FIELD_BIT_WIDTH
+ return BIT_WIDTH_64;
+}
+
+inline BitWidth WidthI(int64_t i) {
+ auto u = static_cast<uint64_t>(i) << 1;
+ return WidthU(i >= 0 ? u : ~u);
+}
+
+inline BitWidth WidthF(double f) {
+ return static_cast<double>(static_cast<float>(f)) == f ? BIT_WIDTH_32
+ : BIT_WIDTH_64;
+}
+
+// Base class of all types below.
+// Points into the data buffer and allows access to one type.
+class Object {
+ public:
+ Object(const uint8_t *data, uint8_t byte_width)
+ : data_(data), byte_width_(byte_width) {}
+
+ protected:
+ const uint8_t *data_;
+ uint8_t byte_width_;
+};
+
+// Object that has a size, obtained either from size prefix, or elsewhere.
+class Sized : public Object {
+ public:
+ // Size prefix.
+ Sized(const uint8_t *data, uint8_t byte_width)
+ : Object(data, byte_width), size_(read_size()) {}
+ // Manual size.
+ Sized(const uint8_t *data, uint8_t byte_width, size_t sz)
+ : Object(data, byte_width), size_(sz) {}
+ size_t size() const { return size_; }
+ // Access size stored in `byte_width_` bytes before data_ pointer.
+ size_t read_size() const {
+ return static_cast<size_t>(ReadUInt64(data_ - byte_width_, byte_width_));
+ }
+
+ protected:
+ size_t size_;
+};
+
+class String : public Sized {
+ public:
+ // Size prefix.
+ String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
+ // Manual size.
+ String(const uint8_t *data, uint8_t byte_width, size_t sz)
+ : Sized(data, byte_width, sz) {}
+
+ size_t length() const { return size(); }
+ const char *c_str() const { return reinterpret_cast<const char *>(data_); }
+ std::string str() const { return std::string(c_str(), size()); }
+
+ static String EmptyString() {
+ static const char *empty_string = "";
+ return String(reinterpret_cast<const uint8_t *>(empty_string), 1, 0);
+ }
+ bool IsTheEmptyString() const { return data_ == EmptyString().data_; }
+};
+
+class Blob : public Sized {
+ public:
+ Blob(const uint8_t *data_buf, uint8_t byte_width)
+ : Sized(data_buf, byte_width) {}
+
+ static Blob EmptyBlob() {
+ static const uint8_t empty_blob[] = { 0 /*len*/ };
+ return Blob(empty_blob + 1, 1);
+ }
+ bool IsTheEmptyBlob() const { return data_ == EmptyBlob().data_; }
+ const uint8_t *data() const { return data_; }
+};
+
+class Vector : public Sized {
+ public:
+ Vector(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
+
+ Reference operator[](size_t i) const;
+
+ static Vector EmptyVector() {
+ static const uint8_t empty_vector[] = { 0 /*len*/ };
+ return Vector(empty_vector + 1, 1);
+ }
+ bool IsTheEmptyVector() const { return data_ == EmptyVector().data_; }
+};
+
+class TypedVector : public Sized {
+ public:
+ TypedVector(const uint8_t *data, uint8_t byte_width, Type element_type)
+ : Sized(data, byte_width), type_(element_type) {}
+
+ Reference operator[](size_t i) const;
+
+ static TypedVector EmptyTypedVector() {
+ static const uint8_t empty_typed_vector[] = { 0 /*len*/ };
+ return TypedVector(empty_typed_vector + 1, 1, FBT_INT);
+ }
+ bool IsTheEmptyVector() const {
+ return data_ == TypedVector::EmptyTypedVector().data_;
+ }
+
+ Type ElementType() { return type_; }
+
+ friend Reference;
+
+ private:
+ Type type_;
+
+ friend Map;
+};
+
+class FixedTypedVector : public Object {
+ public:
+ FixedTypedVector(const uint8_t *data, uint8_t byte_width, Type element_type,
+ uint8_t len)
+ : Object(data, byte_width), type_(element_type), len_(len) {}
+
+ Reference operator[](size_t i) const;
+
+ static FixedTypedVector EmptyFixedTypedVector() {
+ static const uint8_t fixed_empty_vector[] = { 0 /* unused */ };
+ return FixedTypedVector(fixed_empty_vector, 1, FBT_INT, 0);
+ }
+ bool IsTheEmptyFixedTypedVector() const {
+ return data_ == FixedTypedVector::EmptyFixedTypedVector().data_;
+ }
+
+ Type ElementType() { return type_; }
+ uint8_t size() { return len_; }
+
+ private:
+ Type type_;
+ uint8_t len_;
+};
+
+class Map : public Vector {
+ public:
+ Map(const uint8_t *data, uint8_t byte_width) : Vector(data, byte_width) {}
+
+ Reference operator[](const char *key) const;
+ Reference operator[](const std::string &key) const;
+
+ Vector Values() const { return Vector(data_, byte_width_); }
+
+ TypedVector Keys() const {
+ const size_t num_prefixed_fields = 3;
+ auto keys_offset = data_ - byte_width_ * num_prefixed_fields;
+ return TypedVector(Indirect(keys_offset, byte_width_),
+ static_cast<uint8_t>(
+ ReadUInt64(keys_offset + byte_width_, byte_width_)),
+ FBT_KEY);
+ }
+
+ static Map EmptyMap() {
+ static const uint8_t empty_map[] = {
+ 0 /*keys_len*/, 0 /*keys_offset*/, 1 /*keys_width*/, 0 /*len*/
+ };
+ return Map(empty_map + 4, 1);
+ }
+
+ bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; }
+};
+
+template<typename T>
+void AppendToString(std::string &s, T &&v, bool keys_quoted) {
+ s += "[ ";
+ for (size_t i = 0; i < v.size(); i++) {
+ if (i) s += ", ";
+ v[i].ToString(true, keys_quoted, s);
+ }
+ s += " ]";
+}
+
+class Reference {
+ public:
+ Reference()
+ : data_(nullptr),
+ parent_width_(0),
+ byte_width_(BIT_WIDTH_8),
+ type_(FBT_NULL) {}
+
+ Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
+ Type type)
+ : data_(data),
+ parent_width_(parent_width),
+ byte_width_(byte_width),
+ type_(type) {}
+
+ Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type)
+ : data_(data), parent_width_(parent_width) {
+ byte_width_ = 1U << static_cast<BitWidth>(packed_type & 3);
+ type_ = static_cast<Type>(packed_type >> 2);
+ }
+
+ Type GetType() const { return type_; }
+
+ bool IsNull() const { return type_ == FBT_NULL; }
+ bool IsBool() const { return type_ == FBT_BOOL; }
+ bool IsInt() const { return type_ == FBT_INT || type_ == FBT_INDIRECT_INT; }
+ bool IsUInt() const {
+ return type_ == FBT_UINT || type_ == FBT_INDIRECT_UINT;
+ }
+ bool IsIntOrUint() const { return IsInt() || IsUInt(); }
+ bool IsFloat() const {
+ return type_ == FBT_FLOAT || type_ == FBT_INDIRECT_FLOAT;
+ }
+ bool IsNumeric() const { return IsIntOrUint() || IsFloat(); }
+ bool IsString() const { return type_ == FBT_STRING; }
+ bool IsKey() const { return type_ == FBT_KEY; }
+ bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; }
+ bool IsUntypedVector() const { return type_ == FBT_VECTOR; }
+ bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); }
+ bool IsFixedTypedVector() const {
+ return flexbuffers::IsFixedTypedVector(type_);
+ }
+ bool IsAnyVector() const {
+ return (IsTypedVector() || IsFixedTypedVector() || IsVector());
+ }
+ bool IsMap() const { return type_ == FBT_MAP; }
+ bool IsBlob() const { return type_ == FBT_BLOB; }
+ bool AsBool() const {
+ return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_)
+ : AsUInt64()) != 0;
+ }
+
+ // Reads any type as a int64_t. Never fails, does most sensible conversion.
+ // Truncates floats, strings are attempted to be parsed for a number,
+ // vectors/maps return their size. Returns 0 if all else fails.
+ int64_t AsInt64() const {
+ if (type_ == FBT_INT) {
+ // A fast path for the common case.
+ return ReadInt64(data_, parent_width_);
+ } else
+ switch (type_) {
+ case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
+ case FBT_UINT: return ReadUInt64(data_, parent_width_);
+ case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
+ case FBT_FLOAT:
+ return static_cast<int64_t>(ReadDouble(data_, parent_width_));
+ case FBT_INDIRECT_FLOAT:
+ return static_cast<int64_t>(ReadDouble(Indirect(), byte_width_));
+ case FBT_NULL: return 0;
+ case FBT_STRING: return flatbuffers::StringToInt(AsString().c_str());
+ case FBT_VECTOR: return static_cast<int64_t>(AsVector().size());
+ case FBT_BOOL: return ReadInt64(data_, parent_width_);
+ default:
+ // Convert other things to int.
+ return 0;
+ }
+ }
+
+ // TODO: could specialize these to not use AsInt64() if that saves
+ // extension ops in generated code, and use a faster op than ReadInt64.
+ int32_t AsInt32() const { return static_cast<int32_t>(AsInt64()); }
+ int16_t AsInt16() const { return static_cast<int16_t>(AsInt64()); }
+ int8_t AsInt8() const { return static_cast<int8_t>(AsInt64()); }
+
+ uint64_t AsUInt64() const {
+ if (type_ == FBT_UINT) {
+ // A fast path for the common case.
+ return ReadUInt64(data_, parent_width_);
+ } else
+ switch (type_) {
+ case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
+ case FBT_INT: return ReadInt64(data_, parent_width_);
+ case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
+ case FBT_FLOAT:
+ return static_cast<uint64_t>(ReadDouble(data_, parent_width_));
+ case FBT_INDIRECT_FLOAT:
+ return static_cast<uint64_t>(ReadDouble(Indirect(), byte_width_));
+ case FBT_NULL: return 0;
+ case FBT_STRING: return flatbuffers::StringToUInt(AsString().c_str());
+ case FBT_VECTOR: return static_cast<uint64_t>(AsVector().size());
+ case FBT_BOOL: return ReadUInt64(data_, parent_width_);
+ default:
+ // Convert other things to uint.
+ return 0;
+ }
+ }
+
+ uint32_t AsUInt32() const { return static_cast<uint32_t>(AsUInt64()); }
+ uint16_t AsUInt16() const { return static_cast<uint16_t>(AsUInt64()); }
+ uint8_t AsUInt8() const { return static_cast<uint8_t>(AsUInt64()); }
+
+ double AsDouble() const {
+ if (type_ == FBT_FLOAT) {
+ // A fast path for the common case.
+ return ReadDouble(data_, parent_width_);
+ } else
+ switch (type_) {
+ case FBT_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_);
+ case FBT_INT:
+ return static_cast<double>(ReadInt64(data_, parent_width_));
+ case FBT_UINT:
+ return static_cast<double>(ReadUInt64(data_, parent_width_));
+ case FBT_INDIRECT_INT:
+ return static_cast<double>(ReadInt64(Indirect(), byte_width_));
+ case FBT_INDIRECT_UINT:
+ return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
+ case FBT_NULL: return 0.0;
+ case FBT_STRING: {
+ double d;
+ flatbuffers::StringToNumber(AsString().c_str(), &d);
+ return d;
+ }
+ case FBT_VECTOR: return static_cast<double>(AsVector().size());
+ case FBT_BOOL:
+ return static_cast<double>(ReadUInt64(data_, parent_width_));
+ default:
+ // Convert strings and other things to float.
+ return 0;
+ }
+ }
+
+ float AsFloat() const { return static_cast<float>(AsDouble()); }
+
+ const char *AsKey() const {
+ if (type_ == FBT_KEY || type_ == FBT_STRING) {
+ return reinterpret_cast<const char *>(Indirect());
+ } else {
+ return "";
+ }
+ }
+
+ // This function returns the empty string if you try to read something that
+ // is not a string or key.
+ String AsString() const {
+ if (type_ == FBT_STRING) {
+ return String(Indirect(), byte_width_);
+ } else if (type_ == FBT_KEY) {
+ auto key = Indirect();
+ return String(key, byte_width_,
+ strlen(reinterpret_cast<const char *>(key)));
+ } else {
+ return String::EmptyString();
+ }
+ }
+
+ // Unlike AsString(), this will convert any type to a std::string.
+ std::string ToString() const {
+ std::string s;
+ ToString(false, false, s);
+ return s;
+ }
+
+ // 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 {
+ if (type_ == FBT_STRING) {
+ String str(Indirect(), byte_width_);
+ if (strings_quoted) {
+ flatbuffers::EscapeString(str.c_str(), str.length(), &s, true, false);
+ } else {
+ s.append(str.c_str(), str.length());
+ }
+ } else if (IsKey()) {
+ auto str = AsKey();
+ if (keys_quoted) {
+ flatbuffers::EscapeString(str, strlen(str), &s, true, false);
+ } else {
+ s += str;
+ }
+ } else if (IsInt()) {
+ s += flatbuffers::NumToString(AsInt64());
+ } else if (IsUInt()) {
+ s += flatbuffers::NumToString(AsUInt64());
+ } else if (IsFloat()) {
+ s += flatbuffers::NumToString(AsDouble());
+ } else if (IsNull()) {
+ s += "null";
+ } else if (IsBool()) {
+ s += AsBool() ? "true" : "false";
+ } else if (IsMap()) {
+ s += "{ ";
+ auto m = AsMap();
+ auto keys = m.Keys();
+ auto vals = m.Values();
+ for (size_t i = 0; i < keys.size(); i++) {
+ keys[i].ToString(true, keys_quoted, s);
+ s += ": ";
+ vals[i].ToString(true, keys_quoted, s);
+ if (i < keys.size() - 1) s += ", ";
+ }
+ s += " }";
+ } else if (IsVector()) {
+ AppendToString<Vector>(s, AsVector(), keys_quoted);
+ } else if (IsTypedVector()) {
+ AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted);
+ } else if (IsFixedTypedVector()) {
+ AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted);
+ } else if (IsBlob()) {
+ auto blob = AsBlob();
+ flatbuffers::EscapeString(reinterpret_cast<const char *>(blob.data()),
+ blob.size(), &s, true, false);
+ } else {
+ s += "(?)";
+ }
+ }
+
+ // This function returns the empty blob if you try to read a not-blob.
+ // Strings can be viewed as blobs too.
+ Blob AsBlob() const {
+ if (type_ == FBT_BLOB || type_ == FBT_STRING) {
+ return Blob(Indirect(), byte_width_);
+ } else {
+ return Blob::EmptyBlob();
+ }
+ }
+
+ // This function returns the empty vector if you try to read a not-vector.
+ // Maps can be viewed as vectors too.
+ Vector AsVector() const {
+ if (type_ == FBT_VECTOR || type_ == FBT_MAP) {
+ return Vector(Indirect(), byte_width_);
+ } else {
+ return Vector::EmptyVector();
+ }
+ }
+
+ TypedVector AsTypedVector() const {
+ if (IsTypedVector()) {
+ auto tv =
+ TypedVector(Indirect(), byte_width_, ToTypedVectorElementType(type_));
+ if (tv.type_ == FBT_STRING) {
+ // These can't be accessed as strings, since we don't know the bit-width
+ // of the size field, see the declaration of
+ // FBT_VECTOR_STRING_DEPRECATED above for details.
+ // We change the type here to be keys, which are a subtype of strings,
+ // and will ignore the size field. This will truncate strings with
+ // embedded nulls.
+ tv.type_ = FBT_KEY;
+ }
+ return tv;
+ } else {
+ return TypedVector::EmptyTypedVector();
+ }
+ }
+
+ FixedTypedVector AsFixedTypedVector() const {
+ if (IsFixedTypedVector()) {
+ uint8_t len = 0;
+ auto vtype = ToFixedTypedVectorElementType(type_, &len);
+ return FixedTypedVector(Indirect(), byte_width_, vtype, len);
+ } else {
+ return FixedTypedVector::EmptyFixedTypedVector();
+ }
+ }
+
+ Map AsMap() const {
+ if (type_ == FBT_MAP) {
+ return Map(Indirect(), byte_width_);
+ } else {
+ return Map::EmptyMap();
+ }
+ }
+
+ template<typename T> T As() const;
+
+ // Experimental: Mutation functions.
+ // These allow scalars in an already created buffer to be updated in-place.
+ // Since by default scalars are stored in the smallest possible space,
+ // the new value may not fit, in which case these functions return false.
+ // To avoid this, you can construct the values you intend to mutate using
+ // Builder::ForceMinimumBitWidth.
+ bool MutateInt(int64_t i) {
+ if (type_ == FBT_INT) {
+ return Mutate(data_, i, parent_width_, WidthI(i));
+ } else if (type_ == FBT_INDIRECT_INT) {
+ return Mutate(Indirect(), i, byte_width_, WidthI(i));
+ } else if (type_ == FBT_UINT) {
+ auto u = static_cast<uint64_t>(i);
+ return Mutate(data_, u, parent_width_, WidthU(u));
+ } else if (type_ == FBT_INDIRECT_UINT) {
+ auto u = static_cast<uint64_t>(i);
+ return Mutate(Indirect(), u, byte_width_, WidthU(u));
+ } else {
+ return false;
+ }
+ }
+
+ bool MutateBool(bool b) {
+ return type_ == FBT_BOOL && Mutate(data_, b, parent_width_, BIT_WIDTH_8);
+ }
+
+ bool MutateUInt(uint64_t u) {
+ if (type_ == FBT_UINT) {
+ return Mutate(data_, u, parent_width_, WidthU(u));
+ } else if (type_ == FBT_INDIRECT_UINT) {
+ return Mutate(Indirect(), u, byte_width_, WidthU(u));
+ } else if (type_ == FBT_INT) {
+ auto i = static_cast<int64_t>(u);
+ return Mutate(data_, i, parent_width_, WidthI(i));
+ } else if (type_ == FBT_INDIRECT_INT) {
+ auto i = static_cast<int64_t>(u);
+ return Mutate(Indirect(), i, byte_width_, WidthI(i));
+ } else {
+ return false;
+ }
+ }
+
+ bool MutateFloat(float f) {
+ if (type_ == FBT_FLOAT) {
+ return MutateF(data_, f, parent_width_, BIT_WIDTH_32);
+ } else if (type_ == FBT_INDIRECT_FLOAT) {
+ return MutateF(Indirect(), f, byte_width_, BIT_WIDTH_32);
+ } else {
+ return false;
+ }
+ }
+
+ bool MutateFloat(double d) {
+ if (type_ == FBT_FLOAT) {
+ return MutateF(data_, d, parent_width_, WidthF(d));
+ } else if (type_ == FBT_INDIRECT_FLOAT) {
+ return MutateF(Indirect(), d, byte_width_, WidthF(d));
+ } else {
+ return false;
+ }
+ }
+
+ bool MutateString(const char *str, size_t len) {
+ auto s = AsString();
+ if (s.IsTheEmptyString()) return false;
+ // This is very strict, could allow shorter strings, but that creates
+ // garbage.
+ if (s.length() != len) return false;
+ memcpy(const_cast<char *>(s.c_str()), str, len);
+ return true;
+ }
+ bool MutateString(const char *str) { return MutateString(str, strlen(str)); }
+ bool MutateString(const std::string &str) {
+ return MutateString(str.data(), str.length());
+ }
+
+ private:
+ const uint8_t *Indirect() const {
+ return flexbuffers::Indirect(data_, parent_width_);
+ }
+
+ template<typename T>
+ bool Mutate(const uint8_t *dest, T t, size_t byte_width,
+ BitWidth value_width) {
+ auto fits = static_cast<size_t>(static_cast<size_t>(1U) << value_width) <=
+ byte_width;
+ if (fits) {
+ t = flatbuffers::EndianScalar(t);
+ memcpy(const_cast<uint8_t *>(dest), &t, byte_width);
+ }
+ return fits;
+ }
+
+ template<typename T>
+ bool MutateF(const uint8_t *dest, T t, size_t byte_width,
+ BitWidth value_width) {
+ if (byte_width == sizeof(double))
+ return Mutate(dest, static_cast<double>(t), byte_width, value_width);
+ if (byte_width == sizeof(float))
+ return Mutate(dest, static_cast<float>(t), byte_width, value_width);
+ FLATBUFFERS_ASSERT(false);
+ return false;
+ }
+
+ const uint8_t *data_;
+ uint8_t parent_width_;
+ uint8_t byte_width_;
+ Type type_;
+};
+
+// Template specialization for As().
+template<> inline bool Reference::As<bool>() const { return AsBool(); }
+
+template<> inline int8_t Reference::As<int8_t>() const { return AsInt8(); }
+template<> inline int16_t Reference::As<int16_t>() const { return AsInt16(); }
+template<> inline int32_t Reference::As<int32_t>() const { return AsInt32(); }
+template<> inline int64_t Reference::As<int64_t>() const { return AsInt64(); }
+
+template<> inline uint8_t Reference::As<uint8_t>() const { return AsUInt8(); }
+template<> inline uint16_t Reference::As<uint16_t>() const {
+ return AsUInt16();
+}
+template<> inline uint32_t Reference::As<uint32_t>() const {
+ return AsUInt32();
+}
+template<> inline uint64_t Reference::As<uint64_t>() const {
+ return AsUInt64();
+}
+
+template<> inline double Reference::As<double>() const { return AsDouble(); }
+template<> inline float Reference::As<float>() const { return AsFloat(); }
+
+template<> inline String Reference::As<String>() const { return AsString(); }
+template<> inline std::string Reference::As<std::string>() const {
+ return AsString().str();
+}
+
+template<> inline Blob Reference::As<Blob>() const { return AsBlob(); }
+template<> inline Vector Reference::As<Vector>() const { return AsVector(); }
+template<> inline TypedVector Reference::As<TypedVector>() const {
+ return AsTypedVector();
+}
+template<> inline FixedTypedVector Reference::As<FixedTypedVector>() const {
+ return AsFixedTypedVector();
+}
+template<> inline Map Reference::As<Map>() const { return AsMap(); }
+
+inline uint8_t PackedType(BitWidth bit_width, Type type) {
+ return static_cast<uint8_t>(bit_width | (type << 2));
+}
+
+inline uint8_t NullPackedType() { return PackedType(BIT_WIDTH_8, FBT_NULL); }
+
+// Vector accessors.
+// Note: if you try to access outside of bounds, you get a Null value back
+// instead. Normally this would be an assert, but since this is "dynamically
+// typed" data, you may not want that (someone sends you a 2d vector and you
+// wanted 3d).
+// The Null converts seamlessly into a default value for any other type.
+// TODO(wvo): Could introduce an #ifdef that makes this into an assert?
+inline Reference Vector::operator[](size_t i) const {
+ auto len = size();
+ if (i >= len) return Reference(nullptr, 1, NullPackedType());
+ auto packed_type = (data_ + len * byte_width_)[i];
+ auto elem = data_ + i * byte_width_;
+ return Reference(elem, byte_width_, packed_type);
+}
+
+inline Reference TypedVector::operator[](size_t i) const {
+ auto len = size();
+ if (i >= len) return Reference(nullptr, 1, NullPackedType());
+ auto elem = data_ + i * byte_width_;
+ return Reference(elem, byte_width_, 1, type_);
+}
+
+inline Reference FixedTypedVector::operator[](size_t i) const {
+ if (i >= len_) return Reference(nullptr, 1, NullPackedType());
+ auto elem = data_ + i * byte_width_;
+ return Reference(elem, byte_width_, 1, type_);
+}
+
+template<typename T> int KeyCompare(const void *key, const void *elem) {
+ auto str_elem = reinterpret_cast<const char *>(
+ Indirect<T>(reinterpret_cast<const uint8_t *>(elem)));
+ auto skey = reinterpret_cast<const char *>(key);
+ return strcmp(skey, str_elem);
+}
+
+inline Reference Map::operator[](const char *key) const {
+ auto keys = Keys();
+ // We can't pass keys.byte_width_ to the comparison function, so we have
+ // to pick the right one ahead of time.
+ int (*comp)(const void *, const void *) = nullptr;
+ switch (keys.byte_width_) {
+ case 1: comp = KeyCompare<uint8_t>; break;
+ case 2: comp = KeyCompare<uint16_t>; break;
+ case 4: comp = KeyCompare<uint32_t>; break;
+ case 8: comp = KeyCompare<uint64_t>; break;
+ }
+ auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp);
+ if (!res) return Reference(nullptr, 1, NullPackedType());
+ auto i = (reinterpret_cast<uint8_t *>(res) - keys.data_) / keys.byte_width_;
+ return (*static_cast<const Vector *>(this))[i];
+}
+
+inline Reference Map::operator[](const std::string &key) const {
+ return (*this)[key.c_str()];
+}
+
+inline Reference GetRoot(const uint8_t *buffer, size_t size) {
+ // See Finish() below for the serialization counterpart of this.
+ // The root starts at the end of the buffer, so we parse backwards from there.
+ auto end = buffer + size;
+ auto byte_width = *--end;
+ auto packed_type = *--end;
+ end -= byte_width; // The root data item.
+ return Reference(end, byte_width, packed_type);
+}
+
+inline Reference GetRoot(const std::vector<uint8_t> &buffer) {
+ return GetRoot(flatbuffers::vector_data(buffer), buffer.size());
+}
+
+// Flags that configure how the Builder behaves.
+// The "Share" flags determine if the Builder automatically tries to pool
+// this type. Pooling can reduce the size of serialized data if there are
+// multiple maps of the same kind, at the expense of slightly slower
+// serialization (the cost of lookups) and more memory use (std::set).
+// By default this is on for keys, but off for strings.
+// Turn keys off if you have e.g. only one map.
+// Turn strings on if you expect many non-unique string values.
+// Additionally, sharing key vectors can save space if you have maps with
+// identical field populations.
+enum BuilderFlag {
+ BUILDER_FLAG_NONE = 0,
+ BUILDER_FLAG_SHARE_KEYS = 1,
+ BUILDER_FLAG_SHARE_STRINGS = 2,
+ BUILDER_FLAG_SHARE_KEYS_AND_STRINGS = 3,
+ BUILDER_FLAG_SHARE_KEY_VECTORS = 4,
+ BUILDER_FLAG_SHARE_ALL = 7,
+};
+
+class Builder FLATBUFFERS_FINAL_CLASS {
+ public:
+ Builder(size_t initial_size = 256,
+ BuilderFlag flags = BUILDER_FLAG_SHARE_KEYS)
+ : buf_(initial_size),
+ finished_(false),
+ has_duplicate_keys_(false),
+ flags_(flags),
+ force_min_bit_width_(BIT_WIDTH_8),
+ key_pool(KeyOffsetCompare(buf_)),
+ string_pool(StringOffsetCompare(buf_)) {
+ buf_.clear();
+ }
+
+#ifdef FLATBUFFERS_DEFAULT_DECLARATION
+ Builder(Builder &&) = default;
+ Builder &operator=(Builder &&) = default;
+#endif
+
+ /// @brief Get the serialized buffer (after you call `Finish()`).
+ /// @return Returns a vector owned by this class.
+ const std::vector<uint8_t> &GetBuffer() const {
+ Finished();
+ return buf_;
+ }
+
+ // Size of the buffer. Does not include unfinished values.
+ size_t GetSize() const { return buf_.size(); }
+
+ // Reset all state so we can re-use the buffer.
+ void Clear() {
+ buf_.clear();
+ stack_.clear();
+ finished_ = false;
+ // flags_ remains as-is;
+ force_min_bit_width_ = BIT_WIDTH_8;
+ key_pool.clear();
+ string_pool.clear();
+ }
+
+ // All value constructing functions below have two versions: one that
+ // takes a key (for placement inside a map) and one that doesn't (for inside
+ // vectors and elsewhere).
+
+ void Null() { stack_.push_back(Value()); }
+ void Null(const char *key) {
+ Key(key);
+ Null();
+ }
+
+ void Int(int64_t i) { stack_.push_back(Value(i, FBT_INT, WidthI(i))); }
+ void Int(const char *key, int64_t i) {
+ Key(key);
+ Int(i);
+ }
+
+ void UInt(uint64_t u) { stack_.push_back(Value(u, FBT_UINT, WidthU(u))); }
+ void UInt(const char *key, uint64_t u) {
+ Key(key);
+ UInt(u);
+ }
+
+ void Float(float f) { stack_.push_back(Value(f)); }
+ void Float(const char *key, float f) {
+ Key(key);
+ Float(f);
+ }
+
+ void Double(double f) { stack_.push_back(Value(f)); }
+ void Double(const char *key, double d) {
+ Key(key);
+ Double(d);
+ }
+
+ void Bool(bool b) { stack_.push_back(Value(b)); }
+ void Bool(const char *key, bool b) {
+ Key(key);
+ Bool(b);
+ }
+
+ void IndirectInt(int64_t i) { PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); }
+ void IndirectInt(const char *key, int64_t i) {
+ Key(key);
+ IndirectInt(i);
+ }
+
+ void IndirectUInt(uint64_t u) {
+ PushIndirect(u, FBT_INDIRECT_UINT, WidthU(u));
+ }
+ void IndirectUInt(const char *key, uint64_t u) {
+ Key(key);
+ IndirectUInt(u);
+ }
+
+ void IndirectFloat(float f) {
+ PushIndirect(f, FBT_INDIRECT_FLOAT, BIT_WIDTH_32);
+ }
+ void IndirectFloat(const char *key, float f) {
+ Key(key);
+ IndirectFloat(f);
+ }
+
+ void IndirectDouble(double f) {
+ PushIndirect(f, FBT_INDIRECT_FLOAT, WidthF(f));
+ }
+ void IndirectDouble(const char *key, double d) {
+ Key(key);
+ IndirectDouble(d);
+ }
+
+ size_t Key(const char *str, size_t len) {
+ auto sloc = buf_.size();
+ WriteBytes(str, len + 1);
+ if (flags_ & BUILDER_FLAG_SHARE_KEYS) {
+ auto it = key_pool.find(sloc);
+ if (it != key_pool.end()) {
+ // Already in the buffer. Remove key we just serialized, and use
+ // existing offset instead.
+ buf_.resize(sloc);
+ sloc = *it;
+ } else {
+ key_pool.insert(sloc);
+ }
+ }
+ stack_.push_back(Value(static_cast<uint64_t>(sloc), FBT_KEY, BIT_WIDTH_8));
+ return sloc;
+ }
+
+ size_t Key(const char *str) { return Key(str, strlen(str)); }
+ size_t Key(const std::string &str) { return Key(str.c_str(), str.size()); }
+
+ size_t String(const char *str, size_t len) {
+ auto reset_to = buf_.size();
+ auto sloc = CreateBlob(str, len, 1, FBT_STRING);
+ if (flags_ & BUILDER_FLAG_SHARE_STRINGS) {
+ StringOffset so(sloc, len);
+ auto it = string_pool.find(so);
+ if (it != string_pool.end()) {
+ // Already in the buffer. Remove string we just serialized, and use
+ // existing offset instead.
+ buf_.resize(reset_to);
+ sloc = it->first;
+ stack_.back().u_ = sloc;
+ } else {
+ string_pool.insert(so);
+ }
+ }
+ return sloc;
+ }
+ size_t String(const char *str) { return String(str, strlen(str)); }
+ size_t String(const std::string &str) {
+ return String(str.c_str(), str.size());
+ }
+ void String(const flexbuffers::String &str) {
+ String(str.c_str(), str.length());
+ }
+
+ void String(const char *key, const char *str) {
+ Key(key);
+ String(str);
+ }
+ void String(const char *key, const std::string &str) {
+ Key(key);
+ String(str);
+ }
+ void String(const char *key, const flexbuffers::String &str) {
+ Key(key);
+ String(str);
+ }
+
+ size_t Blob(const void *data, size_t len) {
+ return CreateBlob(data, len, 0, FBT_BLOB);
+ }
+ size_t Blob(const std::vector<uint8_t> &v) {
+ return CreateBlob(flatbuffers::vector_data(v), v.size(), 0, FBT_BLOB);
+ }
+
+ // TODO(wvo): support all the FlexBuffer types (like flexbuffers::String),
+ // e.g. Vector etc. Also in overloaded versions.
+ // Also some FlatBuffers types?
+
+ size_t StartVector() { return stack_.size(); }
+ size_t StartVector(const char *key) {
+ Key(key);
+ return stack_.size();
+ }
+ size_t StartMap() { return stack_.size(); }
+ size_t StartMap(const char *key) {
+ Key(key);
+ return stack_.size();
+ }
+
+ // TODO(wvo): allow this to specify an aligment greater than the natural
+ // alignment.
+ size_t EndVector(size_t start, bool typed, bool fixed) {
+ auto vec = CreateVector(start, stack_.size() - start, 1, typed, fixed);
+ // Remove temp elements and return vector.
+ stack_.resize(start);
+ stack_.push_back(vec);
+ return static_cast<size_t>(vec.u_);
+ }
+
+ 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;
+ // Make sure keys are all strings:
+ for (auto key = start; key < stack_.size(); key += 2) {
+ FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY);
+ }
+ // Now sort values, so later we can do a binary search lookup.
+ // We want to sort 2 array elements at a time.
+ struct TwoValue {
+ Value key;
+ Value val;
+ };
+ // TODO(wvo): strict aliasing?
+ // TODO(wvo): allow the caller to indicate the data is already sorted
+ // for maximum efficiency? With an assert to check sortedness to make sure
+ // we're not breaking binary search.
+ // Or, we can track if the map is sorted as keys are added which would be
+ // be quite cheap (cheaper than checking it here), so we can skip this
+ // step automatically when appliccable, and encourage people to write in
+ // sorted fashion.
+ // std::sort is typically already a lot faster on sorted data though.
+ auto dict =
+ reinterpret_cast<TwoValue *>(flatbuffers::vector_data(stack_) + start);
+ std::sort(dict, dict + len,
+ [&](const TwoValue &a, const TwoValue &b) -> bool {
+ auto as = reinterpret_cast<const char *>(
+ flatbuffers::vector_data(buf_) + a.key.u_);
+ auto bs = reinterpret_cast<const char *>(
+ flatbuffers::vector_data(buf_) + b.key.u_);
+ auto comp = strcmp(as, bs);
+ // We want to disallow duplicate keys, since this results in a
+ // map where values cannot be found.
+ // But we can't assert here (since we don't want to fail on
+ // random JSON input) or have an error mechanism.
+ // Instead, we set has_duplicate_keys_ in the builder to
+ // signal this.
+ // TODO: Have to check for pointer equality, as some sort
+ // implementation apparently call this function with the same
+ // element?? Why?
+ if (!comp && &a != &b) has_duplicate_keys_ = true;
+ return comp < 0;
+ });
+ // First create a vector out of all keys.
+ // TODO(wvo): if kBuilderFlagShareKeyVectors is true, see if we can share
+ // the first vector.
+ auto keys = CreateVector(start, len, 2, true, false);
+ auto vec = CreateVector(start + 1, len, 2, false, false, &keys);
+ // Remove temp elements and return map.
+ stack_.resize(start);
+ stack_.push_back(vec);
+ return static_cast<size_t>(vec.u_);
+ }
+
+ // Call this after EndMap to see if the map had any duplicate keys.
+ // Any map with such keys won't be able to retrieve all values.
+ bool HasDuplicateKeys() const { return has_duplicate_keys_; }
+
+ template<typename F> size_t Vector(F f) {
+ auto start = StartVector();
+ f();
+ return EndVector(start, false, false);
+ }
+ template<typename F, typename T> size_t Vector(F f, T &state) {
+ auto start = StartVector();
+ f(state);
+ return EndVector(start, false, false);
+ }
+ template<typename F> size_t Vector(const char *key, F f) {
+ auto start = StartVector(key);
+ f();
+ return EndVector(start, false, false);
+ }
+ template<typename F, typename T>
+ size_t Vector(const char *key, F f, T &state) {
+ auto start = StartVector(key);
+ f(state);
+ return EndVector(start, false, false);
+ }
+
+ template<typename T> void Vector(const T *elems, size_t len) {
+ if (flatbuffers::is_scalar<T>::value) {
+ // This path should be a lot quicker and use less space.
+ ScalarVector(elems, len, false);
+ } else {
+ auto start = StartVector();
+ for (size_t i = 0; i < len; i++) Add(elems[i]);
+ EndVector(start, false, false);
+ }
+ }
+ template<typename T>
+ void Vector(const char *key, const T *elems, size_t len) {
+ Key(key);
+ Vector(elems, len);
+ }
+ template<typename T> void Vector(const std::vector<T> &vec) {
+ Vector(flatbuffers::vector_data(vec), vec.size());
+ }
+
+ template<typename F> size_t TypedVector(F f) {
+ auto start = StartVector();
+ f();
+ return EndVector(start, true, false);
+ }
+ template<typename F, typename T> size_t TypedVector(F f, T &state) {
+ auto start = StartVector();
+ f(state);
+ return EndVector(start, true, false);
+ }
+ template<typename F> size_t TypedVector(const char *key, F f) {
+ auto start = StartVector(key);
+ f();
+ return EndVector(start, true, false);
+ }
+ template<typename F, typename T>
+ size_t TypedVector(const char *key, F f, T &state) {
+ auto start = StartVector(key);
+ f(state);
+ return EndVector(start, true, false);
+ }
+
+ template<typename T> size_t FixedTypedVector(const T *elems, size_t len) {
+ // We only support a few fixed vector lengths. Anything bigger use a
+ // regular typed vector.
+ FLATBUFFERS_ASSERT(len >= 2 && len <= 4);
+ // And only scalar values.
+ static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
+ return ScalarVector(elems, len, true);
+ }
+
+ template<typename T>
+ size_t FixedTypedVector(const char *key, const T *elems, size_t len) {
+ Key(key);
+ return FixedTypedVector(elems, len);
+ }
+
+ template<typename F> size_t Map(F f) {
+ auto start = StartMap();
+ f();
+ return EndMap(start);
+ }
+ template<typename F, typename T> size_t Map(F f, T &state) {
+ auto start = StartMap();
+ f(state);
+ return EndMap(start);
+ }
+ template<typename F> size_t Map(const char *key, F f) {
+ auto start = StartMap(key);
+ f();
+ return EndMap(start);
+ }
+ template<typename F, typename T> size_t Map(const char *key, F f, T &state) {
+ auto start = StartMap(key);
+ f(state);
+ return EndMap(start);
+ }
+ template<typename T> void Map(const std::map<std::string, T> &map) {
+ auto start = StartMap();
+ for (auto it = map.begin(); it != map.end(); ++it)
+ Add(it->first.c_str(), it->second);
+ EndMap(start);
+ }
+
+ // 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
+ // and still do some explicit sharing. For example:
+ // builder.IndirectDouble(M_PI);
+ // auto id = builder.LastValue(); // Remember where we stored it.
+ // .. more code goes here ..
+ // builder.ReuseValue(id); // Refers to same double by offset.
+ // LastValue works regardless of whether the value has a key or not.
+ // Works on any data type.
+ struct Value;
+ Value LastValue() { return stack_.back(); }
+ void ReuseValue(Value v) { stack_.push_back(v); }
+ void ReuseValue(const char *key, Value v) {
+ Key(key);
+ ReuseValue(v);
+ }
+
+ // Overloaded Add that tries to call the correct function above.
+ void Add(int8_t i) { Int(i); }
+ void Add(int16_t i) { Int(i); }
+ void Add(int32_t i) { Int(i); }
+ void Add(int64_t i) { Int(i); }
+ void Add(uint8_t u) { UInt(u); }
+ void Add(uint16_t u) { UInt(u); }
+ void Add(uint32_t u) { UInt(u); }
+ void Add(uint64_t u) { UInt(u); }
+ void Add(float f) { Float(f); }
+ void Add(double d) { Double(d); }
+ void Add(bool b) { Bool(b); }
+ void Add(const char *str) { String(str); }
+ void Add(const std::string &str) { String(str); }
+ void Add(const flexbuffers::String &str) { String(str); }
+
+ template<typename T> void Add(const std::vector<T> &vec) { Vector(vec); }
+
+ template<typename T> void Add(const char *key, const T &t) {
+ Key(key);
+ Add(t);
+ }
+
+ template<typename T> void Add(const std::map<std::string, T> &map) {
+ Map(map);
+ }
+
+ template<typename T> void operator+=(const T &t) { Add(t); }
+
+ // This function is useful in combination with the Mutate* functions above.
+ // It forces elements of vectors and maps to have a minimum size, such that
+ // they can later be updated without failing.
+ // Call with no arguments to reset.
+ void ForceMinimumBitWidth(BitWidth bw = BIT_WIDTH_8) {
+ force_min_bit_width_ = bw;
+ }
+
+ void Finish() {
+ // If you hit this assert, you likely have objects that were never included
+ // in a parent. You need to have exactly one root to finish a buffer.
+ // Check your Start/End calls are matched, and all objects are inside
+ // some other object.
+ FLATBUFFERS_ASSERT(stack_.size() == 1);
+
+ // Write root value.
+ auto byte_width = Align(stack_[0].ElemWidth(buf_.size(), 0));
+ WriteAny(stack_[0], byte_width);
+ // Write root type.
+ Write(stack_[0].StoredPackedType(), 1);
+ // Write root size. Normally determined by parent, but root has no parent :)
+ Write(byte_width, 1);
+
+ finished_ = true;
+ }
+
+ private:
+ void Finished() const {
+ // If you get this assert, you're attempting to get access a buffer
+ // which hasn't been finished yet. Be sure to call
+ // Builder::Finish with your root object.
+ FLATBUFFERS_ASSERT(finished_);
+ }
+
+ // Align to prepare for writing a scalar with a certain size.
+ uint8_t Align(BitWidth alignment) {
+ auto byte_width = 1U << alignment;
+ buf_.insert(buf_.end(), flatbuffers::PaddingBytes(buf_.size(), byte_width),
+ 0);
+ return static_cast<uint8_t>(byte_width);
+ }
+
+ void WriteBytes(const void *val, size_t size) {
+ buf_.insert(buf_.end(), reinterpret_cast<const uint8_t *>(val),
+ reinterpret_cast<const uint8_t *>(val) + size);
+ }
+
+ template<typename T> void Write(T val, size_t byte_width) {
+ FLATBUFFERS_ASSERT(sizeof(T) >= byte_width);
+ val = flatbuffers::EndianScalar(val);
+ WriteBytes(&val, byte_width);
+ }
+
+ void WriteDouble(double f, uint8_t byte_width) {
+ switch (byte_width) {
+ case 8: Write(f, byte_width); break;
+ case 4: Write(static_cast<float>(f), byte_width); break;
+ // case 2: Write(static_cast<half>(f), byte_width); break;
+ // case 1: Write(static_cast<quarter>(f), byte_width); break;
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+
+ void WriteOffset(uint64_t o, uint8_t byte_width) {
+ auto reloff = buf_.size() - o;
+ FLATBUFFERS_ASSERT(byte_width == 8 || reloff < 1ULL << (byte_width * 8));
+ Write(reloff, byte_width);
+ }
+
+ template<typename T> void PushIndirect(T val, Type type, BitWidth bit_width) {
+ auto byte_width = Align(bit_width);
+ auto iloc = buf_.size();
+ Write(val, byte_width);
+ stack_.push_back(Value(static_cast<uint64_t>(iloc), type, bit_width));
+ }
+
+ static BitWidth WidthB(size_t byte_width) {
+ switch (byte_width) {
+ case 1: return BIT_WIDTH_8;
+ case 2: return BIT_WIDTH_16;
+ case 4: return BIT_WIDTH_32;
+ case 8: return BIT_WIDTH_64;
+ default: FLATBUFFERS_ASSERT(false); return BIT_WIDTH_64;
+ }
+ }
+
+ template<typename T> static Type GetScalarType() {
+ static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
+ return flatbuffers::is_floating_point<T>::value
+ ? FBT_FLOAT
+ : flatbuffers::is_same<T, bool>::value
+ ? FBT_BOOL
+ : (flatbuffers::is_unsigned<T>::value ? FBT_UINT
+ : FBT_INT);
+ }
+
+ public:
+ // This was really intended to be private, except for LastValue/ReuseValue.
+ struct Value {
+ union {
+ int64_t i_;
+ uint64_t u_;
+ double f_;
+ };
+
+ Type type_;
+
+ // For scalars: of itself, for vector: of its elements, for string: length.
+ BitWidth min_bit_width_;
+
+ Value() : i_(0), type_(FBT_NULL), min_bit_width_(BIT_WIDTH_8) {}
+
+ Value(bool b)
+ : u_(static_cast<uint64_t>(b)),
+ type_(FBT_BOOL),
+ min_bit_width_(BIT_WIDTH_8) {}
+
+ Value(int64_t i, Type t, BitWidth bw)
+ : i_(i), type_(t), min_bit_width_(bw) {}
+ Value(uint64_t u, Type t, BitWidth bw)
+ : u_(u), type_(t), min_bit_width_(bw) {}
+
+ Value(float f)
+ : f_(static_cast<double>(f)),
+ type_(FBT_FLOAT),
+ min_bit_width_(BIT_WIDTH_32) {}
+ Value(double f) : f_(f), type_(FBT_FLOAT), min_bit_width_(WidthF(f)) {}
+
+ uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const {
+ return PackedType(StoredWidth(parent_bit_width_), type_);
+ }
+
+ BitWidth ElemWidth(size_t buf_size, size_t elem_index) const {
+ if (IsInline(type_)) {
+ return min_bit_width_;
+ } else {
+ // We have an absolute offset, but want to store a relative offset
+ // elem_index elements beyond the current buffer end. Since whether
+ // the relative offset fits in a certain byte_width depends on
+ // the size of the elements before it (and their alignment), we have
+ // to test for each size in turn.
+ for (size_t byte_width = 1;
+ byte_width <= sizeof(flatbuffers::largest_scalar_t);
+ byte_width *= 2) {
+ // Where are we going to write this offset?
+ auto offset_loc = buf_size +
+ flatbuffers::PaddingBytes(buf_size, byte_width) +
+ elem_index * byte_width;
+ // Compute relative offset.
+ auto offset = offset_loc - u_;
+ // Does it fit?
+ auto bit_width = WidthU(offset);
+ if (static_cast<size_t>(static_cast<size_t>(1U) << bit_width) ==
+ byte_width)
+ return bit_width;
+ }
+ FLATBUFFERS_ASSERT(false); // Must match one of the sizes above.
+ return BIT_WIDTH_64;
+ }
+ }
+
+ BitWidth StoredWidth(BitWidth parent_bit_width_ = BIT_WIDTH_8) const {
+ if (IsInline(type_)) {
+ return (std::max)(min_bit_width_, parent_bit_width_);
+ } else {
+ return min_bit_width_;
+ }
+ }
+ };
+
+ private:
+ void WriteAny(const Value &val, uint8_t byte_width) {
+ switch (val.type_) {
+ case FBT_NULL:
+ case FBT_INT: Write(val.i_, byte_width); break;
+ case FBT_BOOL:
+ case FBT_UINT: Write(val.u_, byte_width); break;
+ case FBT_FLOAT: WriteDouble(val.f_, byte_width); break;
+ default: WriteOffset(val.u_, byte_width); break;
+ }
+ }
+
+ size_t CreateBlob(const void *data, size_t len, size_t trailing, Type type) {
+ auto bit_width = WidthU(len);
+ auto byte_width = Align(bit_width);
+ Write<uint64_t>(len, byte_width);
+ auto sloc = buf_.size();
+ WriteBytes(data, len + trailing);
+ stack_.push_back(Value(static_cast<uint64_t>(sloc), type, bit_width));
+ return sloc;
+ }
+
+ template<typename T>
+ size_t ScalarVector(const T *elems, size_t len, bool fixed) {
+ auto vector_type = GetScalarType<T>();
+ auto byte_width = sizeof(T);
+ auto bit_width = WidthB(byte_width);
+ // If you get this assert, you're trying to write a vector with a size
+ // field that is bigger than the scalars you're trying to write (e.g. a
+ // byte vector > 255 elements). For such types, write a "blob" instead.
+ // TODO: instead of asserting, could write vector with larger elements
+ // instead, though that would be wasteful.
+ FLATBUFFERS_ASSERT(WidthU(len) <= bit_width);
+ Align(bit_width);
+ if (!fixed) Write<uint64_t>(len, byte_width);
+ auto vloc = buf_.size();
+ for (size_t i = 0; i < len; i++) Write(elems[i], byte_width);
+ stack_.push_back(Value(static_cast<uint64_t>(vloc),
+ ToTypedVector(vector_type, fixed ? len : 0),
+ bit_width));
+ return vloc;
+ }
+
+ Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed,
+ bool fixed, const Value *keys = nullptr) {
+ FLATBUFFERS_ASSERT(
+ !fixed ||
+ typed); // typed=false, fixed=true combination is not supported.
+ // Figure out smallest bit width we can store this vector with.
+ auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len));
+ auto prefix_elems = 1;
+ if (keys) {
+ // If this vector is part of a map, we will pre-fix an offset to the keys
+ // to this vector.
+ bit_width = (std::max)(bit_width, keys->ElemWidth(buf_.size(), 0));
+ prefix_elems += 2;
+ }
+ Type vector_type = FBT_KEY;
+ // Check bit widths and types for all elements.
+ for (size_t i = start; i < stack_.size(); i += step) {
+ auto elem_width =
+ stack_[i].ElemWidth(buf_.size(), i - start + prefix_elems);
+ bit_width = (std::max)(bit_width, elem_width);
+ if (typed) {
+ if (i == start) {
+ vector_type = stack_[i].type_;
+ } else {
+ // If you get this assert, you are writing a typed vector with
+ // elements that are not all the same type.
+ FLATBUFFERS_ASSERT(vector_type == stack_[i].type_);
+ }
+ }
+ }
+ // If you get this assert, your fixed types are not one of:
+ // Int / UInt / Float / Key.
+ FLATBUFFERS_ASSERT(!fixed || IsTypedVectorElementType(vector_type));
+ auto byte_width = Align(bit_width);
+ // Write vector. First the keys width/offset if available, and size.
+ if (keys) {
+ WriteOffset(keys->u_, byte_width);
+ Write<uint64_t>(1ULL << keys->min_bit_width_, byte_width);
+ }
+ if (!fixed) Write<uint64_t>(vec_len, byte_width);
+ // Then the actual data.
+ auto vloc = buf_.size();
+ for (size_t i = start; i < stack_.size(); i += step) {
+ WriteAny(stack_[i], byte_width);
+ }
+ // Then the types.
+ if (!typed) {
+ for (size_t i = start; i < stack_.size(); i += step) {
+ buf_.push_back(stack_[i].StoredPackedType(bit_width));
+ }
+ }
+ return Value(static_cast<uint64_t>(vloc),
+ keys ? FBT_MAP
+ : (typed ? ToTypedVector(vector_type, fixed ? vec_len : 0)
+ : FBT_VECTOR),
+ bit_width);
+ }
+
+ // You shouldn't really be copying instances of this class.
+ Builder(const Builder &);
+ Builder &operator=(const Builder &);
+
+ std::vector<uint8_t> buf_;
+ std::vector<Value> stack_;
+
+ bool finished_;
+ bool has_duplicate_keys_;
+
+ BuilderFlag flags_;
+
+ BitWidth force_min_bit_width_;
+
+ struct KeyOffsetCompare {
+ explicit KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
+ bool operator()(size_t a, size_t b) const {
+ auto stra =
+ reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + a);
+ auto strb =
+ reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + b);
+ return strcmp(stra, strb) < 0;
+ }
+ const std::vector<uint8_t> *buf_;
+ };
+
+ typedef std::pair<size_t, size_t> StringOffset;
+ struct StringOffsetCompare {
+ explicit StringOffsetCompare(const std::vector<uint8_t> &buf)
+ : buf_(&buf) {}
+ bool operator()(const StringOffset &a, const StringOffset &b) const {
+ auto stra = reinterpret_cast<const char *>(
+ flatbuffers::vector_data(*buf_) + a.first);
+ auto strb = reinterpret_cast<const char *>(
+ flatbuffers::vector_data(*buf_) + b.first);
+ return strncmp(stra, strb, (std::min)(a.second, b.second) + 1) < 0;
+ }
+ const std::vector<uint8_t> *buf_;
+ };
+
+ typedef std::set<size_t, KeyOffsetCompare> KeyOffsetMap;
+ typedef std::set<StringOffset, StringOffsetCompare> StringOffsetMap;
+
+ KeyOffsetMap key_pool;
+ StringOffsetMap string_pool;
+};
+
+} // namespace flexbuffers
+
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#endif
+
+#endif // FLATBUFFERS_FLEXBUFFERS_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/hash.h b/contrib/libs/flatbuffers/include/flatbuffers/hash.h
new file mode 100644
index 0000000000..52cc628cdf
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/hash.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2015 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.
+ */
+
+#ifndef FLATBUFFERS_HASH_H_
+#define FLATBUFFERS_HASH_H_
+
+#include <cstdint>
+#include <cstring>
+
+#include "flatbuffers.h"
+
+namespace flatbuffers {
+
+template<typename T> struct FnvTraits {
+ static const T kFnvPrime;
+ static const T kOffsetBasis;
+};
+
+template<> struct FnvTraits<uint32_t> {
+ static const uint32_t kFnvPrime = 0x01000193;
+ static const uint32_t kOffsetBasis = 0x811C9DC5;
+};
+
+template<> struct FnvTraits<uint64_t> {
+ static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
+ static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
+};
+
+template<typename T> T HashFnv1(const char *input) {
+ T hash = FnvTraits<T>::kOffsetBasis;
+ for (const char *c = input; *c; ++c) {
+ hash *= FnvTraits<T>::kFnvPrime;
+ hash ^= static_cast<unsigned char>(*c);
+ }
+ return hash;
+}
+
+template<typename T> T HashFnv1a(const char *input) {
+ T hash = FnvTraits<T>::kOffsetBasis;
+ for (const char *c = input; *c; ++c) {
+ hash ^= static_cast<unsigned char>(*c);
+ hash *= FnvTraits<T>::kFnvPrime;
+ }
+ return hash;
+}
+
+template<> inline uint16_t HashFnv1<uint16_t>(const char *input) {
+ uint32_t hash = HashFnv1<uint32_t>(input);
+ return (hash >> 16) ^ (hash & 0xffff);
+}
+
+template<> inline uint16_t HashFnv1a<uint16_t>(const char *input) {
+ uint32_t hash = HashFnv1a<uint32_t>(input);
+ return (hash >> 16) ^ (hash & 0xffff);
+}
+
+template<typename T> struct NamedHashFunction {
+ const char *name;
+
+ typedef T (*HashFunction)(const char *);
+ HashFunction function;
+};
+
+const NamedHashFunction<uint16_t> kHashFunctions16[] = {
+ { "fnv1_16", HashFnv1<uint16_t> },
+ { "fnv1a_16", HashFnv1a<uint16_t> },
+};
+
+const NamedHashFunction<uint32_t> kHashFunctions32[] = {
+ { "fnv1_32", HashFnv1<uint32_t> },
+ { "fnv1a_32", HashFnv1a<uint32_t> },
+};
+
+const NamedHashFunction<uint64_t> kHashFunctions64[] = {
+ { "fnv1_64", HashFnv1<uint64_t> },
+ { "fnv1a_64", HashFnv1a<uint64_t> },
+};
+
+inline NamedHashFunction<uint16_t>::HashFunction FindHashFunction16(
+ const char *name) {
+ std::size_t size = sizeof(kHashFunctions16) / sizeof(kHashFunctions16[0]);
+ for (std::size_t i = 0; i < size; ++i) {
+ if (std::strcmp(name, kHashFunctions16[i].name) == 0) {
+ return kHashFunctions16[i].function;
+ }
+ }
+ return nullptr;
+}
+
+inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32(
+ const char *name) {
+ std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]);
+ for (std::size_t i = 0; i < size; ++i) {
+ if (std::strcmp(name, kHashFunctions32[i].name) == 0) {
+ return kHashFunctions32[i].function;
+ }
+ }
+ return nullptr;
+}
+
+inline NamedHashFunction<uint64_t>::HashFunction FindHashFunction64(
+ const char *name) {
+ std::size_t size = sizeof(kHashFunctions64) / sizeof(kHashFunctions64[0]);
+ for (std::size_t i = 0; i < size; ++i) {
+ if (std::strcmp(name, kHashFunctions64[i].name) == 0) {
+ return kHashFunctions64[i].function;
+ }
+ }
+ return nullptr;
+}
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_HASH_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/idl.h b/contrib/libs/flatbuffers/include/flatbuffers/idl.h
new file mode 100644
index 0000000000..a82ff8a694
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/idl.h
@@ -0,0 +1,1208 @@
+/*
+ * 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.
+ */
+
+#ifndef FLATBUFFERS_IDL_H_
+#define FLATBUFFERS_IDL_H_
+
+#include <map>
+#include <memory>
+#include <stack>
+
+#include "base.h"
+#include "flatbuffers.h"
+#include "flexbuffers.h"
+#include "hash.h"
+#include "reflection.h"
+
+#if !defined(FLATBUFFERS_CPP98_STL)
+# include <functional>
+#endif // !defined(FLATBUFFERS_CPP98_STL)
+
+// This file defines the data types representing a parsed IDL (Interface
+// Definition Language) / schema file.
+
+// Limits maximum depth of nested objects.
+// Prevents stack overflow while parse scheme, or json, or flexbuffer.
+#if !defined(FLATBUFFERS_MAX_PARSING_DEPTH)
+# define FLATBUFFERS_MAX_PARSING_DEPTH 64
+#endif
+
+namespace flatbuffers {
+
+// The order of these matters for Is*() functions below.
+// Additionally, Parser::ParseType assumes bool..string is a contiguous range
+// of type tokens.
+// clang-format off
+#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
+ TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
+ TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) /* begin scalar/int */ \
+ TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool) \
+ TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8) \
+ TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
+ TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16) \
+ TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16) \
+ TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32) \
+ TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32) \
+ TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64) \
+ TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64) /* end int */ \
+ TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32) /* begin float */ \
+ TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double) /* end float/scalar */
+#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
+ TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>) \
+ TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>) \
+ TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>) \
+ TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>)
+#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
+ TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>)
+// The fields are:
+// - enum
+// - FlatBuffers schema type.
+// - C++ type.
+// - Java type.
+// - Go type.
+// - C# / .Net type.
+// - Python type.
+// - Rust type.
+// - Kotlin type.
+
+// using these macros, we can now write code dealing with types just once, e.g.
+
+/*
+switch (type) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
+ RTYPE, KTYPE) \
+ case BASE_TYPE_ ## ENUM: \
+ // do something specific to CTYPE here
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+}
+*/
+
+// If not all FLATBUFFERS_GEN_() arguments are necessary for implementation
+// of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed).
+// In the above example, only CTYPE is used to generate the code, it can be rewritten:
+
+/*
+switch (type) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_ ## ENUM: \
+ // do something specific to CTYPE here
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+}
+*/
+
+#define FLATBUFFERS_GEN_TYPES(TD) \
+ FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
+ FLATBUFFERS_GEN_TYPES_POINTER(TD) \
+ FLATBUFFERS_GEN_TYPE_ARRAY(TD)
+
+// Create an enum for all the types above.
+#ifdef __GNUC__
+__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
+#endif
+enum BaseType {
+ #define FLATBUFFERS_TD(ENUM, ...) \
+ BASE_TYPE_ ## ENUM,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+};
+
+#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
+ "define largest_scalar_t as " #CTYPE);
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+#undef FLATBUFFERS_TD
+
+inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
+ t <= BASE_TYPE_DOUBLE; }
+inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
+ t <= BASE_TYPE_ULONG; }
+inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
+ t == BASE_TYPE_DOUBLE; }
+inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
+ t == BASE_TYPE_ULONG; }
+inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
+inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
+ t <= BASE_TYPE_UCHAR; }
+
+inline bool IsUnsigned(BaseType t) {
+ return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) ||
+ (t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT) ||
+ (t == BASE_TYPE_ULONG);
+}
+
+// clang-format on
+
+extern const char *const kTypeNames[];
+extern const char kTypeSizes[];
+
+inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
+
+struct StructDef;
+struct EnumDef;
+class Parser;
+
+// Represents any type in the IDL, which is a combination of the BaseType
+// and additional information for vectors/structs_.
+struct Type {
+ explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
+ EnumDef *_ed = nullptr, uint16_t _fixed_length = 0)
+ : base_type(_base_type),
+ element(BASE_TYPE_NONE),
+ struct_def(_sd),
+ enum_def(_ed),
+ fixed_length(_fixed_length) {}
+
+ bool operator==(const Type &o) {
+ return base_type == o.base_type && element == o.element &&
+ struct_def == o.struct_def && enum_def == o.enum_def;
+ }
+
+ Type VectorType() const {
+ return Type(element, struct_def, enum_def, fixed_length);
+ }
+
+ Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
+
+ bool Deserialize(const Parser &parser, const reflection::Type *type);
+
+ BaseType base_type;
+ BaseType element; // only set if t == BASE_TYPE_VECTOR
+ StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
+ EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
+ // or for an integral type derived from an enum.
+ uint16_t fixed_length; // only set if t == BASE_TYPE_ARRAY
+};
+
+// Represents a parsed scalar value, it's type, and field offset.
+struct Value {
+ Value()
+ : constant("0"),
+ offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
+ Type type;
+ std::string constant;
+ voffset_t offset;
+};
+
+// Helper class that retains the original order of a set of identifiers and
+// also provides quick lookup.
+template<typename T> class SymbolTable {
+ public:
+ ~SymbolTable() {
+ for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
+ }
+
+ bool Add(const std::string &name, T *e) {
+ vector_emplace_back(&vec, e);
+ auto it = dict.find(name);
+ if (it != dict.end()) return true;
+ dict[name] = e;
+ return false;
+ }
+
+ void Move(const std::string &oldname, const std::string &newname) {
+ auto it = dict.find(oldname);
+ if (it != dict.end()) {
+ auto obj = it->second;
+ dict.erase(it);
+ dict[newname] = obj;
+ } else {
+ FLATBUFFERS_ASSERT(false);
+ }
+ }
+
+ T *Lookup(const std::string &name) const {
+ auto it = dict.find(name);
+ return it == dict.end() ? nullptr : it->second;
+ }
+
+ public:
+ std::map<std::string, T *> dict; // quick lookup
+ std::vector<T *> vec; // Used to iterate in order of insertion
+};
+
+// A name space, as set in the schema.
+struct Namespace {
+ Namespace() : from_table(0) {}
+
+ // Given a (potentially unqualified) name, return the "fully qualified" name
+ // which has a full namespaced descriptor.
+ // With max_components you can request less than the number of components
+ // the current namespace has.
+ std::string GetFullyQualifiedName(const std::string &name,
+ size_t max_components = 1000) const;
+
+ std::vector<std::string> components;
+ size_t from_table; // Part of the namespace corresponds to a message/table.
+};
+
+inline bool operator<(const Namespace &a, const Namespace &b) {
+ size_t min_size = std::min(a.components.size(), b.components.size());
+ for (size_t i = 0; i < min_size; ++i) {
+ if (a.components[i] != b.components[i])
+ return a.components[i] < b.components[i];
+ }
+ return a.components.size() < b.components.size();
+}
+
+// Base class for all definition types (fields, structs_, enums_).
+struct Definition {
+ Definition()
+ : generated(false),
+ defined_namespace(nullptr),
+ serialized_location(0),
+ index(-1),
+ refcount(1) {}
+
+ flatbuffers::Offset<
+ flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
+ SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
+
+ bool DeserializeAttributes(Parser &parser,
+ const Vector<Offset<reflection::KeyValue>> *attrs);
+
+ std::string name;
+ std::string file;
+ std::vector<std::string> doc_comment;
+ SymbolTable<Value> attributes;
+ bool generated; // did we already output code for this definition?
+ Namespace *defined_namespace; // Where it was defined.
+
+ // For use with Serialize()
+ uoffset_t serialized_location;
+ int index; // Inside the vector it is stored.
+ int refcount;
+};
+
+struct FieldDef : public Definition {
+ FieldDef()
+ : deprecated(false),
+ key(false),
+ shared(false),
+ native_inline(false),
+ flexbuffer(false),
+ presence(kDefault),
+ nested_flatbuffer(NULL),
+ padding(0) {}
+
+ Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
+ const Parser &parser) const;
+
+ bool Deserialize(Parser &parser, const reflection::Field *field);
+
+ bool IsScalarOptional() const {
+ return IsScalar(value.type.base_type) && IsOptional();
+ }
+ bool IsOptional() const {
+ return presence == kOptional;
+ }
+ bool IsRequired() const {
+ return presence == kRequired;
+ }
+ bool IsDefault() const {
+ return presence == kDefault;
+ }
+
+ Value value;
+ bool deprecated; // Field is allowed to be present in old data, but can't be.
+ // written in new data nor accessed in new code.
+ bool key; // Field functions as a key for creating sorted vectors.
+ bool shared; // Field will be using string pooling (i.e. CreateSharedString)
+ // as default serialization behavior if field is a string.
+ bool native_inline; // Field will be defined inline (instead of as a pointer)
+ // for native tables if field is a struct.
+ bool flexbuffer; // This field contains FlexBuffer data.
+
+ enum Presence {
+ // Field must always be present.
+ kRequired,
+ // Non-presence should be signalled to and controlled by users.
+ kOptional,
+ // Non-presence is hidden from users.
+ // Implementations may omit writing default values.
+ kDefault,
+ };
+ Presence static MakeFieldPresence(bool optional, bool required) {
+ FLATBUFFERS_ASSERT(!(required && optional));
+ // clang-format off
+ return required ? FieldDef::kRequired
+ : optional ? FieldDef::kOptional
+ : FieldDef::kDefault;
+ // clang-format on
+ }
+ Presence presence;
+
+ StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
+ size_t padding; // Bytes to always pad after this field.
+};
+
+struct StructDef : public Definition {
+ StructDef()
+ : fixed(false),
+ predecl(true),
+ sortbysize(true),
+ has_key(false),
+ minalign(1),
+ bytesize(0) {}
+
+ void PadLastField(size_t min_align) {
+ auto padding = PaddingBytes(bytesize, min_align);
+ bytesize += padding;
+ if (fields.vec.size()) fields.vec.back()->padding = padding;
+ }
+
+ Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const;
+
+ bool Deserialize(Parser &parser, const reflection::Object *object);
+
+ SymbolTable<FieldDef> fields;
+
+ bool fixed; // If it's struct, not a table.
+ bool predecl; // If it's used before it was defined.
+ bool sortbysize; // Whether fields come in the declaration or size order.
+ bool has_key; // It has a key field.
+ size_t minalign; // What the whole object needs to be aligned to.
+ size_t bytesize; // Size if fixed.
+
+ flatbuffers::unique_ptr<std::string> original_location;
+};
+
+struct EnumDef;
+struct EnumValBuilder;
+
+struct EnumVal {
+ Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const;
+
+ bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
+
+ uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
+ int64_t GetAsInt64() const { return value; }
+ bool IsZero() const { return 0 == value; }
+ bool IsNonZero() const { return !IsZero(); }
+
+ std::string name;
+ std::vector<std::string> doc_comment;
+ Type union_type;
+
+ private:
+ friend EnumDef;
+ friend EnumValBuilder;
+ friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);
+
+ EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
+ EnumVal() : value(0) {}
+
+ int64_t value;
+};
+
+struct EnumDef : public Definition {
+ EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
+
+ Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const;
+
+ bool Deserialize(Parser &parser, const reflection::Enum *values);
+
+ template<typename T> void ChangeEnumValue(EnumVal *ev, T new_val);
+ void SortByValue();
+ void RemoveDuplicates();
+
+ std::string AllFlags() const;
+ const EnumVal *MinValue() const;
+ const EnumVal *MaxValue() const;
+ // Returns the number of integer steps from v1 to v2.
+ uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
+ // Returns the number of integer steps from Min to Max.
+ uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }
+
+ EnumVal *ReverseLookup(int64_t enum_idx,
+ bool skip_union_default = false) const;
+ EnumVal *FindByValue(const std::string &constant) const;
+
+ std::string ToString(const EnumVal &ev) const {
+ return IsUInt64() ? NumToString(ev.GetAsUInt64())
+ : NumToString(ev.GetAsInt64());
+ }
+
+ size_t size() const { return vals.vec.size(); }
+
+ const std::vector<EnumVal *> &Vals() const { return vals.vec; }
+
+ const EnumVal *Lookup(const std::string &enum_name) const {
+ return vals.Lookup(enum_name);
+ }
+
+ bool is_union;
+ // Type is a union which uses type aliases where at least one type is
+ // available under two different names.
+ bool uses_multiple_type_instances;
+ Type underlying_type;
+
+ private:
+ bool IsUInt64() const {
+ return (BASE_TYPE_ULONG == underlying_type.base_type);
+ }
+
+ friend EnumValBuilder;
+ SymbolTable<EnumVal> vals;
+};
+
+inline bool IsString(const Type &type) {
+ return type.base_type == BASE_TYPE_STRING;
+}
+
+inline bool IsStruct(const Type &type) {
+ return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
+}
+
+inline bool IsUnion(const Type &type) {
+ return type.enum_def != nullptr && type.enum_def->is_union;
+}
+
+inline bool IsVector(const Type &type) {
+ return type.base_type == BASE_TYPE_VECTOR;
+}
+
+inline bool IsArray(const Type &type) {
+ return type.base_type == BASE_TYPE_ARRAY;
+}
+
+inline bool IsSeries(const Type &type) {
+ return IsVector(type) || IsArray(type);
+}
+
+inline bool IsEnum(const Type &type) {
+ return type.enum_def != nullptr && IsInteger(type.base_type);
+}
+
+inline size_t InlineSize(const Type &type) {
+ return IsStruct(type)
+ ? type.struct_def->bytesize
+ : (IsArray(type)
+ ? InlineSize(type.VectorType()) * type.fixed_length
+ : SizeOf(type.base_type));
+}
+
+inline size_t InlineAlignment(const Type &type) {
+ if (IsStruct(type)) {
+ return type.struct_def->minalign;
+ } else if (IsArray(type)) {
+ return IsStruct(type.VectorType()) ? type.struct_def->minalign
+ : SizeOf(type.element);
+ } else {
+ return SizeOf(type.base_type);
+ }
+}
+inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) {
+ return lhs.value == rhs.value;
+}
+inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
+ return !(lhs == rhs);
+}
+
+inline bool EqualByName(const Type &a, const Type &b) {
+ return a.base_type == b.base_type && a.element == b.element &&
+ (a.struct_def == b.struct_def ||
+ a.struct_def->name == b.struct_def->name) &&
+ (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
+}
+
+struct RPCCall : public Definition {
+ Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const;
+
+ bool Deserialize(Parser &parser, const reflection::RPCCall *call);
+
+ StructDef *request, *response;
+};
+
+struct ServiceDef : public Definition {
+ Offset<reflection::Service> Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const;
+ bool Deserialize(Parser &parser, const reflection::Service *service);
+
+ SymbolTable<RPCCall> calls;
+};
+
+// Container of options that may apply to any of the source/text generators.
+struct IDLOptions {
+ bool gen_jvmstatic;
+ // Use flexbuffers instead for binary and text generation
+ bool use_flexbuffers;
+ bool strict_json;
+ bool output_default_scalars_in_json;
+ int indent_step;
+ bool output_enum_identifiers;
+ bool prefixed_enums;
+ bool scoped_enums;
+ bool include_dependence_headers;
+ bool mutable_buffer;
+ bool one_file;
+ bool proto_mode;
+ bool proto_oneof_union;
+ bool generate_all;
+ bool skip_unexpected_fields_in_json;
+ bool generate_name_strings;
+ bool generate_object_based_api;
+ bool gen_compare;
+ std::string cpp_object_api_pointer_type;
+ std::string cpp_object_api_string_type;
+ bool cpp_object_api_string_flexible_constructor;
+ bool cpp_direct_copy;
+ bool gen_nullable;
+ bool java_checkerframework;
+ bool gen_generated;
+ std::string object_prefix;
+ std::string object_suffix;
+ bool union_value_namespacing;
+ bool allow_non_utf8;
+ bool natural_utf8;
+ std::string include_prefix;
+ bool keep_include_path;
+ bool binary_schema_comments;
+ bool binary_schema_builtins;
+ bool binary_schema_gen_embed;
+ std::string go_import;
+ std::string go_namespace;
+ bool protobuf_ascii_alike;
+ bool size_prefixed;
+ std::string root_type;
+ bool force_defaults;
+ bool java_primitive_has_method;
+ bool cs_gen_json_serializer;
+ std::vector<std::string> cpp_includes;
+ std::string cpp_std;
+ bool cpp_static_reflection;
+ std::string proto_namespace_suffix;
+ std::string filename_suffix;
+ std::string filename_extension;
+ bool no_warnings;
+
+ // Possible options for the more general generator below.
+ enum Language {
+ kJava = 1 << 0,
+ kCSharp = 1 << 1,
+ kGo = 1 << 2,
+ kCpp = 1 << 3,
+ kPython = 1 << 5,
+ kPhp = 1 << 6,
+ kJson = 1 << 7,
+ kBinary = 1 << 8,
+ kTs = 1 << 9,
+ kJsonSchema = 1 << 10,
+ kDart = 1 << 11,
+ kLua = 1 << 12,
+ kLobster = 1 << 13,
+ kRust = 1 << 14,
+ kKotlin = 1 << 15,
+ kSwift = 1 << 16,
+ kCppYandexMapsIter = 1 << 17,
+ kMAX
+ };
+
+ Language lang;
+
+ enum MiniReflect { kNone, kTypes, kTypesAndNames };
+
+ MiniReflect mini_reflect;
+
+ // If set, require all fields in a table to be explicitly numbered.
+ bool require_explicit_ids;
+
+ // The corresponding language bit will be set if a language is included
+ // for code generation.
+ unsigned long lang_to_generate;
+
+ // If set (default behavior), empty string fields will be set to nullptr to
+ // make the flatbuffer more compact.
+ bool set_empty_strings_to_null;
+
+ // If set (default behavior), empty vector fields will be set to nullptr to
+ // make the flatbuffer more compact.
+ bool set_empty_vectors_to_null;
+
+ IDLOptions()
+ : gen_jvmstatic(false),
+ use_flexbuffers(false),
+ strict_json(false),
+ output_default_scalars_in_json(false),
+ indent_step(2),
+ output_enum_identifiers(true),
+ prefixed_enums(true),
+ scoped_enums(false),
+ include_dependence_headers(true),
+ mutable_buffer(false),
+ one_file(false),
+ proto_mode(false),
+ proto_oneof_union(false),
+ generate_all(false),
+ skip_unexpected_fields_in_json(false),
+ generate_name_strings(false),
+ generate_object_based_api(false),
+ gen_compare(false),
+ cpp_object_api_pointer_type("std::unique_ptr"),
+ cpp_object_api_string_flexible_constructor(false),
+ cpp_direct_copy(true),
+ gen_nullable(false),
+ java_checkerframework(false),
+ gen_generated(false),
+ object_suffix("T"),
+ union_value_namespacing(true),
+ allow_non_utf8(false),
+ natural_utf8(false),
+ keep_include_path(false),
+ binary_schema_comments(false),
+ binary_schema_builtins(false),
+ binary_schema_gen_embed(false),
+ protobuf_ascii_alike(false),
+ size_prefixed(false),
+ force_defaults(false),
+ java_primitive_has_method(false),
+ cs_gen_json_serializer(false),
+ cpp_static_reflection(false),
+ filename_suffix("_generated"),
+ filename_extension(),
+ no_warnings(false),
+ lang(IDLOptions::kJava),
+ mini_reflect(IDLOptions::kNone),
+ require_explicit_ids(false),
+ lang_to_generate(0),
+ set_empty_strings_to_null(true),
+ set_empty_vectors_to_null(true) {}
+};
+
+// This encapsulates where the parser is in the current source file.
+struct ParserState {
+ ParserState()
+ : cursor_(nullptr),
+ line_start_(nullptr),
+ line_(0),
+ token_(-1),
+ attr_is_trivial_ascii_string_(true) {}
+
+ protected:
+ void ResetState(const char *source) {
+ cursor_ = source;
+ line_ = 0;
+ MarkNewLine();
+ }
+
+ void MarkNewLine() {
+ line_start_ = cursor_;
+ line_ += 1;
+ }
+
+ int64_t CursorPosition() const {
+ FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
+ return static_cast<int64_t>(cursor_ - line_start_);
+ }
+
+ const char *cursor_;
+ const char *line_start_;
+ int line_; // the current line being parsed
+ int token_;
+
+ // Flag: text in attribute_ is true ASCII string without escape
+ // sequences. Only printable ASCII (without [\t\r\n]).
+ // Used for number-in-string (and base64 string in future).
+ bool attr_is_trivial_ascii_string_;
+ std::string attribute_;
+ std::vector<std::string> doc_comment_;
+};
+
+// A way to make error propagation less error prone by requiring values to be
+// checked.
+// Once you create a value of this type you must either:
+// - Call Check() on it.
+// - Copy or assign it to another value.
+// Failure to do so leads to an assert.
+// This guarantees that this as return value cannot be ignored.
+class CheckedError {
+ public:
+ explicit CheckedError(bool error)
+ : is_error_(error), has_been_checked_(false) {}
+
+ CheckedError &operator=(const CheckedError &other) {
+ is_error_ = other.is_error_;
+ has_been_checked_ = false;
+ other.has_been_checked_ = true;
+ return *this;
+ }
+
+ CheckedError(const CheckedError &other) {
+ *this = other; // Use assignment operator.
+ }
+
+ ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
+
+ bool Check() {
+ has_been_checked_ = true;
+ return is_error_;
+ }
+
+ private:
+ bool is_error_;
+ mutable bool has_been_checked_;
+};
+
+// Additionally, in GCC we can get these errors statically, for additional
+// assurance:
+// clang-format off
+#ifdef __GNUC__
+#define FLATBUFFERS_CHECKED_ERROR CheckedError \
+ __attribute__((warn_unused_result))
+#else
+#define FLATBUFFERS_CHECKED_ERROR CheckedError
+#endif
+// clang-format on
+
+class Parser : public ParserState {
+ public:
+ explicit Parser(const IDLOptions &options = IDLOptions())
+ : current_namespace_(nullptr),
+ empty_namespace_(nullptr),
+ flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL),
+ root_struct_def_(nullptr),
+ opts(options),
+ uses_flexbuffers_(false),
+ advanced_features_(0),
+ source_(nullptr),
+ anonymous_counter_(0),
+ parse_depth_counter_(0) {
+ if (opts.force_defaults) { builder_.ForceDefaults(true); }
+ // Start out with the empty namespace being current.
+ empty_namespace_ = new Namespace();
+ namespaces_.push_back(empty_namespace_);
+ current_namespace_ = empty_namespace_;
+ known_attributes_["deprecated"] = true;
+ known_attributes_["required"] = true;
+ known_attributes_["key"] = true;
+ known_attributes_["shared"] = true;
+ known_attributes_["hash"] = true;
+ known_attributes_["id"] = true;
+ known_attributes_["force_align"] = true;
+ known_attributes_["bit_flags"] = true;
+ known_attributes_["original_order"] = true;
+ known_attributes_["nested_flatbuffer"] = true;
+ known_attributes_["csharp_partial"] = true;
+ known_attributes_["streaming"] = true;
+ known_attributes_["idempotent"] = true;
+ known_attributes_["cpp_type"] = true;
+ known_attributes_["cpp_ptr_type"] = true;
+ known_attributes_["cpp_ptr_type_get"] = true;
+ known_attributes_["cpp_str_type"] = true;
+ known_attributes_["cpp_str_flex_ctor"] = true;
+ known_attributes_["native_inline"] = true;
+ known_attributes_["native_custom_alloc"] = true;
+ known_attributes_["native_type"] = true;
+ known_attributes_["native_type_pack_name"] = true;
+ known_attributes_["native_default"] = true;
+ known_attributes_["flexbuffer"] = true;
+ known_attributes_["private"] = true;
+ }
+
+ ~Parser() {
+ for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
+ delete *it;
+ }
+ }
+
+ // Parse the string containing either schema or JSON data, which will
+ // populate the SymbolTable's or the FlatBufferBuilder above.
+ // include_paths is used to resolve any include statements, and typically
+ // should at least include the project path (where you loaded source_ from).
+ // include_paths must be nullptr terminated if specified.
+ // If include_paths is nullptr, it will attempt to load from the current
+ // directory.
+ // If the source was loaded from a file and isn't an include file,
+ // supply its name in source_filename.
+ // All paths specified in this call must be in posix format, if you accept
+ // paths from user input, please call PosixPath on them first.
+ bool Parse(const char *_source, const char **include_paths = nullptr,
+ const char *source_filename = nullptr);
+
+ bool ParseJson(const char *json, const char *json_filename = nullptr);
+
+ // Set the root type. May override the one set in the schema.
+ bool SetRootType(const char *name);
+
+ // Mark all definitions as already having code generated.
+ void MarkGenerated();
+
+ // Get the files recursively included by the given file. The returned
+ // container will have at least the given file.
+ std::set<std::string> GetIncludedFilesRecursive(
+ const std::string &file_name) const;
+
+ // Fills builder_ with a binary version of the schema parsed.
+ // See reflection/reflection.fbs
+ void Serialize();
+
+ // Deserialize a schema buffer
+ bool Deserialize(const uint8_t *buf, const size_t size);
+
+ // Fills internal structure as if the schema passed had been loaded by parsing
+ // with Parse except that included filenames will not be populated.
+ bool Deserialize(const reflection::Schema *schema);
+
+ Type *DeserializeType(const reflection::Type *type);
+
+ // Checks that the schema represented by this parser is a safe evolution
+ // of the schema provided. Returns non-empty error on any problems.
+ std::string ConformTo(const Parser &base);
+
+ // Similar to Parse(), but now only accepts JSON to be parsed into a
+ // FlexBuffer.
+ bool ParseFlexBuffer(const char *source, const char *source_filename,
+ flexbuffers::Builder *builder);
+
+ StructDef *LookupStruct(const std::string &id) const;
+ StructDef *LookupStructThruParentNamespaces(const std::string &id) const;
+
+ std::string UnqualifiedName(const std::string &fullQualifiedName);
+
+ FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
+
+ // @brief Verify that any of 'opts.lang_to_generate' supports Optional scalars
+ // in a schema.
+ // @param opts Options used to parce a schema and generate code.
+ static bool SupportsOptionalScalars(const flatbuffers::IDLOptions &opts);
+
+ private:
+ class ParseDepthGuard;
+
+ void Message(const std::string &msg);
+ void Warning(const std::string &msg);
+ FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
+ FLATBUFFERS_CHECKED_ERROR Next();
+ FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
+ bool Is(int t) const;
+ bool IsIdent(const char *id) const;
+ FLATBUFFERS_CHECKED_ERROR Expect(int t);
+ std::string TokenToStringId(int t) const;
+ EnumDef *LookupEnum(const std::string &id);
+ FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
+ std::string *last);
+ FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type);
+ FLATBUFFERS_CHECKED_ERROR ParseType(Type &type);
+ FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def,
+ const std::string &name, const Type &type,
+ FieldDef **dest);
+ FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
+ FLATBUFFERS_CHECKED_ERROR ParseString(Value &val, bool use_string_pooling);
+ FLATBUFFERS_CHECKED_ERROR ParseComma();
+ FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
+ size_t parent_fieldn,
+ const StructDef *parent_struct_def,
+ uoffset_t count,
+ bool inside_vector = false);
+ template<typename F>
+ FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
+ const StructDef *struct_def,
+ F body);
+ FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
+ std::string *value, uoffset_t *ovalue);
+ void SerializeStruct(const StructDef &struct_def, const Value &val);
+ void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
+ const Value &val);
+ template<typename F>
+ FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
+ FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
+ FieldDef *field, size_t fieldn);
+ FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
+ FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(
+ Value &val, FieldDef *field, size_t fieldn,
+ const StructDef *parent_struct_def);
+ FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
+ FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken,
+ bool check, Value &e, BaseType req,
+ bool *destmatch);
+ FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field);
+ FLATBUFFERS_CHECKED_ERROR TokenError();
+ FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e,
+ bool check_now);
+ FLATBUFFERS_CHECKED_ERROR ParseFunction(const std::string *name, Value &e);
+ FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type,
+ std::string *result);
+ StructDef *LookupCreateStruct(const std::string &name,
+ bool create_if_new = true,
+ bool definition = false);
+ FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest);
+ FLATBUFFERS_CHECKED_ERROR ParseNamespace();
+ FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
+ StructDef **dest);
+ FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union,
+ EnumDef **dest);
+ FLATBUFFERS_CHECKED_ERROR ParseDecl();
+ FLATBUFFERS_CHECKED_ERROR ParseService();
+ FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
+ bool isextend, bool inside_oneof);
+ FLATBUFFERS_CHECKED_ERROR ParseProtoOption();
+ FLATBUFFERS_CHECKED_ERROR ParseProtoKey();
+ FLATBUFFERS_CHECKED_ERROR ParseProtoDecl();
+ FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
+ FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
+ FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
+ FLATBUFFERS_CHECKED_ERROR ParseFlexBufferNumericConstant(
+ flexbuffers::Builder *builder);
+ FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
+ FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
+ const char *source_filename);
+ FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
+ const char **include_paths,
+ const char *source_filename);
+ FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
+ const char **include_paths,
+ const char *source_filename,
+ const char *include_filename);
+ FLATBUFFERS_CHECKED_ERROR DoParseJson();
+ FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef *> &fields,
+ StructDef *struct_def,
+ const char *suffix, BaseType baseType);
+ FLATBUFFERS_CHECKED_ERROR ParseAlignAttribute(
+ const std::string &align_constant, size_t min_align, size_t *align);
+
+ bool SupportsAdvancedUnionFeatures() const;
+ bool SupportsAdvancedArrayFeatures() const;
+ bool SupportsOptionalScalars() const;
+ bool SupportsDefaultVectorsAndStrings() const;
+ Namespace *UniqueNamespace(Namespace *ns);
+
+ FLATBUFFERS_CHECKED_ERROR RecurseError();
+ template<typename F> CheckedError Recurse(F f);
+
+ public:
+ SymbolTable<Type> types_;
+ SymbolTable<StructDef> structs_;
+ SymbolTable<EnumDef> enums_;
+ SymbolTable<ServiceDef> services_;
+ std::vector<Namespace *> namespaces_;
+ Namespace *current_namespace_;
+ Namespace *empty_namespace_;
+ std::string error_; // User readable error_ if Parse() == false
+
+ FlatBufferBuilder builder_; // any data contained in the file
+ flexbuffers::Builder flex_builder_;
+ flexbuffers::Reference flex_root_;
+ StructDef *root_struct_def_;
+ std::string file_identifier_;
+ std::string file_extension_;
+
+ std::map<uint64_t, std::string> included_files_;
+ std::map<std::string, std::set<std::string>> files_included_per_file_;
+ std::vector<std::string> native_included_files_;
+
+ std::map<std::string, bool> known_attributes_;
+
+ IDLOptions opts;
+ bool uses_flexbuffers_;
+
+ uint64_t advanced_features_;
+
+ private:
+ const char *source_;
+
+ std::string file_being_parsed_;
+
+ std::vector<std::pair<Value, FieldDef *>> field_stack_;
+
+ int anonymous_counter_;
+ int parse_depth_counter_; // stack-overflow guard
+};
+
+// Utility functions for multiple generators:
+
+extern std::string MakeCamel(const std::string &in, bool first = true);
+
+extern std::string MakeScreamingCamel(const std::string &in);
+
+// Generate text (JSON) from a given FlatBuffer, and a given Parser
+// object that has been populated with the corresponding schema.
+// If ident_step is 0, no indentation will be generated. Additionally,
+// if it is less than 0, no linefeeds will be generated either.
+// See idl_gen_text.cpp.
+// strict_json adds "quotes" around field names if true.
+// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
+// byte arrays in String values), returns false.
+extern bool GenerateTextFromTable(const Parser &parser, const void *table,
+ const std::string &tablename,
+ std::string *text);
+extern bool GenerateText(const Parser &parser, const void *flatbuffer,
+ std::string *text);
+extern bool GenerateTextFile(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Json schema to string
+// See idl_gen_json_schema.cpp.
+extern bool GenerateJsonSchema(const Parser &parser, std::string *json);
+
+// Generate binary files from a given FlatBuffer, and a given Parser
+// object that has been populated with the corresponding schema.
+// See code_generators.cpp.
+extern bool GenerateBinary(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a C++ header from the definitions in the Parser object.
+// See idl_gen_cpp.
+extern bool GenerateCPP(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate C# files from the definitions in the Parser object.
+// See idl_gen_csharp.cpp.
+extern bool GenerateCSharp(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+extern bool GenerateDart(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Java files from the definitions in the Parser object.
+// See idl_gen_java.cpp.
+extern bool GenerateJava(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate JavaScript or TypeScript code from the definitions in the Parser
+// object. See idl_gen_js.
+extern bool GenerateTS(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Go files from the definitions in the Parser object.
+// See idl_gen_go.cpp.
+extern bool GenerateGo(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Php code from the definitions in the Parser object.
+// See idl_gen_php.
+extern bool GeneratePhp(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Python files from the definitions in the Parser object.
+// See idl_gen_python.cpp.
+extern bool GeneratePython(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Lobster files from the definitions in the Parser object.
+// See idl_gen_lobster.cpp.
+extern bool GenerateLobster(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Lua files from the definitions in the Parser object.
+// See idl_gen_lua.cpp.
+extern bool GenerateLua(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Rust files from the definitions in the Parser object.
+// See idl_gen_rust.cpp.
+extern bool GenerateRust(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Json schema file
+// See idl_gen_json_schema.cpp.
+extern bool GenerateJsonSchema(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+extern bool GenerateKotlin(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate Swift classes.
+// See idl_gen_swift.cpp
+extern bool GenerateSwift(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a schema file from the internal representation, useful after
+// parsing a .proto schema.
+extern std::string GenerateFBS(const Parser &parser,
+ const std::string &file_name);
+extern bool GenerateFBS(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a C++ header for reading with templated file iterator from
+// the definitions in the Parser object.
+// See idl_gen_cpp_yandex_maps_iter.cpp.
+extern std::string GenerateCPPYandexMapsIter(const Parser &parser,
+ const std::string &include_guard_ident);
+extern bool GenerateCPPYandexMapsIter(const Parser &parser,
+ const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for the generated TypeScript code.
+// See idl_gen_ts.cpp.
+extern std::string TSMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for the generated C++ header.
+// See idl_gen_cpp.cpp.
+extern std::string CPPMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for the generated Dart code
+// see idl_gen_dart.cpp
+extern std::string DartMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for the generated Rust code.
+// See idl_gen_rust.cpp.
+extern std::string RustMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for generated Java or C# files.
+// See code_generators.cpp.
+extern std::string JavaCSharpMakeRule(const Parser &parser,
+ const std::string &path,
+ const std::string &file_name);
+
+// Generate a make rule for the generated text (JSON) files.
+// See idl_gen_text.cpp.
+extern std::string TextMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_names);
+
+// Generate a make rule for the generated binary files.
+// See code_generators.cpp.
+extern std::string BinaryMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate GRPC Cpp interfaces.
+// See idl_gen_grpc.cpp.
+bool GenerateCppGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate GRPC Go interfaces.
+// See idl_gen_grpc.cpp.
+bool GenerateGoGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate GRPC Java classes.
+// See idl_gen_grpc.cpp
+bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate GRPC Python interfaces.
+// See idl_gen_grpc.cpp.
+bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+// Generate GRPC Swift interfaces.
+// See idl_gen_grpc.cpp.
+extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+
+extern bool GenerateTSGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name);
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_IDL_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/reflection.h b/contrib/libs/flatbuffers/include/flatbuffers/reflection.h
new file mode 100644
index 0000000000..d268a3ffea
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/reflection.h
@@ -0,0 +1,502 @@
+/*
+ * Copyright 2015 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.
+ */
+
+#ifndef FLATBUFFERS_REFLECTION_H_
+#define FLATBUFFERS_REFLECTION_H_
+
+// This is somewhat of a circular dependency because flatc (and thus this
+// file) is needed to generate this header in the first place.
+// Should normally not be a problem since it can be generated by the
+// previous version of flatc whenever this code needs to change.
+// See reflection/generate_code.sh
+#include "reflection_generated.h"
+
+// Helper functionality for reflection.
+
+namespace flatbuffers {
+
+// ------------------------- GETTERS -------------------------
+
+inline bool IsScalar(reflection::BaseType t) {
+ return t >= reflection::UType && t <= reflection::Double;
+}
+inline bool IsInteger(reflection::BaseType t) {
+ return t >= reflection::UType && t <= reflection::ULong;
+}
+inline bool IsFloat(reflection::BaseType t) {
+ return t == reflection::Float || t == reflection::Double;
+}
+inline bool IsLong(reflection::BaseType t) {
+ return t == reflection::Long || t == reflection::ULong;
+}
+
+// Size of a basic type, don't use with structs.
+inline size_t GetTypeSize(reflection::BaseType base_type) {
+ // This needs to correspond to the BaseType enum.
+ static size_t sizes[] = {
+ 0, // None
+ 1, // UType
+ 1, // Bool
+ 1, // Byte
+ 1, // UByte
+ 2, // Short
+ 2, // UShort
+ 4, // Int
+ 4, // UInt
+ 8, // Long
+ 8, // ULong
+ 4, // Float
+ 8, // Double
+ 4, // String
+ 4, // Vector
+ 4, // Obj
+ 4, // Union
+ 0, // Array. Only used in structs. 0 was chosen to prevent out-of-bounds
+ // errors.
+
+ 0 // MaxBaseType. This must be kept the last entry in this array.
+ };
+ static_assert(sizeof(sizes) / sizeof(size_t) == reflection::MaxBaseType + 1,
+ "Size of sizes[] array does not match the count of BaseType "
+ "enum values.");
+ return sizes[base_type];
+}
+
+// Same as above, but now correctly returns the size of a struct if
+// the field (or vector element) is a struct.
+inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index,
+ const reflection::Schema &schema) {
+ if (base_type == reflection::Obj &&
+ schema.objects()->Get(type_index)->is_struct()) {
+ return schema.objects()->Get(type_index)->bytesize();
+ } else {
+ return GetTypeSize(base_type);
+ }
+}
+
+// Get the root, regardless of what type it is.
+inline Table *GetAnyRoot(uint8_t *flatbuf) {
+ return GetMutableRoot<Table>(flatbuf);
+}
+inline const Table *GetAnyRoot(const uint8_t *flatbuf) {
+ return GetRoot<Table>(flatbuf);
+}
+
+// Get a field's default, if you know it's an integer, and its exact type.
+template<typename T> T GetFieldDefaultI(const reflection::Field &field) {
+ FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
+ return static_cast<T>(field.default_integer());
+}
+
+// Get a field's default, if you know it's floating point and its exact type.
+template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
+ FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
+ return static_cast<T>(field.default_real());
+}
+
+// Get a field, if you know it's an integer, and its exact type.
+template<typename T>
+T GetFieldI(const Table &table, const reflection::Field &field) {
+ FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
+ return table.GetField<T>(field.offset(),
+ static_cast<T>(field.default_integer()));
+}
+
+// Get a field, if you know it's floating point and its exact type.
+template<typename T>
+T GetFieldF(const Table &table, const reflection::Field &field) {
+ FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
+ return table.GetField<T>(field.offset(),
+ static_cast<T>(field.default_real()));
+}
+
+// Get a field, if you know it's a string.
+inline const String *GetFieldS(const Table &table,
+ const reflection::Field &field) {
+ FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::String);
+ return table.GetPointer<const String *>(field.offset());
+}
+
+// Get a field, if you know it's a vector.
+template<typename T>
+Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) {
+ FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Vector &&
+ sizeof(T) == GetTypeSize(field.type()->element()));
+ return table.GetPointer<Vector<T> *>(field.offset());
+}
+
+// Get a field, if you know it's a vector, generically.
+// To actually access elements, use the return value together with
+// field.type()->element() in any of GetAnyVectorElemI below etc.
+inline VectorOfAny *GetFieldAnyV(const Table &table,
+ const reflection::Field &field) {
+ return table.GetPointer<VectorOfAny *>(field.offset());
+}
+
+// Get a field, if you know it's a table.
+inline Table *GetFieldT(const Table &table, const reflection::Field &field) {
+ FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj ||
+ field.type()->base_type() == reflection::Union);
+ return table.GetPointer<Table *>(field.offset());
+}
+
+// Get a field, if you know it's a struct.
+inline const Struct *GetFieldStruct(const Table &table,
+ const reflection::Field &field) {
+ // TODO: This does NOT check if the field is a table or struct, but we'd need
+ // access to the schema to check the is_struct flag.
+ FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
+ return table.GetStruct<const Struct *>(field.offset());
+}
+
+// Get a structure's field, if you know it's a struct.
+inline const Struct *GetFieldStruct(const Struct &structure,
+ const reflection::Field &field) {
+ FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
+ return structure.GetStruct<const Struct *>(field.offset());
+}
+
+// Raw helper functions used below: get any value in memory as a 64bit int, a
+// double or a string.
+// All scalars get static_cast to an int64_t, strings use strtoull, every other
+// data type returns 0.
+int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data);
+// All scalars static cast to double, strings use strtod, every other data
+// type is 0.0.
+double GetAnyValueF(reflection::BaseType type, const uint8_t *data);
+// All scalars converted using stringstream, strings as-is, and all other
+// data types provide some level of debug-pretty-printing.
+std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
+ const reflection::Schema *schema, int type_index);
+
+// Get any table field as a 64bit int, regardless of what type it is.
+inline int64_t GetAnyFieldI(const Table &table,
+ const reflection::Field &field) {
+ auto field_ptr = table.GetAddressOf(field.offset());
+ return field_ptr ? GetAnyValueI(field.type()->base_type(), field_ptr)
+ : field.default_integer();
+}
+
+// Get any table field as a double, regardless of what type it is.
+inline double GetAnyFieldF(const Table &table, const reflection::Field &field) {
+ auto field_ptr = table.GetAddressOf(field.offset());
+ return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr)
+ : field.default_real();
+}
+
+// Get any table field as a string, regardless of what type it is.
+// You may pass nullptr for the schema if you don't care to have fields that
+// are of table type pretty-printed.
+inline std::string GetAnyFieldS(const Table &table,
+ const reflection::Field &field,
+ const reflection::Schema *schema) {
+ auto field_ptr = table.GetAddressOf(field.offset());
+ return field_ptr ? GetAnyValueS(field.type()->base_type(), field_ptr, schema,
+ field.type()->index())
+ : "";
+}
+
+// Get any struct field as a 64bit int, regardless of what type it is.
+inline int64_t GetAnyFieldI(const Struct &st, const reflection::Field &field) {
+ return GetAnyValueI(field.type()->base_type(),
+ st.GetAddressOf(field.offset()));
+}
+
+// Get any struct field as a double, regardless of what type it is.
+inline double GetAnyFieldF(const Struct &st, const reflection::Field &field) {
+ return GetAnyValueF(field.type()->base_type(),
+ st.GetAddressOf(field.offset()));
+}
+
+// Get any struct field as a string, regardless of what type it is.
+inline std::string GetAnyFieldS(const Struct &st,
+ const reflection::Field &field) {
+ return GetAnyValueS(field.type()->base_type(),
+ st.GetAddressOf(field.offset()), nullptr, -1);
+}
+
+// Get any vector element as a 64bit int, regardless of what type it is.
+inline int64_t GetAnyVectorElemI(const VectorOfAny *vec,
+ reflection::BaseType elem_type, size_t i) {
+ return GetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
+}
+
+// Get any vector element as a double, regardless of what type it is.
+inline double GetAnyVectorElemF(const VectorOfAny *vec,
+ reflection::BaseType elem_type, size_t i) {
+ return GetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
+}
+
+// Get any vector element as a string, regardless of what type it is.
+inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
+ reflection::BaseType elem_type, size_t i) {
+ return GetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i,
+ nullptr, -1);
+}
+
+// Get a vector element that's a table/string/vector from a generic vector.
+// Pass Table/String/VectorOfAny as template parameter.
+// Warning: does no typechecking.
+template<typename T>
+T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
+ auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
+ return reinterpret_cast<T *>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
+}
+
+// Get the inline-address of a vector element. Useful for Structs (pass Struct
+// as template arg), or being able to address a range of scalars in-line.
+// Get elem_size from GetTypeSizeInline().
+// Note: little-endian data on all platforms, use EndianScalar() instead of
+// raw pointer access with scalars).
+template<typename T>
+T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i,
+ size_t elem_size) {
+ return reinterpret_cast<T *>(vec->Data() + elem_size * i);
+}
+
+// Similarly, for elements of tables.
+template<typename T>
+T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) {
+ return reinterpret_cast<T *>(table.GetAddressOf(field.offset()));
+}
+
+// Similarly, for elements of structs.
+template<typename T>
+T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
+ return reinterpret_cast<T *>(st.GetAddressOf(field.offset()));
+}
+
+// ------------------------- SETTERS -------------------------
+
+// Set any scalar field, if you know its exact type.
+template<typename T>
+bool SetField(Table *table, const reflection::Field &field, T val) {
+ reflection::BaseType type = field.type()->base_type();
+ if (!IsScalar(type)) { return false; }
+ FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(type));
+ T def;
+ if (IsInteger(type)) {
+ def = GetFieldDefaultI<T>(field);
+ } else {
+ FLATBUFFERS_ASSERT(IsFloat(type));
+ def = GetFieldDefaultF<T>(field);
+ }
+ return table->SetField(field.offset(), val, def);
+}
+
+// Raw helper functions used below: set any value in memory as a 64bit int, a
+// double or a string.
+// These work for all scalar values, but do nothing for other data types.
+// To set a string, see SetString below.
+void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val);
+void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val);
+void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val);
+
+// Set any table field as a 64bit int, regardless of type what it is.
+inline bool SetAnyFieldI(Table *table, const reflection::Field &field,
+ int64_t val) {
+ auto field_ptr = table->GetAddressOf(field.offset());
+ if (!field_ptr) return val == GetFieldDefaultI<int64_t>(field);
+ SetAnyValueI(field.type()->base_type(), field_ptr, val);
+ return true;
+}
+
+// Set any table field as a double, regardless of what type it is.
+inline bool SetAnyFieldF(Table *table, const reflection::Field &field,
+ double val) {
+ auto field_ptr = table->GetAddressOf(field.offset());
+ if (!field_ptr) return val == GetFieldDefaultF<double>(field);
+ SetAnyValueF(field.type()->base_type(), field_ptr, val);
+ return true;
+}
+
+// Set any table field as a string, regardless of what type it is.
+inline bool SetAnyFieldS(Table *table, const reflection::Field &field,
+ const char *val) {
+ auto field_ptr = table->GetAddressOf(field.offset());
+ if (!field_ptr) return false;
+ SetAnyValueS(field.type()->base_type(), field_ptr, val);
+ return true;
+}
+
+// Set any struct field as a 64bit int, regardless of type what it is.
+inline void SetAnyFieldI(Struct *st, const reflection::Field &field,
+ int64_t val) {
+ SetAnyValueI(field.type()->base_type(), st->GetAddressOf(field.offset()),
+ val);
+}
+
+// Set any struct field as a double, regardless of type what it is.
+inline void SetAnyFieldF(Struct *st, const reflection::Field &field,
+ double val) {
+ SetAnyValueF(field.type()->base_type(), st->GetAddressOf(field.offset()),
+ val);
+}
+
+// Set any struct field as a string, regardless of type what it is.
+inline void SetAnyFieldS(Struct *st, const reflection::Field &field,
+ const char *val) {
+ SetAnyValueS(field.type()->base_type(), st->GetAddressOf(field.offset()),
+ val);
+}
+
+// Set any vector element as a 64bit int, regardless of type what it is.
+inline void SetAnyVectorElemI(VectorOfAny *vec, reflection::BaseType elem_type,
+ size_t i, int64_t val) {
+ SetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
+}
+
+// Set any vector element as a double, regardless of type what it is.
+inline void SetAnyVectorElemF(VectorOfAny *vec, reflection::BaseType elem_type,
+ size_t i, double val) {
+ SetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
+}
+
+// Set any vector element as a string, regardless of type what it is.
+inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type,
+ size_t i, const char *val) {
+ SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
+}
+
+// ------------------------- RESIZING SETTERS -------------------------
+
+// "smart" pointer for use with resizing vectors: turns a pointer inside
+// a vector into a relative offset, such that it is not affected by resizes.
+template<typename T, typename U> class pointer_inside_vector {
+ public:
+ pointer_inside_vector(T *ptr, std::vector<U> &vec)
+ : offset_(reinterpret_cast<uint8_t *>(ptr) -
+ reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))),
+ vec_(vec) {}
+
+ T *operator*() const {
+ return reinterpret_cast<T *>(
+ reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec_)) + offset_);
+ }
+ T *operator->() const { return operator*(); }
+
+ private:
+ size_t offset_;
+ std::vector<U> &vec_;
+};
+
+// Helper to create the above easily without specifying template args.
+template<typename T, typename U>
+pointer_inside_vector<T, U> piv(T *ptr, std::vector<U> &vec) {
+ return pointer_inside_vector<T, U>(ptr, vec);
+}
+
+inline const char *UnionTypeFieldSuffix() { return "_type"; }
+
+// Helper to figure out the actual table type a union refers to.
+inline const reflection::Object &GetUnionType(
+ const reflection::Schema &schema, const reflection::Object &parent,
+ const reflection::Field &unionfield, const Table &table) {
+ auto enumdef = schema.enums()->Get(unionfield.type()->index());
+ // TODO: this is clumsy and slow, but no other way to find it?
+ auto type_field = parent.fields()->LookupByKey(
+ (unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
+ FLATBUFFERS_ASSERT(type_field);
+ auto union_type = GetFieldI<uint8_t>(table, *type_field);
+ auto enumval = enumdef->values()->LookupByKey(union_type);
+ return *enumval->object();
+}
+
+// Changes the contents of a string inside a FlatBuffer. FlatBuffer must
+// live inside a std::vector so we can resize the buffer if needed.
+// "str" must live inside "flatbuf" and may be invalidated after this call.
+// If your FlatBuffer's root table is not the schema's root table, you should
+// pass in your root_table type as well.
+void SetString(const reflection::Schema &schema, const std::string &val,
+ const String *str, std::vector<uint8_t> *flatbuf,
+ const reflection::Object *root_table = nullptr);
+
+// Resizes a flatbuffers::Vector inside a FlatBuffer. FlatBuffer must
+// live inside a std::vector so we can resize the buffer if needed.
+// "vec" must live inside "flatbuf" and may be invalidated after this call.
+// If your FlatBuffer's root table is not the schema's root table, you should
+// pass in your root_table type as well.
+uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
+ const VectorOfAny *vec, uoffset_t num_elems,
+ uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
+ const reflection::Object *root_table = nullptr);
+
+template<typename T>
+void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
+ const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
+ const reflection::Object *root_table = nullptr) {
+ auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
+ auto newelems = ResizeAnyVector(
+ schema, newsize, reinterpret_cast<const VectorOfAny *>(vec), vec->size(),
+ static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table);
+ // Set new elements to "val".
+ for (int i = 0; i < delta_elem; i++) {
+ auto loc = newelems + i * sizeof(T);
+ auto is_scalar = flatbuffers::is_scalar<T>::value;
+ if (is_scalar) {
+ WriteScalar(loc, val);
+ } else { // struct
+ *reinterpret_cast<T *>(loc) = val;
+ }
+ }
+}
+
+// Adds any new data (in the form of a new FlatBuffer) to an existing
+// FlatBuffer. This can be used when any of the above methods are not
+// sufficient, in particular for adding new tables and new fields.
+// This is potentially slightly less efficient than a FlatBuffer constructed
+// in one piece, since the new FlatBuffer doesn't share any vtables with the
+// existing one.
+// The return value can now be set using Vector::MutateOffset or SetFieldT
+// below.
+const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
+ const uint8_t *newbuf, size_t newlen);
+
+inline bool SetFieldT(Table *table, const reflection::Field &field,
+ const uint8_t *val) {
+ FLATBUFFERS_ASSERT(sizeof(uoffset_t) ==
+ GetTypeSize(field.type()->base_type()));
+ return table->SetPointer(field.offset(), val);
+}
+
+// ------------------------- COPYING -------------------------
+
+// Generic copying of tables from a FlatBuffer into a FlatBuffer builder.
+// Can be used to do any kind of merging/selecting you may want to do out
+// of existing buffers. Also useful to reconstruct a whole buffer if the
+// above resizing functionality has introduced garbage in a buffer you want
+// to remove.
+// Note: this does not deal with DAGs correctly. If the table passed forms a
+// DAG, the copy will be a tree instead (with duplicates). Strings can be
+// shared however, by passing true for use_string_pooling.
+
+Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
+ const reflection::Schema &schema,
+ const reflection::Object &objectdef,
+ const Table &table,
+ bool use_string_pooling = false);
+
+// Verifies the provided flatbuffer using reflection.
+// root should point to the root type for this flatbuffer.
+// buf should point to the start of flatbuffer data.
+// length specifies the size of the flatbuffer data.
+bool Verify(const reflection::Schema &schema, const reflection::Object &root,
+ const uint8_t *buf, size_t length, uoffset_t max_depth = 64,
+ uoffset_t max_tables = 1000000);
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_REFLECTION_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h b/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h
new file mode 100644
index 0000000000..93dc4b88b7
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/reflection_generated.h
@@ -0,0 +1,1278 @@
+// automatically generated by the FlatBuffers compiler, do not modify
+
+
+#ifndef FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
+#define FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
+
+#include "flatbuffers.h"
+
+namespace reflection {
+
+struct Type;
+struct TypeBuilder;
+
+struct KeyValue;
+struct KeyValueBuilder;
+
+struct EnumVal;
+struct EnumValBuilder;
+
+struct Enum;
+struct EnumBuilder;
+
+struct Field;
+struct FieldBuilder;
+
+struct Object;
+struct ObjectBuilder;
+
+struct RPCCall;
+struct RPCCallBuilder;
+
+struct Service;
+struct ServiceBuilder;
+
+struct Schema;
+struct SchemaBuilder;
+
+enum BaseType {
+ None = 0,
+ UType = 1,
+ Bool = 2,
+ Byte = 3,
+ UByte = 4,
+ Short = 5,
+ UShort = 6,
+ Int = 7,
+ UInt = 8,
+ Long = 9,
+ ULong = 10,
+ Float = 11,
+ Double = 12,
+ String = 13,
+ Vector = 14,
+ Obj = 15,
+ Union = 16,
+ Array = 17,
+ MaxBaseType = 18
+};
+
+inline const BaseType (&EnumValuesBaseType())[19] {
+ static const BaseType values[] = {
+ None,
+ UType,
+ Bool,
+ Byte,
+ UByte,
+ Short,
+ UShort,
+ Int,
+ UInt,
+ Long,
+ ULong,
+ Float,
+ Double,
+ String,
+ Vector,
+ Obj,
+ Union,
+ Array,
+ MaxBaseType
+ };
+ return values;
+}
+
+inline const char * const *EnumNamesBaseType() {
+ static const char * const names[20] = {
+ "None",
+ "UType",
+ "Bool",
+ "Byte",
+ "UByte",
+ "Short",
+ "UShort",
+ "Int",
+ "UInt",
+ "Long",
+ "ULong",
+ "Float",
+ "Double",
+ "String",
+ "Vector",
+ "Obj",
+ "Union",
+ "Array",
+ "MaxBaseType",
+ nullptr
+ };
+ return names;
+}
+
+inline const char *EnumNameBaseType(BaseType e) {
+ if (flatbuffers::IsOutRange(e, None, MaxBaseType)) return "";
+ const size_t index = static_cast<size_t>(e);
+ return EnumNamesBaseType()[index];
+}
+
+enum AdvancedFeatures {
+ AdvancedArrayFeatures = 1ULL,
+ AdvancedUnionFeatures = 2ULL,
+ OptionalScalars = 4ULL,
+ DefaultVectorsAndStrings = 8ULL
+};
+
+inline const AdvancedFeatures (&EnumValuesAdvancedFeatures())[4] {
+ static const AdvancedFeatures values[] = {
+ AdvancedArrayFeatures,
+ AdvancedUnionFeatures,
+ OptionalScalars,
+ DefaultVectorsAndStrings
+ };
+ return values;
+}
+
+inline const char * const *EnumNamesAdvancedFeatures() {
+ static const char * const names[9] = {
+ "AdvancedArrayFeatures",
+ "AdvancedUnionFeatures",
+ "",
+ "OptionalScalars",
+ "",
+ "",
+ "",
+ "DefaultVectorsAndStrings",
+ nullptr
+ };
+ return names;
+}
+
+inline const char *EnumNameAdvancedFeatures(AdvancedFeatures e) {
+ if (flatbuffers::IsOutRange(e, AdvancedArrayFeatures, DefaultVectorsAndStrings)) return "";
+ const size_t index = static_cast<size_t>(e) - static_cast<size_t>(AdvancedArrayFeatures);
+ return EnumNamesAdvancedFeatures()[index];
+}
+
+struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef TypeBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_BASE_TYPE = 4,
+ VT_ELEMENT = 6,
+ VT_INDEX = 8,
+ VT_FIXED_LENGTH = 10
+ };
+ reflection::BaseType base_type() const {
+ return static_cast<reflection::BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
+ }
+ reflection::BaseType element() const {
+ return static_cast<reflection::BaseType>(GetField<int8_t>(VT_ELEMENT, 0));
+ }
+ int32_t index() const {
+ return GetField<int32_t>(VT_INDEX, -1);
+ }
+ uint16_t fixed_length() const {
+ return GetField<uint16_t>(VT_FIXED_LENGTH, 0);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
+ VerifyField<int8_t>(verifier, VT_ELEMENT) &&
+ VerifyField<int32_t>(verifier, VT_INDEX) &&
+ VerifyField<uint16_t>(verifier, VT_FIXED_LENGTH) &&
+ verifier.EndTable();
+ }
+};
+
+struct TypeBuilder {
+ typedef Type Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_base_type(reflection::BaseType base_type) {
+ fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0);
+ }
+ void add_element(reflection::BaseType element) {
+ fbb_.AddElement<int8_t>(Type::VT_ELEMENT, static_cast<int8_t>(element), 0);
+ }
+ void add_index(int32_t index) {
+ fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
+ }
+ void add_fixed_length(uint16_t fixed_length) {
+ fbb_.AddElement<uint16_t>(Type::VT_FIXED_LENGTH, fixed_length, 0);
+ }
+ explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Type> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Type>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Type> CreateType(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ reflection::BaseType base_type = reflection::None,
+ reflection::BaseType element = reflection::None,
+ int32_t index = -1,
+ uint16_t fixed_length = 0) {
+ TypeBuilder builder_(_fbb);
+ builder_.add_index(index);
+ builder_.add_fixed_length(fixed_length);
+ builder_.add_element(element);
+ builder_.add_base_type(base_type);
+ return builder_.Finish();
+}
+
+struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef KeyValueBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_KEY = 4,
+ VT_VALUE = 6
+ };
+ const flatbuffers::String *key() const {
+ return GetPointer<const flatbuffers::String *>(VT_KEY);
+ }
+ bool KeyCompareLessThan(const KeyValue *o) const {
+ return *key() < *o->key();
+ }
+ int KeyCompareWithValue(const char *val) const {
+ return strcmp(key()->c_str(), val);
+ }
+ const flatbuffers::String *value() const {
+ return GetPointer<const flatbuffers::String *>(VT_VALUE);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffsetRequired(verifier, VT_KEY) &&
+ verifier.VerifyString(key()) &&
+ VerifyOffset(verifier, VT_VALUE) &&
+ verifier.VerifyString(value()) &&
+ verifier.EndTable();
+ }
+};
+
+struct KeyValueBuilder {
+ typedef KeyValue Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_key(flatbuffers::Offset<flatbuffers::String> key) {
+ fbb_.AddOffset(KeyValue::VT_KEY, key);
+ }
+ void add_value(flatbuffers::Offset<flatbuffers::String> value) {
+ fbb_.AddOffset(KeyValue::VT_VALUE, value);
+ }
+ explicit KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<KeyValue> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<KeyValue>(end);
+ fbb_.Required(o, KeyValue::VT_KEY);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<KeyValue> CreateKeyValue(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> key = 0,
+ flatbuffers::Offset<flatbuffers::String> value = 0) {
+ KeyValueBuilder builder_(_fbb);
+ builder_.add_value(value);
+ builder_.add_key(key);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ const char *key = nullptr,
+ const char *value = nullptr) {
+ auto key__ = key ? _fbb.CreateString(key) : 0;
+ auto value__ = value ? _fbb.CreateString(value) : 0;
+ return reflection::CreateKeyValue(
+ _fbb,
+ key__,
+ value__);
+}
+
+struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef EnumValBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_NAME = 4,
+ VT_VALUE = 6,
+ VT_OBJECT = 8,
+ VT_UNION_TYPE = 10,
+ VT_DOCUMENTATION = 12
+ };
+ const flatbuffers::String *name() const {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ int64_t value() const {
+ return GetField<int64_t>(VT_VALUE, 0);
+ }
+ bool KeyCompareLessThan(const EnumVal *o) const {
+ return value() < o->value();
+ }
+ int KeyCompareWithValue(int64_t val) const {
+ return static_cast<int>(value() > val) - static_cast<int>(value() < val);
+ }
+ const reflection::Object *object() const {
+ return GetPointer<const reflection::Object *>(VT_OBJECT);
+ }
+ const reflection::Type *union_type() const {
+ return GetPointer<const reflection::Type *>(VT_UNION_TYPE);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) &&
+ VerifyField<int64_t>(verifier, VT_VALUE) &&
+ VerifyOffset(verifier, VT_OBJECT) &&
+ verifier.VerifyTable(object()) &&
+ VerifyOffset(verifier, VT_UNION_TYPE) &&
+ verifier.VerifyTable(union_type()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) &&
+ verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) &&
+ verifier.EndTable();
+ }
+};
+
+struct EnumValBuilder {
+ typedef EnumVal Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ fbb_.AddOffset(EnumVal::VT_NAME, name);
+ }
+ void add_value(int64_t value) {
+ fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0);
+ }
+ void add_object(flatbuffers::Offset<reflection::Object> object) {
+ fbb_.AddOffset(EnumVal::VT_OBJECT, object);
+ }
+ void add_union_type(flatbuffers::Offset<reflection::Type> union_type) {
+ fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type);
+ }
+ void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
+ fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation);
+ }
+ explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<EnumVal> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<EnumVal>(end);
+ fbb_.Required(o, EnumVal::VT_NAME);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<EnumVal> CreateEnumVal(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> name = 0,
+ int64_t value = 0,
+ flatbuffers::Offset<reflection::Object> object = 0,
+ flatbuffers::Offset<reflection::Type> union_type = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
+ EnumValBuilder builder_(_fbb);
+ builder_.add_value(value);
+ builder_.add_documentation(documentation);
+ builder_.add_union_type(union_type);
+ builder_.add_object(object);
+ builder_.add_name(name);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ const char *name = nullptr,
+ int64_t value = 0,
+ flatbuffers::Offset<reflection::Object> object = 0,
+ flatbuffers::Offset<reflection::Type> union_type = 0,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateEnumVal(
+ _fbb,
+ name__,
+ value,
+ object,
+ union_type,
+ documentation__);
+}
+
+struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef EnumBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_NAME = 4,
+ VT_VALUES = 6,
+ VT_IS_UNION = 8,
+ VT_UNDERLYING_TYPE = 10,
+ VT_ATTRIBUTES = 12,
+ VT_DOCUMENTATION = 14
+ };
+ const flatbuffers::String *name() const {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ bool KeyCompareLessThan(const Enum *o) const {
+ return *name() < *o->name();
+ }
+ int KeyCompareWithValue(const char *val) const {
+ return strcmp(name()->c_str(), val);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *values() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *>(VT_VALUES);
+ }
+ bool is_union() const {
+ return GetField<uint8_t>(VT_IS_UNION, 0) != 0;
+ }
+ const reflection::Type *underlying_type() const {
+ return GetPointer<const reflection::Type *>(VT_UNDERLYING_TYPE);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) &&
+ VerifyOffsetRequired(verifier, VT_VALUES) &&
+ verifier.VerifyVector(values()) &&
+ verifier.VerifyVectorOfTables(values()) &&
+ VerifyField<uint8_t>(verifier, VT_IS_UNION) &&
+ VerifyOffsetRequired(verifier, VT_UNDERLYING_TYPE) &&
+ verifier.VerifyTable(underlying_type()) &&
+ VerifyOffset(verifier, VT_ATTRIBUTES) &&
+ verifier.VerifyVector(attributes()) &&
+ verifier.VerifyVectorOfTables(attributes()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) &&
+ verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) &&
+ verifier.EndTable();
+ }
+};
+
+struct EnumBuilder {
+ typedef Enum Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ fbb_.AddOffset(Enum::VT_NAME, name);
+ }
+ void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>>> values) {
+ fbb_.AddOffset(Enum::VT_VALUES, values);
+ }
+ void add_is_union(bool is_union) {
+ fbb_.AddElement<uint8_t>(Enum::VT_IS_UNION, static_cast<uint8_t>(is_union), 0);
+ }
+ void add_underlying_type(flatbuffers::Offset<reflection::Type> underlying_type) {
+ fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type);
+ }
+ void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
+ fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes);
+ }
+ void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
+ fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation);
+ }
+ explicit EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Enum> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Enum>(end);
+ fbb_.Required(o, Enum::VT_NAME);
+ fbb_.Required(o, Enum::VT_VALUES);
+ fbb_.Required(o, Enum::VT_UNDERLYING_TYPE);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Enum> CreateEnum(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>>> values = 0,
+ bool is_union = false,
+ flatbuffers::Offset<reflection::Type> underlying_type = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
+ EnumBuilder builder_(_fbb);
+ builder_.add_documentation(documentation);
+ builder_.add_attributes(attributes);
+ builder_.add_underlying_type(underlying_type);
+ builder_.add_values(values);
+ builder_.add_name(name);
+ builder_.add_is_union(is_union);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Enum> CreateEnumDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ const char *name = nullptr,
+ std::vector<flatbuffers::Offset<reflection::EnumVal>> *values = nullptr,
+ bool is_union = false,
+ flatbuffers::Offset<reflection::Type> underlying_type = 0,
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto values__ = values ? _fbb.CreateVectorOfSortedTables<reflection::EnumVal>(values) : 0;
+ auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
+ auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateEnum(
+ _fbb,
+ name__,
+ values__,
+ is_union,
+ underlying_type,
+ attributes__,
+ documentation__);
+}
+
+struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef FieldBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_NAME = 4,
+ VT_TYPE = 6,
+ VT_ID = 8,
+ VT_OFFSET = 10,
+ VT_DEFAULT_INTEGER = 12,
+ VT_DEFAULT_REAL = 14,
+ VT_DEPRECATED = 16,
+ VT_REQUIRED = 18,
+ VT_KEY = 20,
+ VT_ATTRIBUTES = 22,
+ VT_DOCUMENTATION = 24,
+ VT_OPTIONAL = 26
+ };
+ const flatbuffers::String *name() const {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ bool KeyCompareLessThan(const Field *o) const {
+ return *name() < *o->name();
+ }
+ int KeyCompareWithValue(const char *val) const {
+ return strcmp(name()->c_str(), val);
+ }
+ const reflection::Type *type() const {
+ return GetPointer<const reflection::Type *>(VT_TYPE);
+ }
+ uint16_t id() const {
+ return GetField<uint16_t>(VT_ID, 0);
+ }
+ uint16_t offset() const {
+ return GetField<uint16_t>(VT_OFFSET, 0);
+ }
+ int64_t default_integer() const {
+ return GetField<int64_t>(VT_DEFAULT_INTEGER, 0);
+ }
+ double default_real() const {
+ return GetField<double>(VT_DEFAULT_REAL, 0.0);
+ }
+ bool deprecated() const {
+ return GetField<uint8_t>(VT_DEPRECATED, 0) != 0;
+ }
+ bool required() const {
+ return GetField<uint8_t>(VT_REQUIRED, 0) != 0;
+ }
+ bool key() const {
+ return GetField<uint8_t>(VT_KEY, 0) != 0;
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
+ }
+ bool optional() const {
+ return GetField<uint8_t>(VT_OPTIONAL, 0) != 0;
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) &&
+ VerifyOffsetRequired(verifier, VT_TYPE) &&
+ verifier.VerifyTable(type()) &&
+ VerifyField<uint16_t>(verifier, VT_ID) &&
+ VerifyField<uint16_t>(verifier, VT_OFFSET) &&
+ VerifyField<int64_t>(verifier, VT_DEFAULT_INTEGER) &&
+ VerifyField<double>(verifier, VT_DEFAULT_REAL) &&
+ VerifyField<uint8_t>(verifier, VT_DEPRECATED) &&
+ VerifyField<uint8_t>(verifier, VT_REQUIRED) &&
+ VerifyField<uint8_t>(verifier, VT_KEY) &&
+ VerifyOffset(verifier, VT_ATTRIBUTES) &&
+ verifier.VerifyVector(attributes()) &&
+ verifier.VerifyVectorOfTables(attributes()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) &&
+ verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) &&
+ VerifyField<uint8_t>(verifier, VT_OPTIONAL) &&
+ verifier.EndTable();
+ }
+};
+
+struct FieldBuilder {
+ typedef Field Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ fbb_.AddOffset(Field::VT_NAME, name);
+ }
+ void add_type(flatbuffers::Offset<reflection::Type> type) {
+ fbb_.AddOffset(Field::VT_TYPE, type);
+ }
+ void add_id(uint16_t id) {
+ fbb_.AddElement<uint16_t>(Field::VT_ID, id, 0);
+ }
+ void add_offset(uint16_t offset) {
+ fbb_.AddElement<uint16_t>(Field::VT_OFFSET, offset, 0);
+ }
+ void add_default_integer(int64_t default_integer) {
+ fbb_.AddElement<int64_t>(Field::VT_DEFAULT_INTEGER, default_integer, 0);
+ }
+ void add_default_real(double default_real) {
+ fbb_.AddElement<double>(Field::VT_DEFAULT_REAL, default_real, 0.0);
+ }
+ void add_deprecated(bool deprecated) {
+ fbb_.AddElement<uint8_t>(Field::VT_DEPRECATED, static_cast<uint8_t>(deprecated), 0);
+ }
+ void add_required(bool required) {
+ fbb_.AddElement<uint8_t>(Field::VT_REQUIRED, static_cast<uint8_t>(required), 0);
+ }
+ void add_key(bool key) {
+ fbb_.AddElement<uint8_t>(Field::VT_KEY, static_cast<uint8_t>(key), 0);
+ }
+ void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
+ fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes);
+ }
+ void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
+ fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation);
+ }
+ void add_optional(bool optional) {
+ fbb_.AddElement<uint8_t>(Field::VT_OPTIONAL, static_cast<uint8_t>(optional), 0);
+ }
+ explicit FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Field> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Field>(end);
+ fbb_.Required(o, Field::VT_NAME);
+ fbb_.Required(o, Field::VT_TYPE);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Field> CreateField(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<reflection::Type> type = 0,
+ uint16_t id = 0,
+ uint16_t offset = 0,
+ int64_t default_integer = 0,
+ double default_real = 0.0,
+ bool deprecated = false,
+ bool required = false,
+ bool key = false,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0,
+ bool optional = false) {
+ FieldBuilder builder_(_fbb);
+ builder_.add_default_real(default_real);
+ builder_.add_default_integer(default_integer);
+ builder_.add_documentation(documentation);
+ builder_.add_attributes(attributes);
+ builder_.add_type(type);
+ builder_.add_name(name);
+ builder_.add_offset(offset);
+ builder_.add_id(id);
+ builder_.add_optional(optional);
+ builder_.add_key(key);
+ builder_.add_required(required);
+ builder_.add_deprecated(deprecated);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Field> CreateFieldDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ const char *name = nullptr,
+ flatbuffers::Offset<reflection::Type> type = 0,
+ uint16_t id = 0,
+ uint16_t offset = 0,
+ int64_t default_integer = 0,
+ double default_real = 0.0,
+ bool deprecated = false,
+ bool required = false,
+ bool key = false,
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr,
+ bool optional = false) {
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
+ auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateField(
+ _fbb,
+ name__,
+ type,
+ id,
+ offset,
+ default_integer,
+ default_real,
+ deprecated,
+ required,
+ key,
+ attributes__,
+ documentation__,
+ optional);
+}
+
+struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef ObjectBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_NAME = 4,
+ VT_FIELDS = 6,
+ VT_IS_STRUCT = 8,
+ VT_MINALIGN = 10,
+ VT_BYTESIZE = 12,
+ VT_ATTRIBUTES = 14,
+ VT_DOCUMENTATION = 16
+ };
+ const flatbuffers::String *name() const {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ bool KeyCompareLessThan(const Object *o) const {
+ return *name() < *o->name();
+ }
+ int KeyCompareWithValue(const char *val) const {
+ return strcmp(name()->c_str(), val);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *fields() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *>(VT_FIELDS);
+ }
+ bool is_struct() const {
+ return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0;
+ }
+ int32_t minalign() const {
+ return GetField<int32_t>(VT_MINALIGN, 0);
+ }
+ int32_t bytesize() const {
+ return GetField<int32_t>(VT_BYTESIZE, 0);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) &&
+ VerifyOffsetRequired(verifier, VT_FIELDS) &&
+ verifier.VerifyVector(fields()) &&
+ verifier.VerifyVectorOfTables(fields()) &&
+ VerifyField<uint8_t>(verifier, VT_IS_STRUCT) &&
+ VerifyField<int32_t>(verifier, VT_MINALIGN) &&
+ VerifyField<int32_t>(verifier, VT_BYTESIZE) &&
+ VerifyOffset(verifier, VT_ATTRIBUTES) &&
+ verifier.VerifyVector(attributes()) &&
+ verifier.VerifyVectorOfTables(attributes()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) &&
+ verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) &&
+ verifier.EndTable();
+ }
+};
+
+struct ObjectBuilder {
+ typedef Object Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ fbb_.AddOffset(Object::VT_NAME, name);
+ }
+ void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Field>>> fields) {
+ fbb_.AddOffset(Object::VT_FIELDS, fields);
+ }
+ void add_is_struct(bool is_struct) {
+ fbb_.AddElement<uint8_t>(Object::VT_IS_STRUCT, static_cast<uint8_t>(is_struct), 0);
+ }
+ void add_minalign(int32_t minalign) {
+ fbb_.AddElement<int32_t>(Object::VT_MINALIGN, minalign, 0);
+ }
+ void add_bytesize(int32_t bytesize) {
+ fbb_.AddElement<int32_t>(Object::VT_BYTESIZE, bytesize, 0);
+ }
+ void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
+ fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes);
+ }
+ void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
+ fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation);
+ }
+ explicit ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Object> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Object>(end);
+ fbb_.Required(o, Object::VT_NAME);
+ fbb_.Required(o, Object::VT_FIELDS);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Object> CreateObject(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Field>>> fields = 0,
+ bool is_struct = false,
+ int32_t minalign = 0,
+ int32_t bytesize = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
+ ObjectBuilder builder_(_fbb);
+ builder_.add_documentation(documentation);
+ builder_.add_attributes(attributes);
+ builder_.add_bytesize(bytesize);
+ builder_.add_minalign(minalign);
+ builder_.add_fields(fields);
+ builder_.add_name(name);
+ builder_.add_is_struct(is_struct);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Object> CreateObjectDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ const char *name = nullptr,
+ std::vector<flatbuffers::Offset<reflection::Field>> *fields = nullptr,
+ bool is_struct = false,
+ int32_t minalign = 0,
+ int32_t bytesize = 0,
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto fields__ = fields ? _fbb.CreateVectorOfSortedTables<reflection::Field>(fields) : 0;
+ auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
+ auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateObject(
+ _fbb,
+ name__,
+ fields__,
+ is_struct,
+ minalign,
+ bytesize,
+ attributes__,
+ documentation__);
+}
+
+struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef RPCCallBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_NAME = 4,
+ VT_REQUEST = 6,
+ VT_RESPONSE = 8,
+ VT_ATTRIBUTES = 10,
+ VT_DOCUMENTATION = 12
+ };
+ const flatbuffers::String *name() const {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ bool KeyCompareLessThan(const RPCCall *o) const {
+ return *name() < *o->name();
+ }
+ int KeyCompareWithValue(const char *val) const {
+ return strcmp(name()->c_str(), val);
+ }
+ const reflection::Object *request() const {
+ return GetPointer<const reflection::Object *>(VT_REQUEST);
+ }
+ const reflection::Object *response() const {
+ return GetPointer<const reflection::Object *>(VT_RESPONSE);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) &&
+ VerifyOffsetRequired(verifier, VT_REQUEST) &&
+ verifier.VerifyTable(request()) &&
+ VerifyOffsetRequired(verifier, VT_RESPONSE) &&
+ verifier.VerifyTable(response()) &&
+ VerifyOffset(verifier, VT_ATTRIBUTES) &&
+ verifier.VerifyVector(attributes()) &&
+ verifier.VerifyVectorOfTables(attributes()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) &&
+ verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) &&
+ verifier.EndTable();
+ }
+};
+
+struct RPCCallBuilder {
+ typedef RPCCall Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ fbb_.AddOffset(RPCCall::VT_NAME, name);
+ }
+ void add_request(flatbuffers::Offset<reflection::Object> request) {
+ fbb_.AddOffset(RPCCall::VT_REQUEST, request);
+ }
+ void add_response(flatbuffers::Offset<reflection::Object> response) {
+ fbb_.AddOffset(RPCCall::VT_RESPONSE, response);
+ }
+ void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
+ fbb_.AddOffset(RPCCall::VT_ATTRIBUTES, attributes);
+ }
+ void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
+ fbb_.AddOffset(RPCCall::VT_DOCUMENTATION, documentation);
+ }
+ explicit RPCCallBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<RPCCall> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<RPCCall>(end);
+ fbb_.Required(o, RPCCall::VT_NAME);
+ fbb_.Required(o, RPCCall::VT_REQUEST);
+ fbb_.Required(o, RPCCall::VT_RESPONSE);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<RPCCall> CreateRPCCall(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<reflection::Object> request = 0,
+ flatbuffers::Offset<reflection::Object> response = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
+ RPCCallBuilder builder_(_fbb);
+ builder_.add_documentation(documentation);
+ builder_.add_attributes(attributes);
+ builder_.add_response(response);
+ builder_.add_request(request);
+ builder_.add_name(name);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ const char *name = nullptr,
+ flatbuffers::Offset<reflection::Object> request = 0,
+ flatbuffers::Offset<reflection::Object> response = 0,
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
+ auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateRPCCall(
+ _fbb,
+ name__,
+ request,
+ response,
+ attributes__,
+ documentation__);
+}
+
+struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef ServiceBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_NAME = 4,
+ VT_CALLS = 6,
+ VT_ATTRIBUTES = 8,
+ VT_DOCUMENTATION = 10
+ };
+ const flatbuffers::String *name() const {
+ return GetPointer<const flatbuffers::String *>(VT_NAME);
+ }
+ bool KeyCompareLessThan(const Service *o) const {
+ return *name() < *o->name();
+ }
+ int KeyCompareWithValue(const char *val) const {
+ return strcmp(name()->c_str(), val);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>> *calls() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>> *>(VT_CALLS);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffsetRequired(verifier, VT_NAME) &&
+ verifier.VerifyString(name()) &&
+ VerifyOffset(verifier, VT_CALLS) &&
+ verifier.VerifyVector(calls()) &&
+ verifier.VerifyVectorOfTables(calls()) &&
+ VerifyOffset(verifier, VT_ATTRIBUTES) &&
+ verifier.VerifyVector(attributes()) &&
+ verifier.VerifyVectorOfTables(attributes()) &&
+ VerifyOffset(verifier, VT_DOCUMENTATION) &&
+ verifier.VerifyVector(documentation()) &&
+ verifier.VerifyVectorOfStrings(documentation()) &&
+ verifier.EndTable();
+ }
+};
+
+struct ServiceBuilder {
+ typedef Service Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_name(flatbuffers::Offset<flatbuffers::String> name) {
+ fbb_.AddOffset(Service::VT_NAME, name);
+ }
+ void add_calls(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>>> calls) {
+ fbb_.AddOffset(Service::VT_CALLS, calls);
+ }
+ void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
+ fbb_.AddOffset(Service::VT_ATTRIBUTES, attributes);
+ }
+ void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
+ fbb_.AddOffset(Service::VT_DOCUMENTATION, documentation);
+ }
+ explicit ServiceBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Service> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Service>(end);
+ fbb_.Required(o, Service::VT_NAME);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Service> CreateService(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::String> name = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>>> calls = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
+ ServiceBuilder builder_(_fbb);
+ builder_.add_documentation(documentation);
+ builder_.add_attributes(attributes);
+ builder_.add_calls(calls);
+ builder_.add_name(name);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Service> CreateServiceDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ const char *name = nullptr,
+ std::vector<flatbuffers::Offset<reflection::RPCCall>> *calls = nullptr,
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
+ const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
+ auto name__ = name ? _fbb.CreateString(name) : 0;
+ auto calls__ = calls ? _fbb.CreateVectorOfSortedTables<reflection::RPCCall>(calls) : 0;
+ auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
+ auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
+ return reflection::CreateService(
+ _fbb,
+ name__,
+ calls__,
+ attributes__,
+ documentation__);
+}
+
+struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef SchemaBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_OBJECTS = 4,
+ VT_ENUMS = 6,
+ VT_FILE_IDENT = 8,
+ VT_FILE_EXT = 10,
+ VT_ROOT_TABLE = 12,
+ VT_SERVICES = 14,
+ VT_ADVANCED_FEATURES = 16
+ };
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *>(VT_OBJECTS);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *enums() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *>(VT_ENUMS);
+ }
+ const flatbuffers::String *file_ident() const {
+ return GetPointer<const flatbuffers::String *>(VT_FILE_IDENT);
+ }
+ const flatbuffers::String *file_ext() const {
+ return GetPointer<const flatbuffers::String *>(VT_FILE_EXT);
+ }
+ const reflection::Object *root_table() const {
+ return GetPointer<const reflection::Object *>(VT_ROOT_TABLE);
+ }
+ const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *services() const {
+ return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *>(VT_SERVICES);
+ }
+ reflection::AdvancedFeatures advanced_features() const {
+ return static_cast<reflection::AdvancedFeatures>(GetField<uint64_t>(VT_ADVANCED_FEATURES, 0));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffsetRequired(verifier, VT_OBJECTS) &&
+ verifier.VerifyVector(objects()) &&
+ verifier.VerifyVectorOfTables(objects()) &&
+ VerifyOffsetRequired(verifier, VT_ENUMS) &&
+ verifier.VerifyVector(enums()) &&
+ verifier.VerifyVectorOfTables(enums()) &&
+ VerifyOffset(verifier, VT_FILE_IDENT) &&
+ verifier.VerifyString(file_ident()) &&
+ VerifyOffset(verifier, VT_FILE_EXT) &&
+ verifier.VerifyString(file_ext()) &&
+ VerifyOffset(verifier, VT_ROOT_TABLE) &&
+ verifier.VerifyTable(root_table()) &&
+ VerifyOffset(verifier, VT_SERVICES) &&
+ verifier.VerifyVector(services()) &&
+ verifier.VerifyVectorOfTables(services()) &&
+ VerifyField<uint64_t>(verifier, VT_ADVANCED_FEATURES) &&
+ verifier.EndTable();
+ }
+};
+
+struct SchemaBuilder {
+ typedef Schema Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Object>>> objects) {
+ fbb_.AddOffset(Schema::VT_OBJECTS, objects);
+ }
+ void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>> enums) {
+ fbb_.AddOffset(Schema::VT_ENUMS, enums);
+ }
+ void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) {
+ fbb_.AddOffset(Schema::VT_FILE_IDENT, file_ident);
+ }
+ void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext) {
+ fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext);
+ }
+ void add_root_table(flatbuffers::Offset<reflection::Object> root_table) {
+ fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table);
+ }
+ void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services) {
+ fbb_.AddOffset(Schema::VT_SERVICES, services);
+ }
+ void add_advanced_features(reflection::AdvancedFeatures advanced_features) {
+ fbb_.AddElement<uint64_t>(Schema::VT_ADVANCED_FEATURES, static_cast<uint64_t>(advanced_features), 0);
+ }
+ explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ flatbuffers::Offset<Schema> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Schema>(end);
+ fbb_.Required(o, Schema::VT_OBJECTS);
+ fbb_.Required(o, Schema::VT_ENUMS);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Schema> CreateSchema(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Object>>> objects = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>> enums = 0,
+ flatbuffers::Offset<flatbuffers::String> file_ident = 0,
+ flatbuffers::Offset<flatbuffers::String> file_ext = 0,
+ flatbuffers::Offset<reflection::Object> root_table = 0,
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services = 0,
+ reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0)) {
+ SchemaBuilder builder_(_fbb);
+ builder_.add_advanced_features(advanced_features);
+ builder_.add_services(services);
+ builder_.add_root_table(root_table);
+ builder_.add_file_ext(file_ext);
+ builder_.add_file_ident(file_ident);
+ builder_.add_enums(enums);
+ builder_.add_objects(objects);
+ return builder_.Finish();
+}
+
+inline flatbuffers::Offset<Schema> CreateSchemaDirect(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ std::vector<flatbuffers::Offset<reflection::Object>> *objects = nullptr,
+ std::vector<flatbuffers::Offset<reflection::Enum>> *enums = nullptr,
+ const char *file_ident = nullptr,
+ const char *file_ext = nullptr,
+ flatbuffers::Offset<reflection::Object> root_table = 0,
+ std::vector<flatbuffers::Offset<reflection::Service>> *services = nullptr,
+ reflection::AdvancedFeatures advanced_features = static_cast<reflection::AdvancedFeatures>(0)) {
+ auto objects__ = objects ? _fbb.CreateVectorOfSortedTables<reflection::Object>(objects) : 0;
+ auto enums__ = enums ? _fbb.CreateVectorOfSortedTables<reflection::Enum>(enums) : 0;
+ auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0;
+ auto file_ext__ = file_ext ? _fbb.CreateString(file_ext) : 0;
+ auto services__ = services ? _fbb.CreateVectorOfSortedTables<reflection::Service>(services) : 0;
+ return reflection::CreateSchema(
+ _fbb,
+ objects__,
+ enums__,
+ file_ident__,
+ file_ext__,
+ root_table,
+ services__,
+ advanced_features);
+}
+
+inline const reflection::Schema *GetSchema(const void *buf) {
+ return flatbuffers::GetRoot<reflection::Schema>(buf);
+}
+
+inline const reflection::Schema *GetSizePrefixedSchema(const void *buf) {
+ return flatbuffers::GetSizePrefixedRoot<reflection::Schema>(buf);
+}
+
+inline const char *SchemaIdentifier() {
+ return "BFBS";
+}
+
+inline bool SchemaBufferHasIdentifier(const void *buf) {
+ return flatbuffers::BufferHasIdentifier(
+ buf, SchemaIdentifier());
+}
+
+inline bool VerifySchemaBuffer(
+ flatbuffers::Verifier &verifier) {
+ return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());
+}
+
+inline bool VerifySizePrefixedSchemaBuffer(
+ flatbuffers::Verifier &verifier) {
+ return verifier.VerifySizePrefixedBuffer<reflection::Schema>(SchemaIdentifier());
+}
+
+inline const char *SchemaExtension() {
+ return "bfbs";
+}
+
+inline void FinishSchemaBuffer(
+ flatbuffers::FlatBufferBuilder &fbb,
+ flatbuffers::Offset<reflection::Schema> root) {
+ fbb.Finish(root, SchemaIdentifier());
+}
+
+inline void FinishSizePrefixedSchemaBuffer(
+ flatbuffers::FlatBufferBuilder &fbb,
+ flatbuffers::Offset<reflection::Schema> root) {
+ fbb.FinishSizePrefixed(root, SchemaIdentifier());
+}
+
+} // namespace reflection
+
+#endif // FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
diff --git a/contrib/libs/flatbuffers/include/flatbuffers/util.h b/contrib/libs/flatbuffers/include/flatbuffers/util.h
new file mode 100644
index 0000000000..4493c561c2
--- /dev/null
+++ b/contrib/libs/flatbuffers/include/flatbuffers/util.h
@@ -0,0 +1,698 @@
+/*
+ * 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.
+ */
+
+#ifndef FLATBUFFERS_UTIL_H_
+#define FLATBUFFERS_UTIL_H_
+
+#include <errno.h>
+
+#include "base.h"
+#include "stl_emulation.h"
+
+#ifndef FLATBUFFERS_PREFER_PRINTF
+# include <sstream>
+#else // FLATBUFFERS_PREFER_PRINTF
+# include <float.h>
+# include <stdio.h>
+#endif // FLATBUFFERS_PREFER_PRINTF
+
+#include <iomanip>
+#include <string>
+
+namespace flatbuffers {
+
+// @locale-independent functions for ASCII characters set.
+
+// Fast checking that character lies in closed range: [a <= x <= b]
+// using one compare (conditional branch) operator.
+inline bool check_ascii_range(char x, char a, char b) {
+ FLATBUFFERS_ASSERT(a <= b);
+ // (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`.
+ // The x, a, b will be promoted to int and subtracted without overflow.
+ return static_cast<unsigned int>(x - a) <= static_cast<unsigned int>(b - a);
+}
+
+// Case-insensitive isalpha
+inline bool is_alpha(char c) {
+ // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
+ return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF);
+}
+
+// Check for uppercase alpha
+inline bool is_alpha_upper(char c) { return check_ascii_range(c, 'A', 'Z'); }
+
+// Check (case-insensitive) that `c` is equal to alpha.
+inline bool is_alpha_char(char c, char alpha) {
+ FLATBUFFERS_ASSERT(is_alpha(alpha));
+ // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
+ return ((c & 0xDF) == (alpha & 0xDF));
+}
+
+// https://en.cppreference.com/w/cpp/string/byte/isxdigit
+// isdigit and isxdigit are the only standard narrow character classification
+// functions that are not affected by the currently installed C locale. although
+// some implementations (e.g. Microsoft in 1252 codepage) may classify
+// additional single-byte characters as digits.
+inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); }
+
+inline bool is_xdigit(char c) {
+ // Replace by look-up table.
+ return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF);
+}
+
+// Case-insensitive isalnum
+inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); }
+
+inline char CharToUpper(char c) {
+ return static_cast<char>(::toupper(static_cast<unsigned char>(c)));
+}
+
+inline char CharToLower(char c) {
+ return static_cast<char>(::tolower(static_cast<unsigned char>(c)));
+}
+
+// @end-locale-independent functions for ASCII character set
+
+#ifdef FLATBUFFERS_PREFER_PRINTF
+template<typename T> size_t IntToDigitCount(T t) {
+ size_t digit_count = 0;
+ // Count the sign for negative numbers
+ if (t < 0) digit_count++;
+ // Count a single 0 left of the dot for fractional numbers
+ if (-1 < t && t < 1) digit_count++;
+ // Count digits until fractional part
+ T eps = std::numeric_limits<float>::epsilon();
+ while (t <= (-1 + eps) || (1 - eps) <= t) {
+ t /= 10;
+ digit_count++;
+ }
+ return digit_count;
+}
+
+template<typename T> size_t NumToStringWidth(T t, int precision = 0) {
+ size_t string_width = IntToDigitCount(t);
+ // Count the dot for floating point numbers
+ if (precision) string_width += (precision + 1);
+ return string_width;
+}
+
+template<typename T>
+std::string NumToStringImplWrapper(T t, const char *fmt, int precision = 0) {
+ size_t string_width = NumToStringWidth(t, precision);
+ std::string s(string_width, 0x00);
+ // Allow snprintf to use std::string trailing null to detect buffer overflow
+ snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, string_width, t);
+ return s;
+}
+#endif // FLATBUFFERS_PREFER_PRINTF
+
+// Convert an integer or floating point value to a string.
+// In contrast to std::stringstream, "char" values are
+// converted to a string of digits, and we don't use scientific notation.
+template<typename T> std::string NumToString(T t) {
+ // clang-format off
+
+ #ifndef FLATBUFFERS_PREFER_PRINTF
+ std::stringstream ss;
+ ss << t;
+ return ss.str();
+ #else // FLATBUFFERS_PREFER_PRINTF
+ auto v = static_cast<long long>(t);
+ return NumToStringImplWrapper(v, "%.*lld");
+ #endif // FLATBUFFERS_PREFER_PRINTF
+ // clang-format on
+}
+// Avoid char types used as character data.
+template<> inline std::string NumToString<signed char>(signed char t) {
+ return NumToString(static_cast<int>(t));
+}
+template<> inline std::string NumToString<unsigned char>(unsigned char t) {
+ return NumToString(static_cast<int>(t));
+}
+template<> inline std::string NumToString<char>(char t) {
+ return NumToString(static_cast<int>(t));
+}
+#if defined(FLATBUFFERS_CPP98_STL)
+template<> inline std::string NumToString<long long>(long long t) {
+ char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2
+ snprintf(buf, sizeof(buf), "%lld", t);
+ return std::string(buf);
+}
+
+template<>
+inline std::string NumToString<unsigned long long>(unsigned long long t) {
+ char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1
+ snprintf(buf, sizeof(buf), "%llu", t);
+ return std::string(buf);
+}
+#endif // defined(FLATBUFFERS_CPP98_STL)
+
+// Special versions for floats/doubles.
+template<typename T> std::string FloatToString(T t, int precision) {
+ // clang-format off
+
+ #ifndef FLATBUFFERS_PREFER_PRINTF
+ // to_string() prints different numbers of digits for floats depending on
+ // platform and isn't available on Android, so we use stringstream
+ std::stringstream ss;
+ // Use std::fixed to suppress scientific notation.
+ ss << std::fixed;
+ // Default precision is 6, we want that to be higher for doubles.
+ ss << std::setprecision(precision);
+ ss << t;
+ auto s = ss.str();
+ #else // FLATBUFFERS_PREFER_PRINTF
+ auto v = static_cast<double>(t);
+ auto s = NumToStringImplWrapper(v, "%0.*f", precision);
+ #endif // FLATBUFFERS_PREFER_PRINTF
+ // clang-format on
+ // Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
+ auto p = s.find_last_not_of('0');
+ if (p != std::string::npos) {
+ // Strip trailing zeroes. If it is a whole number, keep one zero.
+ s.resize(p + (s[p] == '.' ? 2 : 1));
+ }
+ return s;
+}
+
+template<> inline std::string NumToString<double>(double t) {
+ return FloatToString(t, 12);
+}
+template<> inline std::string NumToString<float>(float t) {
+ return FloatToString(t, 6);
+}
+
+// Convert an integer value to a hexadecimal string.
+// The returned string length is always xdigits long, prefixed by 0 digits.
+// For example, IntToStringHex(0x23, 8) returns the string "00000023".
+inline std::string IntToStringHex(int i, int xdigits) {
+ FLATBUFFERS_ASSERT(i >= 0);
+ // clang-format off
+
+ #ifndef FLATBUFFERS_PREFER_PRINTF
+ std::stringstream ss;
+ ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
+ << i;
+ return ss.str();
+ #else // FLATBUFFERS_PREFER_PRINTF
+ return NumToStringImplWrapper(i, "%.*X", xdigits);
+ #endif // FLATBUFFERS_PREFER_PRINTF
+ // clang-format on
+}
+
+// clang-format off
+// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}.
+#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
+ class ClassicLocale {
+ #ifdef _MSC_VER
+ typedef _locale_t locale_type;
+ #else
+ typedef locale_t locale_type; // POSIX.1-2008 locale_t type
+ #endif
+ ClassicLocale();
+ ~ClassicLocale();
+ locale_type locale_;
+ static ClassicLocale instance_;
+ public:
+ static locale_type Get() { return instance_.locale_; }
+ };
+
+ #ifdef _MSC_VER
+ #define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get())
+ #define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get())
+ #define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get())
+ #define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get())
+ #else
+ #define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get())
+ #define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get())
+ #define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get())
+ #define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get())
+ #endif
+#else
+ #define __strtod_impl(s, pe) strtod(s, pe)
+ #define __strtof_impl(s, pe) static_cast<float>(strtod(s, pe))
+ #ifdef _MSC_VER
+ #define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b)
+ #define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b)
+ #else
+ #define __strtoull_impl(s, pe, b) strtoull(s, pe, b)
+ #define __strtoll_impl(s, pe, b) strtoll(s, pe, b)
+ #endif
+#endif
+
+inline void strtoval_impl(int64_t *val, const char *str, char **endptr,
+ int base) {
+ *val = __strtoll_impl(str, endptr, base);
+}
+
+inline void strtoval_impl(uint64_t *val, const char *str, char **endptr,
+ int base) {
+ *val = __strtoull_impl(str, endptr, base);
+}
+
+inline void strtoval_impl(double *val, const char *str, char **endptr) {
+ *val = __strtod_impl(str, endptr);
+}
+
+// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true.
+__supress_ubsan__("float-cast-overflow")
+inline void strtoval_impl(float *val, const char *str, char **endptr) {
+ *val = __strtof_impl(str, endptr);
+}
+#undef __strtoull_impl
+#undef __strtoll_impl
+#undef __strtod_impl
+#undef __strtof_impl
+// clang-format on
+
+// Adaptor for strtoull()/strtoll().
+// Flatbuffers accepts numbers with any count of leading zeros (-009 is -9),
+// while strtoll with base=0 interprets first leading zero as octal prefix.
+// In future, it is possible to add prefixed 0b0101.
+// 1) Checks errno code for overflow condition (out of range).
+// 2) If base <= 0, function try to detect base of number by prefix.
+//
+// Return value (like strtoull and strtoll, but reject partial result):
+// - If successful, an integer value corresponding to the str is returned.
+// - If full string conversion can't be performed, 0 is returned.
+// - If the converted value falls out of range of corresponding return type, a
+// range error occurs. In this case value MAX(T)/MIN(T) is returned.
+template<typename T>
+inline bool StringToIntegerImpl(T *val, const char *const str,
+ const int base = 0,
+ const bool check_errno = true) {
+ // T is int64_t or uint64_T
+ FLATBUFFERS_ASSERT(str);
+ if (base <= 0) {
+ auto s = str;
+ while (*s && !is_digit(*s)) s++;
+ if (s[0] == '0' && is_alpha_char(s[1], 'X'))
+ return StringToIntegerImpl(val, str, 16, check_errno);
+ // if a prefix not match, try base=10
+ return StringToIntegerImpl(val, str, 10, check_errno);
+ } else {
+ if (check_errno) errno = 0; // clear thread-local errno
+ auto endptr = str;
+ strtoval_impl(val, str, const_cast<char **>(&endptr), base);
+ if ((*endptr != '\0') || (endptr == str)) {
+ *val = 0; // erase partial result
+ return false; // invalid string
+ }
+ // errno is out-of-range, return MAX/MIN
+ if (check_errno && errno) return false;
+ return true;
+ }
+}
+
+template<typename T>
+inline bool StringToFloatImpl(T *val, const char *const str) {
+ // Type T must be either float or double.
+ FLATBUFFERS_ASSERT(str && val);
+ auto end = str;
+ strtoval_impl(val, str, const_cast<char **>(&end));
+ auto done = (end != str) && (*end == '\0');
+ if (!done) *val = 0; // erase partial result
+ return done;
+}
+
+// Convert a string to an instance of T.
+// Return value (matched with StringToInteger64Impl and strtod):
+// - If successful, a numeric value corresponding to the str is returned.
+// - If full string conversion can't be performed, 0 is returned.
+// - If the converted value falls out of range of corresponding return type, a
+// range error occurs. In this case value MAX(T)/MIN(T) is returned.
+template<typename T> inline bool StringToNumber(const char *s, T *val) {
+ // Assert on `unsigned long` and `signed long` on LP64.
+ // If it is necessary, it could be solved with flatbuffers::enable_if<B,T>.
+ static_assert(sizeof(T) < sizeof(int64_t), "unexpected type T");
+ FLATBUFFERS_ASSERT(s && val);
+ int64_t i64;
+ // The errno check isn't needed, will return MAX/MIN on overflow.
+ if (StringToIntegerImpl(&i64, s, 0, false)) {
+ const int64_t max = (flatbuffers::numeric_limits<T>::max)();
+ const int64_t min = flatbuffers::numeric_limits<T>::lowest();
+ if (i64 > max) {
+ *val = static_cast<T>(max);
+ return false;
+ }
+ if (i64 < min) {
+ // For unsigned types return max to distinguish from
+ // "no conversion can be performed" when 0 is returned.
+ *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
+ return false;
+ }
+ *val = static_cast<T>(i64);
+ return true;
+ }
+ *val = 0;
+ return false;
+}
+
+template<> inline bool StringToNumber<int64_t>(const char *str, int64_t *val) {
+ return StringToIntegerImpl(val, str);
+}
+
+template<>
+inline bool StringToNumber<uint64_t>(const char *str, uint64_t *val) {
+ if (!StringToIntegerImpl(val, str)) return false;
+ // The strtoull accepts negative numbers:
+ // If the minus sign was part of the input sequence, the numeric value
+ // calculated from the sequence of digits is negated as if by unary minus
+ // in the result type, which applies unsigned integer wraparound rules.
+ // Fix this behaviour (except -0).
+ if (*val) {
+ auto s = str;
+ while (*s && !is_digit(*s)) s++;
+ s = (s > str) ? (s - 1) : s; // step back to one symbol
+ if (*s == '-') {
+ // For unsigned types return the max to distinguish from
+ // "no conversion can be performed".
+ *val = (flatbuffers::numeric_limits<uint64_t>::max)();
+ return false;
+ }
+ }
+ return true;
+}
+
+template<> inline bool StringToNumber(const char *s, float *val) {
+ return StringToFloatImpl(val, s);
+}
+
+template<> inline bool StringToNumber(const char *s, double *val) {
+ return StringToFloatImpl(val, s);
+}
+
+inline int64_t StringToInt(const char *s, int base = 10) {
+ int64_t val;
+ return StringToIntegerImpl(&val, s, base) ? val : 0;
+}
+
+inline uint64_t StringToUInt(const char *s, int base = 10) {
+ uint64_t val;
+ return StringToIntegerImpl(&val, s, base) ? val : 0;
+}
+
+typedef bool (*LoadFileFunction)(const char *filename, bool binary,
+ std::string *dest);
+typedef bool (*FileExistsFunction)(const char *filename);
+
+LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
+
+FileExistsFunction SetFileExistsFunction(
+ FileExistsFunction file_exists_function);
+
+// Check if file "name" exists.
+bool FileExists(const char *name);
+
+// Check if "name" exists and it is also a directory.
+bool DirExists(const char *name);
+
+// Load file "name" into "buf" returning true if successful
+// false otherwise. If "binary" is false data is read
+// using ifstream's text mode, otherwise data is read with
+// no transcoding.
+bool LoadFile(const char *name, bool binary, std::string *buf);
+
+// Save data "buf" of length "len" bytes into a file
+// "name" returning true if successful, false otherwise.
+// If "binary" is false data is written using ifstream's
+// text mode, otherwise data is written with no
+// transcoding.
+bool SaveFile(const char *name, const char *buf, size_t len, bool binary);
+
+// Save data "buf" into file "name" returning true if
+// successful, false otherwise. If "binary" is false
+// data is written using ifstream's text mode, otherwise
+// data is written with no transcoding.
+inline bool SaveFile(const char *name, const std::string &buf, bool binary) {
+ return SaveFile(name, buf.c_str(), buf.size(), binary);
+}
+
+// Functionality for minimalistic portable path handling.
+
+// The functions below behave correctly regardless of whether posix ('/') or
+// Windows ('/' or '\\') separators are used.
+
+// Any new separators inserted are always posix.
+FLATBUFFERS_CONSTEXPR char kPathSeparator = '/';
+
+// Returns the path with the extension, if any, removed.
+std::string StripExtension(const std::string &filepath);
+
+// Returns the extension, if any.
+std::string GetExtension(const std::string &filepath);
+
+// Return the last component of the path, after the last separator.
+std::string StripPath(const std::string &filepath);
+
+// Strip the last component of the path + separator.
+std::string StripFileName(const std::string &filepath);
+
+// Concatenates a path with a filename, regardless of whether the path
+// ends in a separator or not.
+std::string ConCatPathFileName(const std::string &path,
+ const std::string &filename);
+
+// Replaces any '\\' separators with '/'
+std::string PosixPath(const char *path);
+
+// This function ensure a directory exists, by recursively
+// creating dirs for any parts of the path that don't exist yet.
+void EnsureDirExists(const std::string &filepath);
+
+// 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);
+
+// To and from UTF-8 unicode conversion functions
+
+// Convert a unicode code point into a UTF-8 representation by appending it
+// to a string. Returns the number of bytes generated.
+inline int ToUTF8(uint32_t ucc, std::string *out) {
+ FLATBUFFERS_ASSERT(!(ucc & 0x80000000)); // Top bit can't be set.
+ // 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8
+ for (int i = 0; i < 6; i++) {
+ // Max bits this encoding can represent.
+ uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i);
+ if (ucc < (1u << max_bits)) { // does it fit?
+ // Remaining bits not encoded in the first byte, store 6 bits each
+ uint32_t remain_bits = i * 6;
+ // Store first byte:
+ (*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
+ (ucc >> remain_bits));
+ // Store remaining bytes:
+ for (int j = i - 1; j >= 0; j--) {
+ (*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
+ }
+ return i + 1; // Return the number of bytes added.
+ }
+ }
+ FLATBUFFERS_ASSERT(0); // Impossible to arrive here.
+ return -1;
+}
+
+// Converts whatever prefix of the incoming string corresponds to a valid
+// UTF-8 sequence into a unicode code. The incoming pointer will have been
+// advanced past all bytes parsed.
+// returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in
+// this case).
+inline int FromUTF8(const char **in) {
+ int len = 0;
+ // Count leading 1 bits.
+ for (int mask = 0x80; mask >= 0x04; mask >>= 1) {
+ if (**in & mask) {
+ len++;
+ } else {
+ break;
+ }
+ }
+ if ((static_cast<unsigned char>(**in) << len) & 0x80)
+ return -1; // Bit after leading 1's must be 0.
+ if (!len) return *(*in)++;
+ // UTF-8 encoded values with a length are between 2 and 4 bytes.
+ if (len < 2 || len > 4) { return -1; }
+ // Grab initial bits of the code.
+ int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
+ for (int i = 0; i < len - 1; i++) {
+ if ((**in & 0xC0) != 0x80) return -1; // Upper bits must 1 0.
+ ucc <<= 6;
+ ucc |= *(*in)++ & 0x3F; // Grab 6 more bits of the code.
+ }
+ // UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
+ // UTF-16 surrogate pairs).
+ if (ucc >= 0xD800 && ucc <= 0xDFFF) { return -1; }
+ // UTF-8 must represent code points in their shortest possible encoding.
+ switch (len) {
+ case 2:
+ // Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
+ if (ucc < 0x0080 || ucc > 0x07FF) { return -1; }
+ break;
+ case 3:
+ // Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
+ if (ucc < 0x0800 || ucc > 0xFFFF) { return -1; }
+ break;
+ case 4:
+ // Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
+ if (ucc < 0x10000 || ucc > 0x10FFFF) { return -1; }
+ break;
+ }
+ return ucc;
+}
+
+#ifndef FLATBUFFERS_PREFER_PRINTF
+// Wraps a string to a maximum length, inserting new lines where necessary. Any
+// existing whitespace will be collapsed down to a single space. A prefix or
+// suffix can be provided, which will be inserted before or after a wrapped
+// line, respectively.
+inline std::string WordWrap(const std::string in, size_t max_length,
+ const std::string wrapped_line_prefix,
+ const std::string wrapped_line_suffix) {
+ std::istringstream in_stream(in);
+ std::string wrapped, line, word;
+
+ in_stream >> word;
+ line = word;
+
+ while (in_stream >> word) {
+ if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) <
+ max_length) {
+ line += " " + word;
+ } else {
+ wrapped += line + wrapped_line_suffix + "\n";
+ line = wrapped_line_prefix + word;
+ }
+ }
+ wrapped += line;
+
+ return wrapped;
+}
+#endif // !FLATBUFFERS_PREFER_PRINTF
+
+inline bool EscapeString(const char *s, size_t length, std::string *_text,
+ bool allow_non_utf8, bool natural_utf8) {
+ std::string &text = *_text;
+ text += "\"";
+ for (uoffset_t i = 0; i < length; i++) {
+ char c = s[i];
+ switch (c) {
+ case '\n': text += "\\n"; break;
+ case '\t': text += "\\t"; break;
+ case '\r': text += "\\r"; break;
+ case '\b': text += "\\b"; break;
+ case '\f': text += "\\f"; break;
+ case '\"': text += "\\\""; break;
+ case '\\': text += "\\\\"; break;
+ default:
+ if (c >= ' ' && c <= '~') {
+ text += c;
+ } else {
+ // Not printable ASCII data. Let's see if it's valid UTF-8 first:
+ const char *utf8 = s + i;
+ int ucc = FromUTF8(&utf8);
+ if (ucc < 0) {
+ if (allow_non_utf8) {
+ text += "\\x";
+ text += IntToStringHex(static_cast<uint8_t>(c), 2);
+ } else {
+ // There are two cases here:
+ //
+ // 1) We reached here by parsing an IDL file. In that case,
+ // we previously checked for non-UTF-8, so we shouldn't reach
+ // here.
+ //
+ // 2) We reached here by someone calling GenerateText()
+ // on a previously-serialized flatbuffer. The data might have
+ // non-UTF-8 Strings, or might be corrupt.
+ //
+ // In both cases, we have to give up and inform the caller
+ // they have no JSON.
+ return false;
+ }
+ } else {
+ if (natural_utf8) {
+ // utf8 points to past all utf-8 bytes parsed
+ text.append(s + i, static_cast<size_t>(utf8 - s - i));
+ } else if (ucc <= 0xFFFF) {
+ // Parses as Unicode within JSON's \uXXXX range, so use that.
+ text += "\\u";
+ text += IntToStringHex(ucc, 4);
+ } else if (ucc <= 0x10FFFF) {
+ // Encode Unicode SMP values to a surrogate pair using two \u
+ // escapes.
+ uint32_t base = ucc - 0x10000;
+ auto high_surrogate = (base >> 10) + 0xD800;
+ auto low_surrogate = (base & 0x03FF) + 0xDC00;
+ text += "\\u";
+ text += IntToStringHex(high_surrogate, 4);
+ text += "\\u";
+ text += IntToStringHex(low_surrogate, 4);
+ }
+ // Skip past characters recognized.
+ i = static_cast<uoffset_t>(utf8 - s - 1);
+ }
+ }
+ break;
+ }
+ }
+ text += "\"";
+ return true;
+}
+
+inline std::string BufferToHexText(const void *buffer, size_t buffer_size,
+ size_t max_length,
+ const std::string &wrapped_line_prefix,
+ const std::string &wrapped_line_suffix) {
+ std::string text = wrapped_line_prefix;
+ size_t start_offset = 0;
+ const char *s = reinterpret_cast<const char *>(buffer);
+ for (size_t i = 0; s && i < buffer_size; i++) {
+ // Last iteration or do we have more?
+ bool have_more = i + 1 < buffer_size;
+ text += "0x";
+ text += IntToStringHex(static_cast<uint8_t>(s[i]), 2);
+ if (have_more) { text += ','; }
+ // If we have more to process and we reached max_length
+ if (have_more &&
+ text.size() + wrapped_line_suffix.size() >= start_offset + max_length) {
+ text += wrapped_line_suffix;
+ text += '\n';
+ start_offset = text.size();
+ text += wrapped_line_prefix;
+ }
+ }
+ text += wrapped_line_suffix;
+ return text;
+}
+
+// Remove paired quotes in a string: "text"|'text' -> text.
+std::string RemoveStringQuotes(const std::string &s);
+
+// Change th global C-locale to locale with name <locale_name>.
+// Returns an actual locale name in <_value>, useful if locale_name is "" or
+// null.
+bool SetGlobalTestLocale(const char *locale_name,
+ std::string *_value = nullptr);
+
+// Read (or test) a value of environment variable.
+bool ReadEnvironmentVariable(const char *var_name,
+ std::string *_value = nullptr);
+
+// MSVC specific: Send all assert reports to STDOUT to prevent CI hangs.
+void SetupDefaultCRTReportMode();
+
+} // namespace flatbuffers
+
+#endif // FLATBUFFERS_UTIL_H_
diff --git a/contrib/libs/flatbuffers/samples/monster.fbs b/contrib/libs/flatbuffers/samples/monster.fbs
new file mode 100644
index 0000000000..af224512ee
--- /dev/null
+++ b/contrib/libs/flatbuffers/samples/monster.fbs
@@ -0,0 +1,33 @@
+// Example IDL file for our monster's schema.
+
+namespace MyGame.Sample;
+
+enum Color:byte { Red = 0, Green, Blue = 2 }
+
+union Equipment { Weapon } // Optionally add more tables.
+
+struct Vec3 {
+ x:float;
+ y:float;
+ z:float;
+}
+
+table Monster {
+ pos:Vec3;
+ mana:short = 150;
+ hp:short = 100;
+ name:string;
+ friendly:bool = false (deprecated);
+ inventory:[ubyte];
+ color:Color = Blue;
+ weapons:[Weapon];
+ equipped:Equipment;
+ path:[Vec3];
+}
+
+table Weapon {
+ name:string;
+ damage:short;
+}
+
+root_type Monster;
diff --git a/contrib/libs/flatbuffers/samples/sample_binary.cpp b/contrib/libs/flatbuffers/samples/sample_binary.cpp
new file mode 100644
index 0000000000..6bd1cdcf43
--- /dev/null
+++ b/contrib/libs/flatbuffers/samples/sample_binary.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2015 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.
+ */
+
+#include <contrib/libs/flatbuffers/samples/monster.fbs.h>
+
+using namespace MyGame::Sample;
+
+// Example how to use FlatBuffers to create and read binary buffers.
+
+int main(int /*argc*/, const char * /*argv*/[]) {
+ // Build up a serialized buffer algorithmically:
+ flatbuffers::FlatBufferBuilder builder;
+
+ // First, lets serialize some weapons for the Monster: A 'sword' and an 'axe'.
+ auto weapon_one_name = builder.CreateString("Sword");
+ short weapon_one_damage = 3;
+
+ auto weapon_two_name = builder.CreateString("Axe");
+ short weapon_two_damage = 5;
+
+ // Use the `CreateWeapon` shortcut to create Weapons with all fields set.
+ auto sword = CreateWeapon(builder, weapon_one_name, weapon_one_damage);
+ auto axe = CreateWeapon(builder, weapon_two_name, weapon_two_damage);
+
+ // Create a FlatBuffer's `vector` from the `std::vector`.
+ std::vector<flatbuffers::Offset<Weapon>> weapons_vector;
+ weapons_vector.push_back(sword);
+ weapons_vector.push_back(axe);
+ auto weapons = builder.CreateVector(weapons_vector);
+
+ // Second, serialize the rest of the objects needed by the Monster.
+ auto position = Vec3(1.0f, 2.0f, 3.0f);
+
+ auto name = builder.CreateString("MyMonster");
+
+ unsigned char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ auto inventory = builder.CreateVector(inv_data, 10);
+
+ // Shortcut for creating monster with all fields set:
+ auto orc = CreateMonster(builder, &position, 150, 80, name, inventory,
+ Color_Red, weapons, Equipment_Weapon, axe.Union());
+
+ builder.Finish(orc); // Serialize the root of the object.
+
+ // We now have a FlatBuffer we can store on disk or send over a network.
+
+ // ** file/network code goes here :) **
+ // access builder.GetBufferPointer() for builder.GetSize() bytes
+
+ // Instead, we're going to access it right away (as if we just received it).
+
+ // Get access to the root:
+ auto monster = GetMonster(builder.GetBufferPointer());
+
+ // Get and test some scalar types from the FlatBuffer.
+ assert(monster->hp() == 80);
+ assert(monster->mana() == 150); // default
+ assert(monster->name()->str() == "MyMonster");
+
+ // Get and test a field of the FlatBuffer's `struct`.
+ auto pos = monster->pos();
+ assert(pos);
+ assert(pos->z() == 3.0f);
+ (void)pos;
+
+ // Get a test an element from the `inventory` FlatBuffer's `vector`.
+ auto inv = monster->inventory();
+ assert(inv);
+ assert(inv->Get(9) == 9);
+ (void)inv;
+
+ // Get and test the `weapons` FlatBuffers's `vector`.
+ std::string expected_weapon_names[] = { "Sword", "Axe" };
+ short expected_weapon_damages[] = { 3, 5 };
+ auto weps = monster->weapons();
+ for (unsigned int i = 0; i < weps->size(); i++) {
+ assert(weps->Get(i)->name()->str() == expected_weapon_names[i]);
+ assert(weps->Get(i)->damage() == expected_weapon_damages[i]);
+ }
+ (void)expected_weapon_names;
+ (void)expected_weapon_damages;
+
+ // Get and test the `Equipment` union (`equipped` field).
+ assert(monster->equipped_type() == Equipment_Weapon);
+ auto equipped = static_cast<const Weapon *>(monster->equipped());
+ assert(equipped->name()->str() == "Axe");
+ assert(equipped->damage() == 5);
+ (void)equipped;
+
+ printf("The FlatBuffer was successfully created and verified!\n");
+}
diff --git a/contrib/libs/flatbuffers/samples/ya.make b/contrib/libs/flatbuffers/samples/ya.make
new file mode 100644
index 0000000000..7855f8f461
--- /dev/null
+++ b/contrib/libs/flatbuffers/samples/ya.make
@@ -0,0 +1,18 @@
+PROGRAM()
+
+LICENSE(Apache-2.0)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+NO_UTIL()
+
+SRCS(
+ monster.fbs
+ sample_binary.cpp
+)
+
+PEERDIR(
+ contrib/libs/flatbuffers
+)
+
+END()
diff --git a/contrib/libs/flatbuffers/src/code_generators.cpp b/contrib/libs/flatbuffers/src/code_generators.cpp
new file mode 100644
index 0000000000..745406ba95
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/code_generators.cpp
@@ -0,0 +1,395 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#include "flatbuffers/code_generators.h"
+
+#include <assert.h>
+
+#include <cmath>
+
+#include "flatbuffers/base.h"
+#include "flatbuffers/util.h"
+
+#if defined(_MSC_VER)
+# pragma warning(push)
+# pragma warning(disable : 4127) // C4127: conditional expression is constant
+#endif
+
+namespace flatbuffers {
+
+void CodeWriter::operator+=(std::string text) {
+ if (!ignore_ident_ && !text.empty()) AppendIdent(stream_);
+
+ while (true) {
+ auto begin = text.find("{{");
+ if (begin == std::string::npos) { break; }
+
+ auto end = text.find("}}");
+ if (end == std::string::npos || end < begin) { break; }
+
+ // Write all the text before the first {{ into the stream.
+ stream_.write(text.c_str(), begin);
+
+ // The key is between the {{ and }}.
+ const std::string key = text.substr(begin + 2, end - begin - 2);
+
+ // Find the value associated with the key. If it exists, write the
+ // value into the stream, otherwise write the key itself into the stream.
+ auto iter = value_map_.find(key);
+ if (iter != value_map_.end()) {
+ const std::string &value = iter->second;
+ stream_ << value;
+ } else {
+ FLATBUFFERS_ASSERT(false && "could not find key");
+ stream_ << key;
+ }
+
+ // Update the text to everything after the }}.
+ text = text.substr(end + 2);
+ }
+ if (!text.empty() && string_back(text) == '\\') {
+ text.pop_back();
+ ignore_ident_ = true;
+ stream_ << text;
+ } else {
+ ignore_ident_ = false;
+ stream_ << text << std::endl;
+ }
+}
+
+void CodeWriter::AppendIdent(std::stringstream &stream) {
+ int lvl = cur_ident_lvl_;
+ while (lvl--) {
+ stream.write(pad_.c_str(), static_cast<std::streamsize>(pad_.size()));
+ }
+}
+
+const char *BaseGenerator::FlatBuffersGeneratedWarning() {
+ return "automatically generated by the FlatBuffers compiler,"
+ " do not modify";
+}
+
+std::string BaseGenerator::NamespaceDir(const Parser &parser,
+ const std::string &path,
+ const Namespace &ns,
+ const bool dasherize) {
+ EnsureDirExists(path);
+ if (parser.opts.one_file) return path;
+ std::string namespace_dir = path; // Either empty or ends in separator.
+ auto &namespaces = ns.components;
+ for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
+ namespace_dir += !dasherize ? *it : ToDasherizedCase(*it);
+ namespace_dir += kPathSeparator;
+ EnsureDirExists(namespace_dir);
+ }
+ return namespace_dir;
+}
+
+std::string BaseGenerator::NamespaceDir(const Namespace &ns,
+ const bool dasherize) const {
+ return BaseGenerator::NamespaceDir(parser_, path_, ns, dasherize);
+}
+
+std::string BaseGenerator::ToDasherizedCase(const std::string pascal_case) {
+ std::string dasherized_case;
+ char p = 0;
+ for (size_t i = 0; i < pascal_case.length(); i++) {
+ char const &c = pascal_case[i];
+ if (is_alpha_upper(c)) {
+ if (i > 0 && p != kPathSeparator) dasherized_case += "-";
+ dasherized_case += CharToLower(c);
+ } else {
+ dasherized_case += c;
+ }
+ p = c;
+ }
+ return dasherized_case;
+}
+
+std::string BaseGenerator::FullNamespace(const char *separator,
+ const Namespace &ns) {
+ std::string namespace_name;
+ auto &namespaces = ns.components;
+ for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
+ if (namespace_name.length()) namespace_name += separator;
+ namespace_name += *it;
+ }
+ return namespace_name;
+}
+
+std::string BaseGenerator::LastNamespacePart(const Namespace &ns) {
+ if (!ns.components.empty())
+ return ns.components.back();
+ else
+ return std::string("");
+}
+
+// Ensure that a type is prefixed with its namespace.
+std::string BaseGenerator::WrapInNameSpace(const Namespace *ns,
+ const std::string &name) const {
+ std::string qualified_name = qualifying_start_;
+ for (auto it = ns->components.begin(); it != ns->components.end(); ++it)
+ qualified_name += *it + qualifying_separator_;
+ return qualified_name + name;
+}
+
+std::string BaseGenerator::WrapInNameSpace(const Definition &def) const {
+ return WrapInNameSpace(def.defined_namespace, def.name);
+}
+
+std::string BaseGenerator::GetNameSpace(const Definition &def) const {
+ const Namespace *ns = def.defined_namespace;
+ if (CurrentNameSpace() == ns) return "";
+ std::string qualified_name = qualifying_start_;
+ for (auto it = ns->components.begin(); it != ns->components.end(); ++it) {
+ qualified_name += *it;
+ if ((it + 1) != ns->components.end()) {
+ qualified_name += qualifying_separator_;
+ }
+ }
+
+ return qualified_name;
+}
+
+std::string BaseGenerator::GeneratedFileName(const std::string &path,
+ const std::string &file_name,
+ const IDLOptions &options) const {
+ return path + file_name + options.filename_suffix + "." +
+ (options.filename_extension.empty() ? default_extension_
+ : options.filename_extension);
+}
+
+// Generate a documentation comment, if available.
+void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
+ const CommentConfig *config, const char *prefix) {
+ if (dc.begin() == dc.end()) {
+ // Don't output empty comment blocks with 0 lines of comment content.
+ return;
+ }
+
+ std::string &code = *code_ptr;
+ if (config != nullptr && config->first_line != nullptr) {
+ code += std::string(prefix) + std::string(config->first_line) + "\n";
+ }
+ std::string line_prefix =
+ std::string(prefix) +
+ ((config != nullptr && config->content_line_prefix != nullptr)
+ ? config->content_line_prefix
+ : "///");
+ for (auto it = dc.begin(); it != dc.end(); ++it) {
+ code += line_prefix + *it + "\n";
+ }
+ if (config != nullptr && config->last_line != nullptr) {
+ code += std::string(prefix) + std::string(config->last_line) + "\n";
+ }
+}
+
+template<typename T>
+std::string FloatConstantGenerator::GenFloatConstantImpl(
+ const FieldDef &field) const {
+ const auto &constant = field.value.constant;
+ T v;
+ auto done = StringToNumber(constant.c_str(), &v);
+ FLATBUFFERS_ASSERT(done);
+ if (done) {
+#if (!defined(_MSC_VER) || (_MSC_VER >= 1800))
+ if (std::isnan(v)) return NaN(v);
+ if (std::isinf(v)) return Inf(v);
+#endif
+ return Value(v, constant);
+ }
+ return "#"; // compile time error
+}
+
+std::string FloatConstantGenerator::GenFloatConstant(
+ const FieldDef &field) const {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_FLOAT: return GenFloatConstantImpl<float>(field);
+ case BASE_TYPE_DOUBLE: return GenFloatConstantImpl<double>(field);
+ default: {
+ FLATBUFFERS_ASSERT(false);
+ return "INVALID_BASE_TYPE";
+ }
+ };
+}
+
+TypedFloatConstantGenerator::TypedFloatConstantGenerator(
+ const char *double_prefix, const char *single_prefix,
+ const char *nan_number, const char *pos_inf_number,
+ const char *neg_inf_number)
+ : double_prefix_(double_prefix),
+ single_prefix_(single_prefix),
+ nan_number_(nan_number),
+ pos_inf_number_(pos_inf_number),
+ neg_inf_number_(neg_inf_number) {}
+
+std::string TypedFloatConstantGenerator::MakeNaN(
+ const std::string &prefix) const {
+ return prefix + nan_number_;
+}
+std::string TypedFloatConstantGenerator::MakeInf(
+ bool neg, const std::string &prefix) const {
+ if (neg)
+ return !neg_inf_number_.empty() ? (prefix + neg_inf_number_)
+ : ("-" + prefix + pos_inf_number_);
+ else
+ return prefix + pos_inf_number_;
+}
+
+std::string TypedFloatConstantGenerator::Value(double v,
+ const std::string &src) const {
+ (void)v;
+ return src;
+}
+
+std::string TypedFloatConstantGenerator::Inf(double v) const {
+ return MakeInf(v < 0, double_prefix_);
+}
+
+std::string TypedFloatConstantGenerator::NaN(double v) const {
+ (void)v;
+ return MakeNaN(double_prefix_);
+}
+
+std::string TypedFloatConstantGenerator::Value(float v,
+ const std::string &src) const {
+ (void)v;
+ return src + "f";
+}
+
+std::string TypedFloatConstantGenerator::Inf(float v) const {
+ return MakeInf(v < 0, single_prefix_);
+}
+
+std::string TypedFloatConstantGenerator::NaN(float v) const {
+ (void)v;
+ return MakeNaN(single_prefix_);
+}
+
+SimpleFloatConstantGenerator::SimpleFloatConstantGenerator(
+ const char *nan_number, const char *pos_inf_number,
+ const char *neg_inf_number)
+ : nan_number_(nan_number),
+ pos_inf_number_(pos_inf_number),
+ neg_inf_number_(neg_inf_number) {}
+
+std::string SimpleFloatConstantGenerator::Value(double v,
+ const std::string &src) const {
+ (void)v;
+ return src;
+}
+
+std::string SimpleFloatConstantGenerator::Inf(double v) const {
+ return (v < 0) ? neg_inf_number_ : pos_inf_number_;
+}
+
+std::string SimpleFloatConstantGenerator::NaN(double v) const {
+ (void)v;
+ return nan_number_;
+}
+
+std::string SimpleFloatConstantGenerator::Value(float v,
+ const std::string &src) const {
+ return this->Value(static_cast<double>(v), src);
+}
+
+std::string SimpleFloatConstantGenerator::Inf(float v) const {
+ return this->Inf(static_cast<double>(v));
+}
+
+std::string SimpleFloatConstantGenerator::NaN(float v) const {
+ return this->NaN(static_cast<double>(v));
+}
+
+std::string JavaCSharpMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ FLATBUFFERS_ASSERT(parser.opts.lang == IDLOptions::kJava ||
+ parser.opts.lang == IDLOptions::kCSharp);
+
+ std::string file_extension =
+ (parser.opts.lang == IDLOptions::kJava) ? ".java" : ".cs";
+
+ std::string make_rule;
+
+ for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end();
+ ++it) {
+ auto &enum_def = **it;
+ if (!make_rule.empty()) make_rule += " ";
+ std::string directory =
+ BaseGenerator::NamespaceDir(parser, path, *enum_def.defined_namespace);
+ make_rule += directory + enum_def.name + file_extension;
+ }
+
+ for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
+ ++it) {
+ auto &struct_def = **it;
+ if (!make_rule.empty()) make_rule += " ";
+ std::string directory = BaseGenerator::NamespaceDir(
+ parser, path, *struct_def.defined_namespace);
+ make_rule += directory + struct_def.name + file_extension;
+ }
+
+ make_rule += ": ";
+ auto included_files = parser.GetIncludedFilesRecursive(file_name);
+ for (auto it = included_files.begin(); it != included_files.end(); ++it) {
+ make_rule += " " + *it;
+ }
+ return make_rule;
+}
+
+std::string BinaryFileName(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ auto ext = parser.file_extension_.length() ? parser.file_extension_ : "bin";
+ return path + file_name + "." + ext;
+}
+
+bool GenerateBinary(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ if (parser.opts.use_flexbuffers) {
+ auto data_vec = parser.flex_builder_.GetBuffer();
+ auto data_ptr = reinterpret_cast<char *>(data(data_vec));
+ return !parser.flex_builder_.GetSize() ||
+ flatbuffers::SaveFile(
+ BinaryFileName(parser, path, file_name).c_str(), data_ptr,
+ parser.flex_builder_.GetSize(), true);
+ }
+ return !parser.builder_.GetSize() ||
+ flatbuffers::SaveFile(
+ BinaryFileName(parser, path, file_name).c_str(),
+ reinterpret_cast<char *>(parser.builder_.GetBufferPointer()),
+ parser.builder_.GetSize(), true);
+}
+
+std::string BinaryMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ if (!parser.builder_.GetSize()) return "";
+ std::string filebase =
+ flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
+ std::string make_rule =
+ BinaryFileName(parser, path, filebase) + ": " + file_name;
+ auto included_files =
+ parser.GetIncludedFilesRecursive(parser.root_struct_def_->file);
+ for (auto it = included_files.begin(); it != included_files.end(); ++it) {
+ make_rule += " " + *it;
+ }
+ return make_rule;
+}
+
+} // namespace flatbuffers
+
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#endif
diff --git a/contrib/libs/flatbuffers/src/flatc.cpp b/contrib/libs/flatbuffers/src/flatc.cpp
new file mode 100644
index 0000000000..221b88676d
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/flatc.cpp
@@ -0,0 +1,554 @@
+/*
+ * 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.
+ */
+
+#include "flatbuffers/flatc.h"
+
+#include <list>
+
+namespace flatbuffers {
+
+const char *FLATC_VERSION() { return FLATBUFFERS_VERSION(); }
+
+void FlatCompiler::ParseFile(
+ flatbuffers::Parser &parser, const std::string &filename,
+ const std::string &contents,
+ std::vector<const char *> &include_directories) const {
+ auto local_include_directory = flatbuffers::StripFileName(filename);
+ include_directories.push_back(local_include_directory.c_str());
+ include_directories.push_back(nullptr);
+ if (!parser.Parse(contents.c_str(), &include_directories[0],
+ filename.c_str())) {
+ Error(parser.error_, false, false);
+ }
+ if (!parser.error_.empty()) { Warn(parser.error_, false); }
+ include_directories.pop_back();
+ include_directories.pop_back();
+}
+
+void FlatCompiler::LoadBinarySchema(flatbuffers::Parser &parser,
+ const std::string &filename,
+ const std::string &contents) {
+ if (!parser.Deserialize(reinterpret_cast<const uint8_t *>(contents.c_str()),
+ contents.size())) {
+ Error("failed to load binary schema: " + filename, false, false);
+ }
+}
+
+void FlatCompiler::Warn(const std::string &warn, bool show_exe_name) const {
+ params_.warn_fn(this, warn, show_exe_name);
+}
+
+void FlatCompiler::Error(const std::string &err, bool usage,
+ bool show_exe_name) const {
+ params_.error_fn(this, err, usage, show_exe_name);
+}
+
+std::string FlatCompiler::GetUsageString(const char *program_name) const {
+ std::stringstream ss;
+ ss << "Usage: " << program_name << " [OPTION]... FILE... [-- FILE...]\n";
+ for (size_t i = 0; i < params_.num_generators; ++i) {
+ const Generator &g = params_.generators[i];
+
+ std::stringstream full_name;
+ full_name << std::setw(16) << std::left << g.generator_opt_long;
+ const char *name = g.generator_opt_short ? g.generator_opt_short : " ";
+ const char *help = g.generator_help;
+
+ ss << " " << full_name.str() << " " << name << " " << help << ".\n";
+ }
+ // clang-format off
+
+ // Output width
+ // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
+ ss <<
+ " -o PATH Prefix PATH to all generated files.\n"
+ " -I PATH Search for includes in the specified path.\n"
+ " -M Print make rules for generated files.\n"
+ " --version Print the version number of flatc and exit.\n"
+ " --strict-json Strict JSON: field names must be / will be quoted,\n"
+ " no trailing commas in tables/vectors.\n"
+ " --allow-non-utf8 Pass non-UTF-8 input through parser and emit nonstandard\n"
+ " \\x escapes in JSON. (Default is to raise parse error on\n"
+ " non-UTF-8 input.)\n"
+ " --natural-utf8 Output strings with UTF-8 as human-readable strings.\n"
+ " By default, UTF-8 characters are printed as \\uXXXX escapes.\n"
+ " --defaults-json Output fields whose value is the default when\n"
+ " writing JSON\n"
+ " --unknown-json Allow fields in JSON that are not defined in the\n"
+ " schema. These fields will be discared when generating\n"
+ " binaries.\n"
+ " --no-prefix Don\'t prefix enum values with the enum type in C++.\n"
+ " --scoped-enums Use C++11 style scoped and strongly typed enums.\n"
+ " also implies --no-prefix.\n"
+ " --gen-includes (deprecated), this is the default behavior.\n"
+ " If the original behavior is required (no include\n"
+ " statements) use --no-includes.\n"
+ " --no-includes Don\'t generate include statements for included\n"
+ " schemas the generated file depends on (C++ / Python).\n"
+ " --gen-mutable Generate accessors that can mutate buffers in-place.\n"
+ " --gen-onefile Generate single output file for C# and Go.\n"
+ " --gen-name-strings Generate type name functions for C++ and Rust.\n"
+ " --gen-object-api Generate an additional object-based API.\n"
+ " --gen-compare Generate operator== for object-based API types.\n"
+ " --gen-nullable Add Clang _Nullable for C++ pointer. or @Nullable for Java\n"
+ " --java-checkerframe work Add @Pure for Java.\n"
+ " --gen-generated Add @Generated annotation for Java\n"
+ " --gen-jvmstatic Add @JvmStatic annotation for Kotlin methods\n"
+ " in companion object for interop from Java to Kotlin.\n"
+ " --gen-all Generate not just code for the current schema files,\n"
+ " but for all files it includes as well.\n"
+ " If the language uses a single file for output (by default\n"
+ " the case for C++ and JS), all code will end up in this one\n"
+ " file.\n"
+ " --cpp-include Adds an #include in generated file.\n"
+ " --cpp-ptr-type T Set object API pointer type (default std::unique_ptr).\n"
+ " --cpp-str-type T Set object API string type (default std::string).\n"
+ " T::c_str(), T::length() and T::empty() must be supported.\n"
+ " The custom type also needs to be constructible from std::string\n"
+ " (see the --cpp-str-flex-ctor option to change this behavior).\n"
+ " --cpp-str-flex-ctor Don't construct custom string types by passing std::string\n"
+ " from Flatbuffers, but (char* + length).\n"
+ " --cpp-std CPP_STD Generate a C++ code using features of selected C++ standard.\n"
+ " Supported CPP_STD values:\n"
+ " * 'c++0x' - generate code compatible with old compilers;\n"
+ " * 'c++11' - use C++11 code generator (default);\n"
+ " * 'c++17' - use C++17 features in generated code (experimental).\n"
+ " --cpp-static-reflection When using C++17, generate extra code to provide compile-time\n"
+ " (static) reflection of Flatbuffers types. Requires --cpp-std\n"
+ " to be \"c++17\" or higher.\n"
+ " --object-prefix Customise class prefix for C++ object-based API.\n"
+ " --object-suffix Customise class suffix for C++ object-based API.\n"
+ " Default value is \"T\".\n"
+ " --go-namespace Generate the overriding namespace in Golang.\n"
+ " --go-import Generate the overriding import for flatbuffers in Golang\n"
+ " (default is \"github.com/google/flatbuffers/go\").\n"
+ " --raw-binary Allow binaries without file_identifier to be read.\n"
+ " This may crash flatc given a mismatched schema.\n"
+ " --size-prefixed Input binaries are size prefixed buffers.\n"
+ " --proto Input is a .proto, translate to .fbs.\n"
+ " --proto-namespace-suffix Add this namespace to any flatbuffers generated\n"
+ " SUFFIX from protobufs.\n"
+ " --oneof-union Translate .proto oneofs to flatbuffer unions.\n"
+ " --grpc Generate GRPC interfaces for the specified languages.\n"
+ " --schema Serialize schemas instead of JSON (use with -b).\n"
+ " --bfbs-comments Add doc comments to the binary schema files.\n"
+ " --bfbs-builtins Add builtin attributes to the binary schema files.\n"
+ " --bfbs-gen-embed Generate code to embed the bfbs schema to the source.\n"
+ " --conform FILE Specify a schema the following schemas should be\n"
+ " an evolution of. Gives errors if not.\n"
+ " --conform-includes Include path for the schema given with --conform PATH\n"
+ " --filename-suffix The suffix appended to the generated file names.\n"
+ " Default is '_generated'.\n"
+ " --filename-ext The extension appended to the generated file names.\n"
+ " Default is language-specific (e.g., '.h' for C++)\n"
+ " --include-prefix Prefix this path to any generated include statements.\n"
+ " PATH\n"
+ " --keep-prefix Keep original prefix of schema include statement.\n"
+ " --reflect-types Add minimal type reflection to code generation.\n"
+ " --reflect-names Add minimal type/name reflection.\n"
+ " --root-type T Select or override the default root_type\n"
+ " --require-explicit-ids When parsing schemas, require explicit ids (id: x).\n"
+ " --force-defaults Emit default values in binary output from JSON\n"
+ " --force-empty When serializing from object API representation,\n"
+ " force strings and vectors to empty rather than null.\n"
+ " --force-empty-vectors When serializing from object API representation,\n"
+ " force vectors to empty rather than null.\n"
+ " --flexbuffers Used with \"binary\" and \"json\" options, it generates\n"
+ " data using schema-less FlexBuffers.\n"
+ " --no-warnings Inhibit all warning messages.\n"
+ "FILEs may be schemas (must end in .fbs), binary schemas (must end in .bfbs),\n"
+ "or JSON files (conforming to preceding schema). FILEs after the -- must be\n"
+ "binary flatbuffer format files.\n"
+ "Output files are named using the base file name of the input,\n"
+ "and written to the current directory or the path given by -o.\n"
+ "example: " << program_name << " -c -b schema1.fbs schema2.fbs data.json\n";
+ // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
+ // clang-format on
+ return ss.str();
+}
+
+int FlatCompiler::Compile(int argc, const char **argv) {
+ if (params_.generators == nullptr || params_.num_generators == 0) {
+ return 0;
+ }
+
+ flatbuffers::IDLOptions opts;
+ std::string output_path;
+
+ bool any_generator = false;
+ bool print_make_rules = false;
+ bool raw_binary = false;
+ bool schema_binary = false;
+ bool grpc_enabled = false;
+ std::vector<std::string> filenames;
+ std::list<std::string> include_directories_storage;
+ std::vector<const char *> include_directories;
+ std::vector<const char *> conform_include_directories;
+ std::vector<bool> generator_enabled(params_.num_generators, false);
+ size_t binary_files_from = std::numeric_limits<size_t>::max();
+ std::string conform_to_schema;
+
+ for (int argi = 0; argi < argc; argi++) {
+ std::string arg = argv[argi];
+ if (arg[0] == '-') {
+ if (filenames.size() && arg[1] != '-')
+ Error("invalid option location: " + arg, true);
+ if (arg == "-o") {
+ if (++argi >= argc) Error("missing path following: " + arg, true);
+ output_path = flatbuffers::ConCatPathFileName(
+ flatbuffers::PosixPath(argv[argi]), "");
+ } else if (arg == "-I") {
+ if (++argi >= argc) Error("missing path following: " + arg, true);
+ include_directories_storage.push_back(
+ flatbuffers::PosixPath(argv[argi]));
+ include_directories.push_back(
+ include_directories_storage.back().c_str());
+ } else if (arg == "--conform") {
+ if (++argi >= argc) Error("missing path following: " + arg, true);
+ conform_to_schema = flatbuffers::PosixPath(argv[argi]);
+ } else if (arg == "--conform-includes") {
+ if (++argi >= argc) Error("missing path following: " + arg, true);
+ include_directories_storage.push_back(
+ flatbuffers::PosixPath(argv[argi]));
+ conform_include_directories.push_back(
+ include_directories_storage.back().c_str());
+ } else if (arg == "--include-prefix") {
+ if (++argi >= argc) Error("missing path following: " + arg, true);
+ opts.include_prefix = flatbuffers::ConCatPathFileName(
+ flatbuffers::PosixPath(argv[argi]), "");
+ } else if (arg == "--keep-prefix") {
+ opts.keep_include_path = true;
+ } else if (arg == "--strict-json") {
+ opts.strict_json = true;
+ } else if (arg == "--allow-non-utf8") {
+ opts.allow_non_utf8 = true;
+ } else if (arg == "--natural-utf8") {
+ opts.natural_utf8 = true;
+ } else if (arg == "--go-namespace") {
+ if (++argi >= argc) Error("missing golang namespace" + arg, true);
+ opts.go_namespace = argv[argi];
+ } else if (arg == "--go-import") {
+ if (++argi >= argc) Error("missing golang import" + arg, true);
+ opts.go_import = argv[argi];
+ } else if (arg == "--defaults-json") {
+ opts.output_default_scalars_in_json = true;
+ } else if (arg == "--unknown-json") {
+ opts.skip_unexpected_fields_in_json = true;
+ } else if (arg == "--no-prefix") {
+ opts.prefixed_enums = false;
+ } else if (arg == "--scoped-enums") {
+ opts.prefixed_enums = false;
+ opts.scoped_enums = true;
+ } else if (arg == "--no-union-value-namespacing") {
+ opts.union_value_namespacing = false;
+ } else if (arg == "--gen-mutable") {
+ opts.mutable_buffer = true;
+ } else if (arg == "--gen-name-strings") {
+ opts.generate_name_strings = true;
+ } else if (arg == "--gen-object-api") {
+ opts.generate_object_based_api = true;
+ } else if (arg == "--gen-compare") {
+ opts.gen_compare = true;
+ } else if (arg == "--cpp-include") {
+ if (++argi >= argc) Error("missing include following: " + arg, true);
+ opts.cpp_includes.push_back(argv[argi]);
+ } else if (arg == "--cpp-ptr-type") {
+ if (++argi >= argc) Error("missing type following: " + arg, true);
+ opts.cpp_object_api_pointer_type = argv[argi];
+ } else if (arg == "--cpp-str-type") {
+ if (++argi >= argc) Error("missing type following: " + arg, true);
+ opts.cpp_object_api_string_type = argv[argi];
+ } else if (arg == "--cpp-str-flex-ctor") {
+ opts.cpp_object_api_string_flexible_constructor = true;
+ } else if (arg == "--no-cpp-direct-copy") {
+ opts.cpp_direct_copy = false;
+ } else if (arg == "--gen-nullable") {
+ opts.gen_nullable = true;
+ } else if (arg == "--java-checkerframework") {
+ opts.java_checkerframework = true;
+ } else if (arg == "--gen-generated") {
+ opts.gen_generated = true;
+ } else if (arg == "--object-prefix") {
+ if (++argi >= argc) Error("missing prefix following: " + arg, true);
+ opts.object_prefix = argv[argi];
+ } else if (arg == "--object-suffix") {
+ if (++argi >= argc) Error("missing suffix following: " + arg, true);
+ opts.object_suffix = argv[argi];
+ } else if (arg == "--gen-all") {
+ opts.generate_all = true;
+ opts.include_dependence_headers = false;
+ } else if (arg == "--gen-includes") {
+ // Deprecated, remove this option some time in the future.
+ Warn("warning: --gen-includes is deprecated (it is now default)\n");
+ } else if (arg == "--no-includes") {
+ opts.include_dependence_headers = false;
+ } else if (arg == "--gen-onefile") {
+ opts.one_file = true;
+ } else if (arg == "--raw-binary") {
+ raw_binary = true;
+ } else if (arg == "--size-prefixed") {
+ opts.size_prefixed = true;
+ } else if (arg == "--") { // Separator between text and binary inputs.
+ binary_files_from = filenames.size();
+ } else if (arg == "--proto") {
+ opts.proto_mode = true;
+ } else if (arg == "--proto-namespace-suffix") {
+ if (++argi >= argc) Error("missing namespace suffix" + arg, true);
+ opts.proto_namespace_suffix = argv[argi];
+ } else if (arg == "--oneof-union") {
+ opts.proto_oneof_union = true;
+ } else if (arg == "--schema") {
+ schema_binary = true;
+ } else if (arg == "-M") {
+ print_make_rules = true;
+ } else if (arg == "--version") {
+ printf("flatc version %s\n", FLATC_VERSION());
+ exit(0);
+ } else if (arg == "--grpc") {
+ grpc_enabled = true;
+ } else if (arg == "--bfbs-comments") {
+ opts.binary_schema_comments = true;
+ } else if (arg == "--bfbs-builtins") {
+ opts.binary_schema_builtins = true;
+ } else if (arg == "--bfbs-gen-embed") {
+ opts.binary_schema_gen_embed = true;
+ } else if (arg == "--reflect-types") {
+ opts.mini_reflect = IDLOptions::kTypes;
+ } else if (arg == "--reflect-names") {
+ opts.mini_reflect = IDLOptions::kTypesAndNames;
+ } else if (arg == "--require-explicit-ids") {
+ opts.require_explicit_ids = true;
+ } else if (arg == "--root-type") {
+ if (++argi >= argc) Error("missing type following: " + arg, true);
+ opts.root_type = argv[argi];
+ } else if (arg == "--filename-suffix") {
+ if (++argi >= argc) Error("missing filename suffix: " + arg, true);
+ opts.filename_suffix = argv[argi];
+ } else if (arg == "--filename-ext") {
+ if (++argi >= argc) Error("missing filename extension: " + arg, true);
+ opts.filename_extension = argv[argi];
+ } else if (arg == "--force-defaults") {
+ opts.force_defaults = true;
+ } else if (arg == "--force-empty") {
+ opts.set_empty_strings_to_null = false;
+ opts.set_empty_vectors_to_null = false;
+ } else if (arg == "--force-empty-vectors") {
+ opts.set_empty_vectors_to_null = false;
+ } else if (arg == "--java-primitive-has-method") {
+ opts.java_primitive_has_method = true;
+ } else if (arg == "--cs-gen-json-serializer") {
+ opts.cs_gen_json_serializer = true;
+ } else if (arg == "--flexbuffers") {
+ opts.use_flexbuffers = true;
+ } else if (arg == "--gen-jvmstatic") {
+ opts.gen_jvmstatic = true;
+ } else if (arg == "--no-warnings") {
+ opts.no_warnings = true;
+ } else if (arg == "--cpp-std") {
+ if (++argi >= argc)
+ Error("missing C++ standard specification" + arg, true);
+ opts.cpp_std = argv[argi];
+ } else if (arg.rfind("--cpp-std=", 0) == 0) {
+ opts.cpp_std = arg.substr(std::string("--cpp-std=").size());
+ } else if (arg == "--cpp-static-reflection") {
+ opts.cpp_static_reflection = true;
+ } else {
+ for (size_t i = 0; i < params_.num_generators; ++i) {
+ if (arg == params_.generators[i].generator_opt_long ||
+ (params_.generators[i].generator_opt_short &&
+ arg == params_.generators[i].generator_opt_short)) {
+ generator_enabled[i] = true;
+ any_generator = true;
+ opts.lang_to_generate |= params_.generators[i].lang;
+ goto found;
+ }
+ }
+ Error("unknown commandline argument: " + arg, true);
+ found:;
+ }
+ } else {
+ filenames.push_back(flatbuffers::PosixPath(argv[argi]));
+ }
+ }
+
+ if (!filenames.size()) Error("missing input files", false, true);
+
+ if (opts.proto_mode) {
+ if (any_generator)
+ Error("cannot generate code directly from .proto files", true);
+ } else if (!any_generator && conform_to_schema.empty()) {
+ Error("no options: specify at least one generator.", true);
+ }
+
+ flatbuffers::Parser conform_parser;
+ if (!conform_to_schema.empty()) {
+ std::string contents;
+ if (!flatbuffers::LoadFile(conform_to_schema.c_str(), true, &contents))
+ Error("unable to load schema: " + conform_to_schema);
+
+ if (flatbuffers::GetExtension(conform_to_schema) ==
+ reflection::SchemaExtension()) {
+ LoadBinarySchema(conform_parser, conform_to_schema, contents);
+ } else {
+ ParseFile(conform_parser, conform_to_schema, contents,
+ conform_include_directories);
+ }
+ }
+
+ std::unique_ptr<flatbuffers::Parser> parser(new flatbuffers::Parser(opts));
+
+ for (auto file_it = filenames.begin(); file_it != filenames.end();
+ ++file_it) {
+ auto &filename = *file_it;
+ std::string contents;
+ if (!flatbuffers::LoadFile(filename.c_str(), true, &contents))
+ Error("unable to load file: " + filename);
+
+ bool is_binary =
+ static_cast<size_t>(file_it - filenames.begin()) >= binary_files_from;
+ auto ext = flatbuffers::GetExtension(filename);
+ auto is_schema = ext == "fbs" || ext == "proto";
+ auto is_binary_schema = ext == reflection::SchemaExtension();
+ if (is_binary) {
+ parser->builder_.Clear();
+ parser->builder_.PushFlatBuffer(
+ reinterpret_cast<const uint8_t *>(contents.c_str()),
+ contents.length());
+ if (!raw_binary) {
+ // Generally reading binaries that do not correspond to the schema
+ // will crash, and sadly there's no way around that when the binary
+ // does not contain a file identifier.
+ // We'd expect that typically any binary used as a file would have
+ // such an identifier, so by default we require them to match.
+ if (!parser->file_identifier_.length()) {
+ Error("current schema has no file_identifier: cannot test if \"" +
+ filename +
+ "\" matches the schema, use --raw-binary to read this file"
+ " anyway.");
+ } else if (!flatbuffers::BufferHasIdentifier(
+ contents.c_str(), parser->file_identifier_.c_str(),
+ opts.size_prefixed)) {
+ Error("binary \"" + filename +
+ "\" does not have expected file_identifier \"" +
+ parser->file_identifier_ +
+ "\", use --raw-binary to read this file anyway.");
+ }
+ }
+ } else {
+ // Check if file contains 0 bytes.
+ if (!opts.use_flexbuffers && !is_binary_schema &&
+ contents.length() != strlen(contents.c_str())) {
+ Error("input file appears to be binary: " + filename, true);
+ }
+ if (is_schema) {
+ // If we're processing multiple schemas, make sure to start each
+ // one from scratch. If it depends on previous schemas it must do
+ // so explicitly using an include.
+ parser.reset(new flatbuffers::Parser(opts));
+ }
+ if (is_binary_schema) {
+ LoadBinarySchema(*parser.get(), filename, contents);
+ }
+ if (opts.use_flexbuffers) {
+ if (opts.lang_to_generate == IDLOptions::kJson) {
+ parser->flex_root_ = flexbuffers::GetRoot(
+ reinterpret_cast<const uint8_t *>(contents.c_str()),
+ contents.size());
+ } else {
+ parser->flex_builder_.Clear();
+ ParseFile(*parser.get(), filename, contents, include_directories);
+ }
+ } else {
+ ParseFile(*parser.get(), filename, contents, include_directories);
+ if (!is_schema && !parser->builder_.GetSize()) {
+ // If a file doesn't end in .fbs, it must be json/binary. Ensure we
+ // didn't just parse a schema with a different extension.
+ Error("input file is neither json nor a .fbs (schema) file: " +
+ filename,
+ true);
+ }
+ }
+ if ((is_schema || is_binary_schema) && !conform_to_schema.empty()) {
+ auto err = parser->ConformTo(conform_parser);
+ if (!err.empty()) Error("schemas don\'t conform: " + err);
+ }
+ if (schema_binary || opts.binary_schema_gen_embed) {
+ parser->Serialize();
+ }
+ if (schema_binary) {
+ parser->file_extension_ = reflection::SchemaExtension();
+ }
+ }
+
+ std::string filebase =
+ flatbuffers::StripPath(flatbuffers::StripExtension(filename));
+
+ for (size_t i = 0; i < params_.num_generators; ++i) {
+ parser->opts.lang = params_.generators[i].lang;
+ if (generator_enabled[i]) {
+ if (!print_make_rules) {
+ flatbuffers::EnsureDirExists(output_path);
+ if ((!params_.generators[i].schema_only ||
+ (is_schema || is_binary_schema)) &&
+ !params_.generators[i].generate(*parser.get(), output_path,
+ filebase)) {
+ Error(std::string("Unable to generate ") +
+ params_.generators[i].lang_name + " for " + filebase);
+ }
+ } else {
+ if (params_.generators[i].make_rule == nullptr) {
+ Error(std::string("Cannot generate make rule for ") +
+ params_.generators[i].lang_name);
+ } else {
+ std::string make_rule = params_.generators[i].make_rule(
+ *parser.get(), output_path, filename);
+ if (!make_rule.empty())
+ printf("%s\n",
+ flatbuffers::WordWrap(make_rule, 80, " ", " \\").c_str());
+ }
+ }
+ if (grpc_enabled) {
+ if (params_.generators[i].generateGRPC != nullptr) {
+ if (!params_.generators[i].generateGRPC(*parser.get(), output_path,
+ filebase)) {
+ Error(std::string("Unable to generate GRPC interface for") +
+ params_.generators[i].lang_name);
+ }
+ } else {
+ Warn(std::string("GRPC interface generator not implemented for ") +
+ params_.generators[i].lang_name);
+ }
+ }
+ }
+ }
+
+ if (!opts.root_type.empty()) {
+ if (!parser->SetRootType(opts.root_type.c_str()))
+ Error("unknown root type: " + opts.root_type);
+ else if (parser->root_struct_def_->fixed)
+ Error("root type must be a table");
+ }
+
+ if (opts.proto_mode) GenerateFBS(*parser.get(), output_path, filebase);
+
+ // We do not want to generate code for the definitions in this file
+ // in any files coming up next.
+ parser->MarkGenerated();
+ }
+ return 0;
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/flatc_main.cpp b/contrib/libs/flatbuffers/src/flatc_main.cpp
new file mode 100644
index 0000000000..31ccbc7185
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/flatc_main.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#include "flatbuffers/flatc.h"
+#include "flatbuffers/util.h"
+
+static const char *g_program_name = nullptr;
+
+static void Warn(const flatbuffers::FlatCompiler *flatc,
+ const std::string &warn, bool show_exe_name) {
+ (void)flatc;
+ if (show_exe_name) { printf("%s: ", g_program_name); }
+ printf("warning: %s\n", warn.c_str());
+}
+
+static void Error(const flatbuffers::FlatCompiler *flatc,
+ const std::string &err, bool usage, bool show_exe_name) {
+ if (show_exe_name) { printf("%s: ", g_program_name); }
+ printf("error: %s\n", err.c_str());
+ if (usage && flatc) {
+ printf("%s", flatc->GetUsageString(g_program_name).c_str());
+ }
+ exit(1);
+}
+
+namespace flatbuffers {
+void LogCompilerWarn(const std::string &warn) {
+ Warn(static_cast<const flatbuffers::FlatCompiler *>(nullptr), warn, true);
+}
+void LogCompilerError(const std::string &err) {
+ Error(static_cast<const flatbuffers::FlatCompiler *>(nullptr), err, false,
+ true);
+}
+} // namespace flatbuffers
+
+int main(int argc, const char *argv[]) {
+ // Prevent Appveyor-CI hangs.
+ flatbuffers::SetupDefaultCRTReportMode();
+
+ g_program_name = argv[0];
+
+ const flatbuffers::FlatCompiler::Generator generators[] = {
+ { flatbuffers::GenerateBinary, "-b", "--binary", "binary", false, nullptr,
+ flatbuffers::IDLOptions::kBinary,
+ "Generate wire format binaries for any data definitions",
+ flatbuffers::BinaryMakeRule },
+ { flatbuffers::GenerateTextFile, "-t", "--json", "text", false, nullptr,
+ flatbuffers::IDLOptions::kJson,
+ "Generate text output for any data definitions",
+ flatbuffers::TextMakeRule },
+ { flatbuffers::GenerateCPP, "-c", "--cpp", "C++", true,
+ flatbuffers::GenerateCppGRPC, flatbuffers::IDLOptions::kCpp,
+ "Generate C++ headers for tables/structs", flatbuffers::CPPMakeRule },
+ { flatbuffers::GenerateGo, "-g", "--go", "Go", true,
+ flatbuffers::GenerateGoGRPC, flatbuffers::IDLOptions::kGo,
+ "Generate Go files for tables/structs", nullptr },
+ { flatbuffers::GenerateJava, "-j", "--java", "Java", true,
+ flatbuffers::GenerateJavaGRPC, flatbuffers::IDLOptions::kJava,
+ "Generate Java classes for tables/structs",
+ flatbuffers::JavaCSharpMakeRule },
+ { flatbuffers::GenerateDart, "-d", "--dart", "Dart", true, nullptr,
+ flatbuffers::IDLOptions::kDart,
+ "Generate Dart classes for tables/structs", flatbuffers::DartMakeRule },
+ { flatbuffers::GenerateTS, "-T", "--ts", "TypeScript", true,
+ flatbuffers::GenerateTSGRPC, flatbuffers::IDLOptions::kTs,
+ "Generate TypeScript code for tables/structs", flatbuffers::TSMakeRule },
+ { flatbuffers::GenerateCSharp, "-n", "--csharp", "C#", true, nullptr,
+ flatbuffers::IDLOptions::kCSharp,
+ "Generate C# classes for tables/structs",
+ flatbuffers::JavaCSharpMakeRule },
+ { flatbuffers::GeneratePython, "-p", "--python", "Python", true,
+ flatbuffers::GeneratePythonGRPC, flatbuffers::IDLOptions::kPython,
+ "Generate Python files for tables/structs", nullptr },
+ { flatbuffers::GenerateLobster, nullptr, "--lobster", "Lobster", true,
+ nullptr, flatbuffers::IDLOptions::kLobster,
+ "Generate Lobster files for tables/structs", nullptr },
+ { flatbuffers::GenerateLua, "-l", "--lua", "Lua", true, nullptr,
+ flatbuffers::IDLOptions::kLua, "Generate Lua files for tables/structs",
+ nullptr },
+ { flatbuffers::GenerateRust, "-r", "--rust", "Rust", true, nullptr,
+ flatbuffers::IDLOptions::kRust, "Generate Rust files for tables/structs",
+ flatbuffers::RustMakeRule },
+ { flatbuffers::GeneratePhp, nullptr, "--php", "PHP", true, nullptr,
+ flatbuffers::IDLOptions::kPhp, "Generate PHP files for tables/structs",
+ nullptr },
+ { flatbuffers::GenerateKotlin, nullptr, "--kotlin", "Kotlin", true, nullptr,
+ flatbuffers::IDLOptions::kKotlin,
+ "Generate Kotlin classes for tables/structs", nullptr },
+ { flatbuffers::GenerateJsonSchema, nullptr, "--jsonschema", "JsonSchema",
+ true, nullptr, flatbuffers::IDLOptions::kJsonSchema,
+ "Generate Json schema", nullptr },
+ { flatbuffers::GenerateSwift, nullptr, "--swift", "swift", true,
+ flatbuffers::GenerateSwiftGRPC, flatbuffers::IDLOptions::kSwift,
+ "Generate Swift files for tables/structs", nullptr },
+ { flatbuffers::GenerateCPPYandexMapsIter, nullptr, "--yandex-maps-iter", "C++Iter",
+ true, nullptr, flatbuffers::IDLOptions::kCppYandexMapsIter,
+ "Generate C++ template headers for tables/structs", nullptr },
+ };
+
+ flatbuffers::FlatCompiler::InitParams params;
+ params.generators = generators;
+ params.num_generators = sizeof(generators) / sizeof(generators[0]);
+ params.warn_fn = Warn;
+ params.error_fn = Error;
+
+ flatbuffers::FlatCompiler flatc(params);
+ return flatc.Compile(argc - 1, argv + 1);
+}
diff --git a/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp b/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp
new file mode 100644
index 0000000000..a33697eaed
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_cpp.cpp
@@ -0,0 +1,3514 @@
+/*
+ * 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 <unordered_set>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/flatc.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+// Make numerical literal with type-suffix.
+// This function is only needed for C++! Other languages do not need it.
+static inline std::string NumToStringCpp(std::string val, BaseType type) {
+ // Avoid issues with -2147483648, -9223372036854775808.
+ switch (type) {
+ case BASE_TYPE_INT:
+ return (val != "-2147483648") ? val : ("(-2147483647 - 1)");
+ case BASE_TYPE_ULONG: return (val == "0") ? val : (val + "ULL");
+ case BASE_TYPE_LONG:
+ if (val == "-9223372036854775808")
+ return "(-9223372036854775807LL - 1LL)";
+ else
+ return (val == "0") ? val : (val + "LL");
+ default: return val;
+ }
+}
+
+static std::string GenIncludeGuard(const std::string &file_name,
+ const Namespace &name_space,
+ const std::string &postfix = "") {
+ // Generate include guard.
+ std::string guard = file_name;
+ // Remove any non-alpha-numeric characters that may appear in a filename.
+ struct IsAlnum {
+ bool operator()(char c) const { return !is_alnum(c); }
+ };
+ guard.erase(std::remove_if(guard.begin(), guard.end(), IsAlnum()),
+ guard.end());
+ guard = "FLATBUFFERS_GENERATED_" + guard;
+ guard += "_";
+ // For further uniqueness, also add the namespace.
+ for (auto it = name_space.components.begin();
+ it != name_space.components.end(); ++it) {
+ guard += *it + "_";
+ }
+ // Anything extra to add to the guard?
+ if (!postfix.empty()) { guard += postfix + "_"; }
+ guard += "H_";
+ std::transform(guard.begin(), guard.end(), guard.begin(), CharToUpper);
+ return guard;
+}
+
+namespace cpp {
+
+enum CppStandard { CPP_STD_X0 = 0, CPP_STD_11, CPP_STD_17 };
+
+// Define a style of 'struct' constructor if it has 'Array' fields.
+enum GenArrayArgMode {
+ kArrayArgModeNone, // don't generate initialization args
+ kArrayArgModeSpanStatic, // generate flatbuffers::span<T,N>
+};
+
+// Extension of IDLOptions for cpp-generator.
+struct IDLOptionsCpp : public IDLOptions {
+ // All fields start with 'g_' prefix to distinguish from the base IDLOptions.
+ CppStandard g_cpp_std; // Base version of C++ standard.
+ bool g_only_fixed_enums; // Generate underlaying type for all enums.
+
+ IDLOptionsCpp(const IDLOptions &opts)
+ : IDLOptions(opts), g_cpp_std(CPP_STD_11), g_only_fixed_enums(true) {}
+};
+
+class CppGenerator : public BaseGenerator {
+ public:
+ CppGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name, IDLOptionsCpp opts)
+ : BaseGenerator(parser, path, file_name, "", "::", "h"),
+ cur_name_space_(nullptr),
+ opts_(opts),
+ float_const_gen_("std::numeric_limits<double>::",
+ "std::numeric_limits<float>::", "quiet_NaN()",
+ "infinity()") {
+ static const char *const keywords[] = {
+ "alignas",
+ "alignof",
+ "and",
+ "and_eq",
+ "asm",
+ "atomic_cancel",
+ "atomic_commit",
+ "atomic_noexcept",
+ "auto",
+ "bitand",
+ "bitor",
+ "bool",
+ "break",
+ "case",
+ "catch",
+ "char",
+ "char16_t",
+ "char32_t",
+ "class",
+ "compl",
+ "concept",
+ "const",
+ "constexpr",
+ "const_cast",
+ "continue",
+ "co_await",
+ "co_return",
+ "co_yield",
+ "decltype",
+ "default",
+ "delete",
+ "do",
+ "double",
+ "dynamic_cast",
+ "else",
+ "enum",
+ "explicit",
+ "export",
+ "extern",
+ "false",
+ "float",
+ "for",
+ "friend",
+ "goto",
+ "if",
+ "import",
+ "inline",
+ "int",
+ "long",
+ "module",
+ "mutable",
+ "namespace",
+ "new",
+ "noexcept",
+ "not",
+ "not_eq",
+ "nullptr",
+ "operator",
+ "or",
+ "or_eq",
+ "private",
+ "protected",
+ "public",
+ "register",
+ "reinterpret_cast",
+ "requires",
+ "return",
+ "short",
+ "signed",
+ "sizeof",
+ "static",
+ "static_assert",
+ "static_cast",
+ "struct",
+ "switch",
+ "synchronized",
+ "template",
+ "this",
+ "thread_local",
+ "throw",
+ "true",
+ "try",
+ "typedef",
+ "typeid",
+ "typename",
+ "union",
+ "unsigned",
+ "using",
+ "virtual",
+ "void",
+ "volatile",
+ "wchar_t",
+ "while",
+ "xor",
+ "xor_eq",
+ nullptr,
+ };
+ for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
+ }
+
+ void GenIncludeDependencies() {
+ int num_includes = 0;
+ if (opts_.generate_object_based_api) {
+ for (auto it = parser_.native_included_files_.begin();
+ it != parser_.native_included_files_.end(); ++it) {
+ code_ += "#include \"" + *it + "\"";
+ num_includes++;
+ }
+ }
+ for (auto it = parser_.included_files_.begin();
+ it != parser_.included_files_.end(); ++it) {
+ if (it->second.empty()) continue;
+ auto noext = flatbuffers::StripExtension(it->second);
+ auto basename = flatbuffers::StripPath(noext);
+ auto includeName =
+ GeneratedFileName(opts_.include_prefix,
+ opts_.keep_include_path ? noext : basename, opts_);
+ code_ += "#include \"" + includeName + "\"";
+ num_includes++;
+ }
+ if (num_includes) code_ += "";
+ }
+
+ void GenExtraIncludes() {
+ for (std::size_t i = 0; i < opts_.cpp_includes.size(); ++i) {
+ code_ += "#include \"" + opts_.cpp_includes[i] + "\"";
+ }
+ if (!opts_.cpp_includes.empty()) { code_ += ""; }
+ }
+
+ std::string EscapeKeyword(const std::string &name) const {
+ return keywords_.find(name) == keywords_.end() ? name : name + "_";
+ }
+
+ std::string Name(const Definition &def) const {
+ return EscapeKeyword(def.name);
+ }
+
+ std::string Name(const EnumVal &ev) const { return EscapeKeyword(ev.name); }
+
+ bool generate_bfbs_embed() {
+ code_.Clear();
+ code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
+
+ // If we don't have a root struct definition,
+ if (!parser_.root_struct_def_) {
+ // put a comment in the output why there is no code generated.
+ code_ += "// Binary schema not generated, no root struct found";
+ } else {
+ auto &struct_def = *parser_.root_struct_def_;
+ const auto include_guard =
+ GenIncludeGuard(file_name_, *struct_def.defined_namespace, "bfbs");
+
+ code_ += "#ifndef " + include_guard;
+ code_ += "#define " + include_guard;
+ code_ += "";
+ if (parser_.opts.gen_nullable) {
+ code_ += "#pragma clang system_header\n\n";
+ }
+
+ SetNameSpace(struct_def.defined_namespace);
+ auto name = Name(struct_def);
+ code_.SetValue("STRUCT_NAME", name);
+
+ // Create code to return the binary schema data.
+ auto binary_schema_hex_text =
+ BufferToHexText(parser_.builder_.GetBufferPointer(),
+ parser_.builder_.GetSize(), 105, " ", "");
+
+ code_ += "struct {{STRUCT_NAME}}BinarySchema {";
+ code_ += " static const uint8_t *data() {";
+ code_ += " // Buffer containing the binary schema.";
+ code_ += " static const uint8_t bfbsData[" +
+ NumToString(parser_.builder_.GetSize()) + "] = {";
+ code_ += binary_schema_hex_text;
+ code_ += " };";
+ code_ += " return bfbsData;";
+ code_ += " }";
+ code_ += " static size_t size() {";
+ code_ += " return " + NumToString(parser_.builder_.GetSize()) + ";";
+ code_ += " }";
+ code_ += " const uint8_t *begin() {";
+ code_ += " return data();";
+ code_ += " }";
+ code_ += " const uint8_t *end() {";
+ code_ += " return data() + size();";
+ code_ += " }";
+ code_ += "};";
+ code_ += "";
+
+ if (cur_name_space_) SetNameSpace(nullptr);
+
+ // Close the include guard.
+ code_ += "#endif // " + include_guard;
+ }
+
+ // We are just adding "_bfbs" to the generated filename.
+ const auto file_path =
+ GeneratedFileName(path_, file_name_ + "_bfbs", opts_);
+ const auto final_code = code_.ToString();
+
+ return SaveFile(file_path.c_str(), final_code, false);
+ }
+
+ // Iterate through all definitions we haven't generate code for (enums,
+ // structs, and tables) and output them to a single file.
+ bool generate() {
+ code_.Clear();
+ code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
+
+ const auto include_guard =
+ GenIncludeGuard(file_name_, *parser_.current_namespace_);
+ code_ += "#ifndef " + include_guard;
+ code_ += "#define " + include_guard;
+ code_ += "";
+
+ if (opts_.gen_nullable) { code_ += "#pragma clang system_header\n\n"; }
+
+ code_ += "#include <contrib/libs/flatbuffers/include/flatbuffers/flatbuffers.h>";
+ if (parser_.uses_flexbuffers_) {
+ code_ += "#include <contrib/libs/flatbuffers/include/flatbuffers/flexbuffers.h>";
+ }
+ code_ += "";
+
+ if (opts_.include_dependence_headers) { GenIncludeDependencies(); }
+ GenExtraIncludes();
+
+ FLATBUFFERS_ASSERT(!cur_name_space_);
+
+ // Generate forward declarations for all structs/tables, since they may
+ // have circular references.
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (!struct_def.generated) {
+ SetNameSpace(struct_def.defined_namespace);
+ code_ += "struct " + Name(struct_def) + ";";
+ if (!struct_def.fixed) {
+ code_ += "struct " + Name(struct_def) + "Builder;";
+ }
+ if (opts_.generate_object_based_api) {
+ auto nativeName = NativeName(Name(struct_def), &struct_def, opts_);
+ if (!struct_def.fixed) { code_ += "struct " + nativeName + ";"; }
+ }
+ code_ += "";
+ }
+ }
+
+ // Generate forward declarations for all equal operators
+ if (opts_.generate_object_based_api && opts_.gen_compare) {
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (!struct_def.generated) {
+ SetNameSpace(struct_def.defined_namespace);
+ auto nativeName = NativeName(Name(struct_def), &struct_def, opts_);
+ code_ += "bool operator==(const " + nativeName + " &lhs, const " +
+ nativeName + " &rhs);";
+ code_ += "bool operator!=(const " + nativeName + " &lhs, const " +
+ nativeName + " &rhs);";
+ }
+ }
+ code_ += "";
+ }
+
+ // Generate preablmle code for mini reflection.
+ if (opts_.mini_reflect != IDLOptions::kNone) {
+ // To break cyclic dependencies, first pre-declare all tables/structs.
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (!struct_def.generated) {
+ SetNameSpace(struct_def.defined_namespace);
+ GenMiniReflectPre(&struct_def);
+ }
+ }
+ }
+
+ // Generate code for all the enum declarations.
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ const auto &enum_def = **it;
+ if (!enum_def.generated) {
+ SetNameSpace(enum_def.defined_namespace);
+ GenEnum(enum_def);
+ }
+ }
+
+ // Generate code for all structs, then all tables.
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (struct_def.fixed && !struct_def.generated) {
+ SetNameSpace(struct_def.defined_namespace);
+ GenStruct(struct_def);
+ }
+ }
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (!struct_def.fixed && !struct_def.generated) {
+ SetNameSpace(struct_def.defined_namespace);
+ GenTable(struct_def);
+ }
+ }
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (!struct_def.fixed && !struct_def.generated) {
+ SetNameSpace(struct_def.defined_namespace);
+ GenTablePost(struct_def);
+ }
+ }
+
+ // Generate code for union verifiers.
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ const auto &enum_def = **it;
+ if (enum_def.is_union && !enum_def.generated) {
+ SetNameSpace(enum_def.defined_namespace);
+ GenUnionPost(enum_def);
+ }
+ }
+
+ // Generate code for mini reflection.
+ if (opts_.mini_reflect != IDLOptions::kNone) {
+ // Then the unions/enums that may refer to them.
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ const auto &enum_def = **it;
+ if (!enum_def.generated) {
+ SetNameSpace(enum_def.defined_namespace);
+ GenMiniReflect(nullptr, &enum_def);
+ }
+ }
+ // Then the full tables/structs.
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (!struct_def.generated) {
+ SetNameSpace(struct_def.defined_namespace);
+ GenMiniReflect(&struct_def, nullptr);
+ }
+ }
+ }
+
+ // Generate convenient global helper functions:
+ if (parser_.root_struct_def_) {
+ auto &struct_def = *parser_.root_struct_def_;
+ SetNameSpace(struct_def.defined_namespace);
+ auto name = Name(struct_def);
+ auto qualified_name = cur_name_space_->GetFullyQualifiedName(name);
+ auto cpp_name = TranslateNameSpace(qualified_name);
+
+ code_.SetValue("STRUCT_NAME", name);
+ code_.SetValue("CPP_NAME", cpp_name);
+ code_.SetValue("NULLABLE_EXT", NullableExtension());
+
+ // The root datatype accessor:
+ code_ += "inline \\";
+ code_ +=
+ "const {{CPP_NAME}} *{{NULLABLE_EXT}}Get{{STRUCT_NAME}}(const void "
+ "*buf) {";
+ code_ += " return flatbuffers::GetRoot<{{CPP_NAME}}>(buf);";
+ code_ += "}";
+ code_ += "";
+
+ code_ += "inline \\";
+ code_ +=
+ "const {{CPP_NAME}} "
+ "*{{NULLABLE_EXT}}GetSizePrefixed{{STRUCT_NAME}}(const void "
+ "*buf) {";
+ code_ += " return flatbuffers::GetSizePrefixedRoot<{{CPP_NAME}}>(buf);";
+ code_ += "}";
+ code_ += "";
+
+ if (opts_.mutable_buffer) {
+ code_ += "inline \\";
+ code_ += "{{STRUCT_NAME}} *GetMutable{{STRUCT_NAME}}(void *buf) {";
+ code_ += " return flatbuffers::GetMutableRoot<{{STRUCT_NAME}}>(buf);";
+ code_ += "}";
+ code_ += "";
+ }
+
+ if (parser_.file_identifier_.length()) {
+ // Return the identifier
+ code_ += "inline const char *{{STRUCT_NAME}}Identifier() {";
+ code_ += " return \"" + parser_.file_identifier_ + "\";";
+ code_ += "}";
+ code_ += "";
+
+ // Check if a buffer has the identifier.
+ code_ += "inline \\";
+ code_ += "bool {{STRUCT_NAME}}BufferHasIdentifier(const void *buf) {";
+ code_ += " return flatbuffers::BufferHasIdentifier(";
+ code_ += " buf, {{STRUCT_NAME}}Identifier());";
+ code_ += "}";
+ code_ += "";
+ }
+
+ // The root verifier.
+ if (parser_.file_identifier_.length()) {
+ code_.SetValue("ID", name + "Identifier()");
+ } else {
+ code_.SetValue("ID", "nullptr");
+ }
+
+ code_ += "inline bool Verify{{STRUCT_NAME}}Buffer(";
+ code_ += " flatbuffers::Verifier &verifier) {";
+ code_ += " return verifier.VerifyBuffer<{{CPP_NAME}}>({{ID}});";
+ code_ += "}";
+ code_ += "";
+
+ code_ += "inline bool VerifySizePrefixed{{STRUCT_NAME}}Buffer(";
+ code_ += " flatbuffers::Verifier &verifier) {";
+ code_ +=
+ " return verifier.VerifySizePrefixedBuffer<{{CPP_NAME}}>({{ID}});";
+ code_ += "}";
+ code_ += "";
+
+ if (parser_.file_extension_.length()) {
+ // Return the extension
+ code_ += "inline const char *{{STRUCT_NAME}}Extension() {";
+ code_ += " return \"" + parser_.file_extension_ + "\";";
+ code_ += "}";
+ code_ += "";
+ }
+
+ // Finish a buffer with a given root object:
+ code_ += "inline void Finish{{STRUCT_NAME}}Buffer(";
+ code_ += " flatbuffers::FlatBufferBuilder &fbb,";
+ code_ += " flatbuffers::Offset<{{CPP_NAME}}> root) {";
+ if (parser_.file_identifier_.length())
+ code_ += " fbb.Finish(root, {{STRUCT_NAME}}Identifier());";
+ else
+ code_ += " fbb.Finish(root);";
+ code_ += "}";
+ code_ += "";
+
+ code_ += "inline void FinishSizePrefixed{{STRUCT_NAME}}Buffer(";
+ code_ += " flatbuffers::FlatBufferBuilder &fbb,";
+ code_ += " flatbuffers::Offset<{{CPP_NAME}}> root) {";
+ if (parser_.file_identifier_.length())
+ code_ += " fbb.FinishSizePrefixed(root, {{STRUCT_NAME}}Identifier());";
+ else
+ code_ += " fbb.FinishSizePrefixed(root);";
+ code_ += "}";
+ code_ += "";
+
+ if (opts_.generate_object_based_api) {
+ // A convenient root unpack function.
+ auto native_name = WrapNativeNameInNameSpace(struct_def, opts_);
+ code_.SetValue("UNPACK_RETURN",
+ GenTypeNativePtr(native_name, nullptr, false));
+ code_.SetValue("UNPACK_TYPE",
+ GenTypeNativePtr(native_name, nullptr, true));
+
+ code_ += "inline {{UNPACK_RETURN}} UnPack{{STRUCT_NAME}}(";
+ code_ += " const void *buf,";
+ code_ += " const flatbuffers::resolver_function_t *res = nullptr) {";
+ code_ += " return {{UNPACK_TYPE}}\\";
+ code_ += "(Get{{STRUCT_NAME}}(buf)->UnPack(res));";
+ code_ += "}";
+ code_ += "";
+
+ code_ += "inline {{UNPACK_RETURN}} UnPackSizePrefixed{{STRUCT_NAME}}(";
+ code_ += " const void *buf,";
+ code_ += " const flatbuffers::resolver_function_t *res = nullptr) {";
+ code_ += " return {{UNPACK_TYPE}}\\";
+ code_ += "(GetSizePrefixed{{STRUCT_NAME}}(buf)->UnPack(res));";
+ code_ += "}";
+ code_ += "";
+ }
+ }
+
+ if (cur_name_space_) SetNameSpace(nullptr);
+
+ // Close the include guard.
+ code_ += "#endif // " + include_guard;
+
+ const auto file_path = GeneratedFileName(path_, file_name_, opts_);
+ const auto final_code = code_.ToString();
+
+ // Save the file and optionally generate the binary schema code.
+ return SaveFile(file_path.c_str(), final_code, false) &&
+ (!parser_.opts.binary_schema_gen_embed || generate_bfbs_embed());
+ }
+
+ private:
+ CodeWriter code_;
+
+ std::unordered_set<std::string> keywords_;
+
+ // This tracks the current namespace so we can insert namespace declarations.
+ const Namespace *cur_name_space_;
+
+ const IDLOptionsCpp opts_;
+ const TypedFloatConstantGenerator float_const_gen_;
+
+ const Namespace *CurrentNameSpace() const { return cur_name_space_; }
+
+ // Translates a qualified name in flatbuffer text format to the same name in
+ // the equivalent C++ namespace.
+ static std::string TranslateNameSpace(const std::string &qualified_name) {
+ std::string cpp_qualified_name = qualified_name;
+ size_t start_pos = 0;
+ while ((start_pos = cpp_qualified_name.find('.', start_pos)) !=
+ std::string::npos) {
+ cpp_qualified_name.replace(start_pos, 1, "::");
+ }
+ return cpp_qualified_name;
+ }
+
+ bool TypeHasKey(const Type &type) {
+ if (type.base_type != BASE_TYPE_STRUCT) { return false; }
+ for (auto it = type.struct_def->fields.vec.begin();
+ it != type.struct_def->fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.key) { return true; }
+ }
+ return false;
+ }
+
+ bool VectorElementUserFacing(const Type &type) const {
+ return opts_.g_cpp_std >= cpp::CPP_STD_17 && opts_.g_only_fixed_enums &&
+ IsEnum(type);
+ }
+
+ void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
+ std::string text;
+ ::flatbuffers::GenComment(dc, &text, nullptr, prefix);
+ code_ += text + "\\";
+ }
+
+ // Return a C++ type from the table in idl.h
+ std::string GenTypeBasic(const Type &type, bool user_facing_type) const {
+ // clang-format off
+ static const char *const ctypename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ #CTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+ if (user_facing_type) {
+ if (type.enum_def) return WrapInNameSpace(*type.enum_def);
+ if (type.base_type == BASE_TYPE_BOOL) return "bool";
+ }
+ return ctypename[type.base_type];
+ }
+
+ // Return a C++ pointer type, specialized to the actual struct/table types,
+ // and vector element types.
+ std::string GenTypePointer(const Type &type) const {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: {
+ return "flatbuffers::String";
+ }
+ case BASE_TYPE_VECTOR: {
+ const auto type_name = GenTypeWire(
+ type.VectorType(), "", VectorElementUserFacing(type.VectorType()));
+ return "flatbuffers::Vector<" + type_name + ">";
+ }
+ case BASE_TYPE_STRUCT: {
+ return WrapInNameSpace(*type.struct_def);
+ }
+ case BASE_TYPE_UNION:
+ // fall through
+ default: {
+ return "void";
+ }
+ }
+ }
+
+ // Return a C++ type for any type (scalar/pointer) specifically for
+ // building a flatbuffer.
+ std::string GenTypeWire(const Type &type, const char *postfix,
+ bool user_facing_type) const {
+ if (IsScalar(type.base_type)) {
+ return GenTypeBasic(type, user_facing_type) + postfix;
+ } else if (IsStruct(type)) {
+ return "const " + GenTypePointer(type) + " *";
+ } else {
+ return "flatbuffers::Offset<" + GenTypePointer(type) + ">" + postfix;
+ }
+ }
+
+ // Return a C++ type for any type (scalar/pointer) that reflects its
+ // serialized size.
+ std::string GenTypeSize(const Type &type) const {
+ if (IsScalar(type.base_type)) {
+ return GenTypeBasic(type, false);
+ } else if (IsStruct(type)) {
+ return GenTypePointer(type);
+ } else {
+ return "flatbuffers::uoffset_t";
+ }
+ }
+
+ std::string NullableExtension() {
+ return opts_.gen_nullable ? " _Nullable " : "";
+ }
+
+ static std::string NativeName(const std::string &name, const StructDef *sd,
+ const IDLOptions &opts) {
+ return sd && !sd->fixed ? opts.object_prefix + name + opts.object_suffix
+ : name;
+ }
+
+ std::string WrapNativeNameInNameSpace(const StructDef &struct_def,
+ const IDLOptions &opts) {
+ return WrapInNameSpace(struct_def.defined_namespace,
+ NativeName(Name(struct_def), &struct_def, opts));
+ }
+
+ const std::string &PtrType(const FieldDef *field) {
+ auto attr = field ? field->attributes.Lookup("cpp_ptr_type") : nullptr;
+ return attr ? attr->constant : opts_.cpp_object_api_pointer_type;
+ }
+
+ const std::string NativeString(const FieldDef *field) {
+ auto attr = field ? field->attributes.Lookup("cpp_str_type") : nullptr;
+ auto &ret = attr ? attr->constant : opts_.cpp_object_api_string_type;
+ if (ret.empty()) { return "std::string"; }
+ return ret;
+ }
+
+ bool FlexibleStringConstructor(const FieldDef *field) {
+ auto attr = field
+ ? (field->attributes.Lookup("cpp_str_flex_ctor") != nullptr)
+ : false;
+ auto ret = attr ? attr : opts_.cpp_object_api_string_flexible_constructor;
+ return ret && NativeString(field) !=
+ "std::string"; // Only for custom string types.
+ }
+
+ std::string GenTypeNativePtr(const std::string &type, const FieldDef *field,
+ bool is_constructor) {
+ auto &ptr_type = PtrType(field);
+ if (ptr_type != "naked") {
+ return (ptr_type != "default_ptr_type"
+ ? ptr_type
+ : opts_.cpp_object_api_pointer_type) +
+ "<" + type + ">";
+ } else if (is_constructor) {
+ return "";
+ } else {
+ return type + " *";
+ }
+ }
+
+ std::string GenPtrGet(const FieldDef &field) {
+ auto cpp_ptr_type_get = field.attributes.Lookup("cpp_ptr_type_get");
+ if (cpp_ptr_type_get) return cpp_ptr_type_get->constant;
+ auto &ptr_type = PtrType(&field);
+ return ptr_type == "naked" ? "" : ".get()";
+ }
+
+ std::string GenOptionalNull() { return "flatbuffers::nullopt"; }
+
+ std::string GenOptionalDecl(const Type &type) {
+ return "flatbuffers::Optional<" + GenTypeBasic(type, true) + ">";
+ }
+
+ std::string GenTypeNative(const Type &type, bool invector,
+ const FieldDef &field) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: {
+ return NativeString(&field);
+ }
+ case BASE_TYPE_VECTOR: {
+ const auto type_name = GenTypeNative(type.VectorType(), true, field);
+ if (type.struct_def &&
+ type.struct_def->attributes.Lookup("native_custom_alloc")) {
+ auto native_custom_alloc =
+ type.struct_def->attributes.Lookup("native_custom_alloc");
+ return "std::vector<" + type_name + "," +
+ native_custom_alloc->constant + "<" + type_name + ">>";
+ } else
+ return "std::vector<" + type_name + ">";
+ }
+ case BASE_TYPE_STRUCT: {
+ auto type_name = WrapInNameSpace(*type.struct_def);
+ if (IsStruct(type)) {
+ auto native_type = type.struct_def->attributes.Lookup("native_type");
+ if (native_type) { type_name = native_type->constant; }
+ if (invector || field.native_inline) {
+ return type_name;
+ } else {
+ return GenTypeNativePtr(type_name, &field, false);
+ }
+ } else {
+ return GenTypeNativePtr(
+ WrapNativeNameInNameSpace(*type.struct_def, opts_), &field,
+ false);
+ }
+ }
+ case BASE_TYPE_UNION: {
+ auto type_name = WrapInNameSpace(*type.enum_def);
+ return type_name + "Union";
+ }
+ default: {
+ return field.IsScalarOptional() ? GenOptionalDecl(type)
+ : GenTypeBasic(type, true);
+ }
+ }
+ }
+
+ // Return a C++ type for any type (scalar/pointer) specifically for
+ // using a flatbuffer.
+ std::string GenTypeGet(const Type &type, const char *afterbasic,
+ const char *beforeptr, const char *afterptr,
+ bool user_facing_type) {
+ if (IsScalar(type.base_type)) {
+ return GenTypeBasic(type, user_facing_type) + afterbasic;
+ } else if (IsArray(type)) {
+ auto element_type = type.VectorType();
+ // Check if enum arrays are used in C++ without specifying --scoped-enums
+ if (IsEnum(element_type) && !opts_.g_only_fixed_enums) {
+ LogCompilerError(
+ "--scoped-enums must be enabled to use enum arrays in C++");
+ FLATBUFFERS_ASSERT(true);
+ }
+ return beforeptr +
+ (IsScalar(element_type.base_type)
+ ? GenTypeBasic(element_type, user_facing_type)
+ : GenTypePointer(element_type)) +
+ afterptr;
+ } else {
+ return beforeptr + GenTypePointer(type) + afterptr;
+ }
+ }
+
+ std::string GenTypeSpan(const Type &type, bool immutable, size_t extent) {
+ // Generate "flatbuffers::span<const U, extent>".
+ FLATBUFFERS_ASSERT(IsSeries(type) && "unexpected type");
+ auto element_type = type.VectorType();
+ std::string text = "flatbuffers::span<";
+ text += immutable ? "const " : "";
+ if (IsScalar(element_type.base_type)) {
+ text += GenTypeBasic(element_type, IsEnum(element_type));
+ } else {
+ switch (element_type.base_type) {
+ case BASE_TYPE_STRING: {
+ text += "char";
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ FLATBUFFERS_ASSERT(type.struct_def);
+ text += WrapInNameSpace(*type.struct_def);
+ break;
+ }
+ default:
+ FLATBUFFERS_ASSERT(false && "unexpected element's type");
+ break;
+ }
+ }
+ if (extent != flatbuffers::dynamic_extent) {
+ text += ", ";
+ text += NumToString(extent);
+ }
+ text += "> ";
+ return text;
+ }
+
+ std::string GenEnumValDecl(const EnumDef &enum_def,
+ const std::string &enum_val) const {
+ return opts_.prefixed_enums ? Name(enum_def) + "_" + enum_val : enum_val;
+ }
+
+ std::string GetEnumValUse(const EnumDef &enum_def,
+ const EnumVal &enum_val) const {
+ if (opts_.scoped_enums) {
+ return Name(enum_def) + "::" + Name(enum_val);
+ } else if (opts_.prefixed_enums) {
+ return Name(enum_def) + "_" + Name(enum_val);
+ } else {
+ return Name(enum_val);
+ }
+ }
+
+ std::string StripUnionType(const std::string &name) {
+ return name.substr(0, name.size() - strlen(UnionTypeFieldSuffix()));
+ }
+
+ std::string GetUnionElement(const EnumVal &ev, bool native_type,
+ const IDLOptions &opts) {
+ if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
+ auto name = ev.union_type.struct_def->name;
+ if (native_type) {
+ name = NativeName(name, ev.union_type.struct_def, opts);
+ }
+ return WrapInNameSpace(ev.union_type.struct_def->defined_namespace, name);
+ } else if (IsString(ev.union_type)) {
+ return native_type ? "std::string" : "flatbuffers::String";
+ } else {
+ FLATBUFFERS_ASSERT(false);
+ return Name(ev);
+ }
+ }
+
+ std::string UnionVerifySignature(const EnumDef &enum_def) {
+ return "bool Verify" + Name(enum_def) +
+ "(flatbuffers::Verifier &verifier, const void *obj, " +
+ Name(enum_def) + " type)";
+ }
+
+ std::string UnionVectorVerifySignature(const EnumDef &enum_def) {
+ return "bool Verify" + Name(enum_def) + "Vector" +
+ "(flatbuffers::Verifier &verifier, " +
+ "const flatbuffers::Vector<flatbuffers::Offset<void>> *values, " +
+ "const flatbuffers::Vector<uint8_t> *types)";
+ }
+
+ std::string UnionUnPackSignature(const EnumDef &enum_def, bool inclass) {
+ return (inclass ? "static " : "") + std::string("void *") +
+ (inclass ? "" : Name(enum_def) + "Union::") +
+ "UnPack(const void *obj, " + Name(enum_def) +
+ " type, const flatbuffers::resolver_function_t *resolver)";
+ }
+
+ std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) {
+ return "flatbuffers::Offset<void> " +
+ (inclass ? "" : Name(enum_def) + "Union::") +
+ "Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
+ "const flatbuffers::rehasher_function_t *_rehasher" +
+ (inclass ? " = nullptr" : "") + ") const";
+ }
+
+ std::string TableCreateSignature(const StructDef &struct_def, bool predecl,
+ const IDLOptions &opts) {
+ return "flatbuffers::Offset<" + Name(struct_def) + "> Create" +
+ Name(struct_def) + "(flatbuffers::FlatBufferBuilder &_fbb, const " +
+ NativeName(Name(struct_def), &struct_def, opts) +
+ " *_o, const flatbuffers::rehasher_function_t *_rehasher" +
+ (predecl ? " = nullptr" : "") + ")";
+ }
+
+ std::string TablePackSignature(const StructDef &struct_def, bool inclass,
+ const IDLOptions &opts) {
+ return std::string(inclass ? "static " : "") + "flatbuffers::Offset<" +
+ Name(struct_def) + "> " + (inclass ? "" : Name(struct_def) + "::") +
+ "Pack(flatbuffers::FlatBufferBuilder &_fbb, " + "const " +
+ NativeName(Name(struct_def), &struct_def, opts) + "* _o, " +
+ "const flatbuffers::rehasher_function_t *_rehasher" +
+ (inclass ? " = nullptr" : "") + ")";
+ }
+
+ std::string TableUnPackSignature(const StructDef &struct_def, bool inclass,
+ const IDLOptions &opts) {
+ return NativeName(Name(struct_def), &struct_def, opts) + " *" +
+ (inclass ? "" : Name(struct_def) + "::") +
+ "UnPack(const flatbuffers::resolver_function_t *_resolver" +
+ (inclass ? " = nullptr" : "") + ") const";
+ }
+
+ std::string TableUnPackToSignature(const StructDef &struct_def, bool inclass,
+ const IDLOptions &opts) {
+ return "void " + (inclass ? "" : Name(struct_def) + "::") + "UnPackTo(" +
+ NativeName(Name(struct_def), &struct_def, opts) + " *" +
+ "_o, const flatbuffers::resolver_function_t *_resolver" +
+ (inclass ? " = nullptr" : "") + ") const";
+ }
+
+ void GenMiniReflectPre(const StructDef *struct_def) {
+ code_.SetValue("NAME", struct_def->name);
+ code_ += "inline const flatbuffers::TypeTable *{{NAME}}TypeTable();";
+ code_ += "";
+ }
+
+ void GenMiniReflect(const StructDef *struct_def, const EnumDef *enum_def) {
+ code_.SetValue("NAME", struct_def ? struct_def->name : enum_def->name);
+ code_.SetValue("SEQ_TYPE",
+ struct_def ? (struct_def->fixed ? "ST_STRUCT" : "ST_TABLE")
+ : (enum_def->is_union ? "ST_UNION" : "ST_ENUM"));
+ auto num_fields =
+ struct_def ? struct_def->fields.vec.size() : enum_def->size();
+ code_.SetValue("NUM_FIELDS", NumToString(num_fields));
+ std::vector<std::string> names;
+ std::vector<Type> types;
+
+ if (struct_def) {
+ for (auto it = struct_def->fields.vec.begin();
+ it != struct_def->fields.vec.end(); ++it) {
+ const auto &field = **it;
+ names.push_back(Name(field));
+ types.push_back(field.value.type);
+ }
+ } else {
+ for (auto it = enum_def->Vals().begin(); it != enum_def->Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ names.push_back(Name(ev));
+ types.push_back(enum_def->is_union ? ev.union_type
+ : Type(enum_def->underlying_type));
+ }
+ }
+ std::string ts;
+ std::vector<std::string> type_refs;
+ std::vector<uint16_t> array_sizes;
+ for (auto it = types.begin(); it != types.end(); ++it) {
+ auto &type = *it;
+ if (!ts.empty()) ts += ",\n ";
+ auto is_vector = IsVector(type);
+ auto is_array = IsArray(type);
+ auto bt = is_vector || is_array ? type.element : type.base_type;
+ auto et = IsScalar(bt) || bt == BASE_TYPE_STRING
+ ? bt - BASE_TYPE_UTYPE + ET_UTYPE
+ : ET_SEQUENCE;
+ int ref_idx = -1;
+ std::string ref_name =
+ type.struct_def
+ ? WrapInNameSpace(*type.struct_def)
+ : type.enum_def ? WrapInNameSpace(*type.enum_def) : "";
+ if (!ref_name.empty()) {
+ auto rit = type_refs.begin();
+ for (; rit != type_refs.end(); ++rit) {
+ if (*rit == ref_name) {
+ ref_idx = static_cast<int>(rit - type_refs.begin());
+ break;
+ }
+ }
+ if (rit == type_refs.end()) {
+ ref_idx = static_cast<int>(type_refs.size());
+ type_refs.push_back(ref_name);
+ }
+ }
+ if (is_array) { array_sizes.push_back(type.fixed_length); }
+ ts += "{ flatbuffers::" + std::string(ElementaryTypeNames()[et]) + ", " +
+ NumToString(is_vector || is_array) + ", " + NumToString(ref_idx) +
+ " }";
+ }
+ std::string rs;
+ for (auto it = type_refs.begin(); it != type_refs.end(); ++it) {
+ if (!rs.empty()) rs += ",\n ";
+ rs += *it + "TypeTable";
+ }
+ std::string as;
+ for (auto it = array_sizes.begin(); it != array_sizes.end(); ++it) {
+ as += NumToString(*it);
+ as += ", ";
+ }
+ std::string ns;
+ for (auto it = names.begin(); it != names.end(); ++it) {
+ if (!ns.empty()) ns += ",\n ";
+ ns += "\"" + *it + "\"";
+ }
+ std::string vs;
+ const auto consecutive_enum_from_zero =
+ enum_def && enum_def->MinValue()->IsZero() &&
+ ((enum_def->size() - 1) == enum_def->Distance());
+ if (enum_def && !consecutive_enum_from_zero) {
+ for (auto it = enum_def->Vals().begin(); it != enum_def->Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ if (!vs.empty()) vs += ", ";
+ vs += NumToStringCpp(enum_def->ToString(ev),
+ enum_def->underlying_type.base_type);
+ }
+ } else if (struct_def && struct_def->fixed) {
+ for (auto it = struct_def->fields.vec.begin();
+ it != struct_def->fields.vec.end(); ++it) {
+ const auto &field = **it;
+ vs += NumToString(field.value.offset);
+ vs += ", ";
+ }
+ vs += NumToString(struct_def->bytesize);
+ }
+ code_.SetValue("TYPES", ts);
+ code_.SetValue("REFS", rs);
+ code_.SetValue("ARRAYSIZES", as);
+ code_.SetValue("NAMES", ns);
+ code_.SetValue("VALUES", vs);
+ code_ += "inline const flatbuffers::TypeTable *{{NAME}}TypeTable() {";
+ if (num_fields) {
+ code_ += " static const flatbuffers::TypeCode type_codes[] = {";
+ code_ += " {{TYPES}}";
+ code_ += " };";
+ }
+ if (!type_refs.empty()) {
+ code_ += " static const flatbuffers::TypeFunction type_refs[] = {";
+ code_ += " {{REFS}}";
+ code_ += " };";
+ }
+ if (!as.empty()) {
+ code_ += " static const int16_t array_sizes[] = { {{ARRAYSIZES}} };";
+ }
+ if (!vs.empty()) {
+ // Problem with uint64_t values greater than 9223372036854775807ULL.
+ code_ += " static const int64_t values[] = { {{VALUES}} };";
+ }
+ auto has_names =
+ num_fields && opts_.mini_reflect == IDLOptions::kTypesAndNames;
+ if (has_names) {
+ code_ += " static const char * const names[] = {";
+ code_ += " {{NAMES}}";
+ code_ += " };";
+ }
+ code_ += " static const flatbuffers::TypeTable tt = {";
+ code_ += std::string(" flatbuffers::{{SEQ_TYPE}}, {{NUM_FIELDS}}, ") +
+ (num_fields ? "type_codes, " : "nullptr, ") +
+ (!type_refs.empty() ? "type_refs, " : "nullptr, ") +
+ (!as.empty() ? "array_sizes, " : "nullptr, ") +
+ (!vs.empty() ? "values, " : "nullptr, ") +
+ (has_names ? "names" : "nullptr");
+ code_ += " };";
+ code_ += " return &tt;";
+ code_ += "}";
+ code_ += "";
+ }
+
+ // Generate an enum declaration,
+ // an enum string lookup table,
+ // and an enum array of values
+
+ void GenEnum(const EnumDef &enum_def) {
+ code_.SetValue("ENUM_NAME", Name(enum_def));
+ code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
+
+ GenComment(enum_def.doc_comment);
+ code_ +=
+ (opts_.scoped_enums ? "enum class " : "enum ") + Name(enum_def) + "\\";
+ if (opts_.g_only_fixed_enums) { code_ += " : {{BASE_TYPE}}\\"; }
+ code_ += " {";
+
+ code_.SetValue("SEP", ",");
+ auto add_sep = false;
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ const auto &ev = **it;
+ if (add_sep) code_ += "{{SEP}}";
+ GenComment(ev.doc_comment, " ");
+ code_.SetValue("KEY", GenEnumValDecl(enum_def, Name(ev)));
+ code_.SetValue("VALUE",
+ NumToStringCpp(enum_def.ToString(ev),
+ enum_def.underlying_type.base_type));
+ code_ += " {{KEY}} = {{VALUE}}\\";
+ add_sep = true;
+ }
+ const EnumVal *minv = enum_def.MinValue();
+ const EnumVal *maxv = enum_def.MaxValue();
+
+ if (opts_.scoped_enums || opts_.prefixed_enums) {
+ FLATBUFFERS_ASSERT(minv && maxv);
+
+ code_.SetValue("SEP", ",\n");
+ if (enum_def.attributes.Lookup("bit_flags")) {
+ code_.SetValue("KEY", GenEnumValDecl(enum_def, "NONE"));
+ code_.SetValue("VALUE", "0");
+ code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\";
+
+ code_.SetValue("KEY", GenEnumValDecl(enum_def, "ANY"));
+ code_.SetValue("VALUE",
+ NumToStringCpp(enum_def.AllFlags(),
+ enum_def.underlying_type.base_type));
+ code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\";
+ } else { // MIN & MAX are useless for bit_flags
+ code_.SetValue("KEY", GenEnumValDecl(enum_def, "MIN"));
+ code_.SetValue("VALUE", GenEnumValDecl(enum_def, Name(*minv)));
+ code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\";
+
+ code_.SetValue("KEY", GenEnumValDecl(enum_def, "MAX"));
+ code_.SetValue("VALUE", GenEnumValDecl(enum_def, Name(*maxv)));
+ code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\";
+ }
+ }
+ code_ += "";
+ code_ += "};";
+
+ if (opts_.scoped_enums && enum_def.attributes.Lookup("bit_flags")) {
+ code_ +=
+ "FLATBUFFERS_DEFINE_BITMASK_OPERATORS({{ENUM_NAME}}, {{BASE_TYPE}})";
+ }
+ code_ += "";
+
+ // Generate an array of all enumeration values
+ auto num_fields = NumToString(enum_def.size());
+ code_ += "inline const {{ENUM_NAME}} (&EnumValues{{ENUM_NAME}}())[" +
+ num_fields + "] {";
+ code_ += " static const {{ENUM_NAME}} values[] = {";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ const auto &ev = **it;
+ auto value = GetEnumValUse(enum_def, ev);
+ auto suffix = *it != enum_def.Vals().back() ? "," : "";
+ code_ += " " + value + suffix;
+ }
+ code_ += " };";
+ code_ += " return values;";
+ code_ += "}";
+ code_ += "";
+
+ // 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) {
+ code_ += "inline const char * const *EnumNames{{ENUM_NAME}}() {";
+ code_ += " static const char * const names[" +
+ NumToString(range + 1 + 1) + "] = {";
+
+ auto val = enum_def.Vals().front();
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ auto ev = *it;
+ for (auto k = enum_def.Distance(val, ev); k > 1; --k) {
+ code_ += " \"\",";
+ }
+ val = ev;
+ code_ += " \"" + Name(*ev) + "\",";
+ }
+ code_ += " nullptr";
+ code_ += " };";
+
+ code_ += " return names;";
+ code_ += "}";
+ code_ += "";
+
+ code_ += "inline const char *EnumName{{ENUM_NAME}}({{ENUM_NAME}} e) {";
+
+ code_ += " if (flatbuffers::IsOutRange(e, " +
+ GetEnumValUse(enum_def, *enum_def.MinValue()) + ", " +
+ GetEnumValUse(enum_def, *enum_def.MaxValue()) +
+ ")) return \"\";";
+
+ code_ += " const size_t index = static_cast<size_t>(e)\\";
+ if (enum_def.MinValue()->IsNonZero()) {
+ auto vals = GetEnumValUse(enum_def, *enum_def.MinValue());
+ code_ += " - static_cast<size_t>(" + vals + ")\\";
+ }
+ code_ += ";";
+
+ code_ += " return EnumNames{{ENUM_NAME}}()[index];";
+ code_ += "}";
+ code_ += "";
+ } else {
+ code_ += "inline const char *EnumName{{ENUM_NAME}}({{ENUM_NAME}} e) {";
+
+ code_ += " switch (e) {";
+
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ code_ += " case " + GetEnumValUse(enum_def, ev) + ": return \"" +
+ Name(ev) + "\";";
+ }
+
+ code_ += " default: return \"\";";
+ code_ += " }";
+
+ code_ += "}";
+ code_ += "";
+ }
+
+ // Generate type traits for unions to map from a type to union enum value.
+ if (enum_def.is_union && !enum_def.uses_multiple_type_instances) {
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+
+ if (it == enum_def.Vals().begin()) {
+ code_ += "template<typename T> struct {{ENUM_NAME}}Traits {";
+ } else {
+ auto name = GetUnionElement(ev, false, opts_);
+ code_ += "template<> struct {{ENUM_NAME}}Traits<" + name + "> {";
+ }
+
+ auto value = GetEnumValUse(enum_def, ev);
+ code_ += " static const {{ENUM_NAME}} enum_value = " + value + ";";
+ code_ += "};";
+ code_ += "";
+ }
+ }
+
+ if (opts_.generate_object_based_api && enum_def.is_union) {
+ // Generate a union type
+ code_.SetValue("NAME", Name(enum_def));
+ FLATBUFFERS_ASSERT(enum_def.Lookup("NONE"));
+ code_.SetValue("NONE", GetEnumValUse(enum_def, *enum_def.Lookup("NONE")));
+
+ code_ += "struct {{NAME}}Union {";
+ code_ += " {{NAME}} type;";
+ code_ += " void *value;";
+ code_ += "";
+ code_ += " {{NAME}}Union() : type({{NONE}}), value(nullptr) {}";
+ code_ += " {{NAME}}Union({{NAME}}Union&& u) FLATBUFFERS_NOEXCEPT :";
+ code_ += " type({{NONE}}), value(nullptr)";
+ code_ += " { std::swap(type, u.type); std::swap(value, u.value); }";
+ code_ += " {{NAME}}Union(const {{NAME}}Union &);";
+ code_ += " {{NAME}}Union &operator=(const {{NAME}}Union &u)";
+ code_ +=
+ " { {{NAME}}Union t(u); std::swap(type, t.type); std::swap(value, "
+ "t.value); return *this; }";
+ code_ +=
+ " {{NAME}}Union &operator=({{NAME}}Union &&u) FLATBUFFERS_NOEXCEPT";
+ code_ +=
+ " { std::swap(type, u.type); std::swap(value, u.value); return "
+ "*this; }";
+ code_ += " ~{{NAME}}Union() { Reset(); }";
+ code_ += "";
+ code_ += " void Reset();";
+ code_ += "";
+ if (!enum_def.uses_multiple_type_instances) {
+ code_ += "#ifndef FLATBUFFERS_CPP98_STL";
+ code_ += " template <typename T>";
+ code_ += " void Set(T&& val) {";
+ code_ += " using RT = typename std::remove_reference<T>::type;";
+ code_ += " Reset();";
+ code_ +=
+ " type = {{NAME}}Traits<typename RT::TableType>::enum_value;";
+ code_ += " if (type != {{NONE}}) {";
+ code_ += " value = new RT(std::forward<T>(val));";
+ code_ += " }";
+ code_ += " }";
+ code_ += "#endif // FLATBUFFERS_CPP98_STL";
+ code_ += "";
+ }
+ code_ += " " + UnionUnPackSignature(enum_def, true) + ";";
+ code_ += " " + UnionPackSignature(enum_def, true) + ";";
+ code_ += "";
+
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ if (ev.IsZero()) { continue; }
+
+ const auto native_type = GetUnionElement(ev, true, opts_);
+ code_.SetValue("NATIVE_TYPE", native_type);
+ code_.SetValue("NATIVE_NAME", Name(ev));
+ code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
+
+ code_ += " {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {";
+ code_ += " return type == {{NATIVE_ID}} ?";
+ code_ += " reinterpret_cast<{{NATIVE_TYPE}} *>(value) : nullptr;";
+ code_ += " }";
+
+ code_ += " const {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() const {";
+ code_ += " return type == {{NATIVE_ID}} ?";
+ code_ +=
+ " reinterpret_cast<const {{NATIVE_TYPE}} *>(value) : nullptr;";
+ code_ += " }";
+ }
+ code_ += "};";
+ code_ += "";
+
+ if (opts_.gen_compare) {
+ code_ += "";
+ code_ +=
+ "inline bool operator==(const {{NAME}}Union &lhs, const "
+ "{{NAME}}Union &rhs) {";
+ code_ += " if (lhs.type != rhs.type) return false;";
+ code_ += " switch (lhs.type) {";
+
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
+ if (ev.IsNonZero()) {
+ const auto native_type = GetUnionElement(ev, true, opts_);
+ code_.SetValue("NATIVE_TYPE", native_type);
+ code_ += " case {{NATIVE_ID}}: {";
+ code_ +=
+ " return *(reinterpret_cast<const {{NATIVE_TYPE}} "
+ "*>(lhs.value)) ==";
+ code_ +=
+ " *(reinterpret_cast<const {{NATIVE_TYPE}} "
+ "*>(rhs.value));";
+ code_ += " }";
+ } else {
+ code_ += " case {{NATIVE_ID}}: {";
+ code_ += " return true;"; // "NONE" enum value.
+ code_ += " }";
+ }
+ }
+ code_ += " default: {";
+ code_ += " return false;";
+ code_ += " }";
+ code_ += " }";
+ code_ += "}";
+
+ code_ += "";
+ code_ +=
+ "inline bool operator!=(const {{NAME}}Union &lhs, const "
+ "{{NAME}}Union &rhs) {";
+ code_ += " return !(lhs == rhs);";
+ code_ += "}";
+ code_ += "";
+ }
+ }
+
+ if (enum_def.is_union) {
+ code_ += UnionVerifySignature(enum_def) + ";";
+ code_ += UnionVectorVerifySignature(enum_def) + ";";
+ code_ += "";
+ }
+ }
+
+ void GenUnionPost(const EnumDef &enum_def) {
+ // Generate a verifier function for this union that can be called by the
+ // table verifier functions. It uses a switch case to select a specific
+ // verifier function to call, this should be safe even if the union type
+ // has been corrupted, since the verifiers will simply fail when called
+ // on the wrong type.
+ code_.SetValue("ENUM_NAME", Name(enum_def));
+
+ code_ += "inline " + UnionVerifySignature(enum_def) + " {";
+ code_ += " switch (type) {";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ const auto &ev = **it;
+ code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
+
+ if (ev.IsNonZero()) {
+ code_.SetValue("TYPE", GetUnionElement(ev, false, opts_));
+ code_ += " case {{LABEL}}: {";
+ auto getptr =
+ " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
+ if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
+ if (ev.union_type.struct_def->fixed) {
+ code_ +=
+ " return verifier.Verify<{{TYPE}}>(static_cast<const "
+ "uint8_t *>(obj), 0);";
+ } else {
+ code_ += getptr;
+ code_ += " return verifier.VerifyTable(ptr);";
+ }
+ } else if (IsString(ev.union_type)) {
+ code_ += getptr;
+ code_ += " return verifier.VerifyString(ptr);";
+ } else {
+ FLATBUFFERS_ASSERT(false);
+ }
+ code_ += " }";
+ } else {
+ code_ += " case {{LABEL}}: {";
+ code_ += " return true;"; // "NONE" enum value.
+ code_ += " }";
+ }
+ }
+ code_ += " default: return true;"; // unknown values are OK.
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+
+ code_ += "inline " + UnionVectorVerifySignature(enum_def) + " {";
+ code_ += " if (!values || !types) return !values && !types;";
+ code_ += " if (values->size() != types->size()) return false;";
+ code_ += " for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {";
+ code_ += " if (!Verify" + Name(enum_def) + "(";
+ code_ += " verifier, values->Get(i), types->GetEnum<" +
+ Name(enum_def) + ">(i))) {";
+ code_ += " return false;";
+ code_ += " }";
+ code_ += " }";
+ code_ += " return true;";
+ code_ += "}";
+ code_ += "";
+
+ if (opts_.generate_object_based_api) {
+ // Generate union Unpack() and Pack() functions.
+ code_ += "inline " + UnionUnPackSignature(enum_def, false) + " {";
+ code_ += " switch (type) {";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ if (ev.IsZero()) { continue; }
+
+ code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
+ code_.SetValue("TYPE", GetUnionElement(ev, false, opts_));
+ code_ += " case {{LABEL}}: {";
+ code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
+ if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
+ if (ev.union_type.struct_def->fixed) {
+ code_ += " return new " +
+ WrapInNameSpace(*ev.union_type.struct_def) + "(*ptr);";
+ } else {
+ code_ += " return ptr->UnPack(resolver);";
+ }
+ } else if (IsString(ev.union_type)) {
+ code_ += " return new std::string(ptr->c_str(), ptr->size());";
+ } else {
+ FLATBUFFERS_ASSERT(false);
+ }
+ code_ += " }";
+ }
+ code_ += " default: return nullptr;";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+
+ code_ += "inline " + UnionPackSignature(enum_def, false) + " {";
+ code_ += " switch (type) {";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ auto &ev = **it;
+ if (ev.IsZero()) { continue; }
+
+ code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
+ code_.SetValue("TYPE", GetUnionElement(ev, true, opts_));
+ code_ += " case {{LABEL}}: {";
+ code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(value);";
+ if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
+ if (ev.union_type.struct_def->fixed) {
+ code_ += " return _fbb.CreateStruct(*ptr).Union();";
+ } else {
+ code_.SetValue("NAME", ev.union_type.struct_def->name);
+ code_ +=
+ " return Create{{NAME}}(_fbb, ptr, _rehasher).Union();";
+ }
+ } else if (IsString(ev.union_type)) {
+ code_ += " return _fbb.CreateString(*ptr).Union();";
+ } else {
+ FLATBUFFERS_ASSERT(false);
+ }
+ code_ += " }";
+ }
+ code_ += " default: return 0;";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+
+ // Union copy constructor
+ code_ +=
+ "inline {{ENUM_NAME}}Union::{{ENUM_NAME}}Union(const "
+ "{{ENUM_NAME}}Union &u) : type(u.type), value(nullptr) {";
+ code_ += " switch (type) {";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ if (ev.IsZero()) { continue; }
+ code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
+ code_.SetValue("TYPE", GetUnionElement(ev, true, opts_));
+ code_ += " case {{LABEL}}: {";
+ bool copyable = true;
+ if (ev.union_type.base_type == BASE_TYPE_STRUCT &&
+ !ev.union_type.struct_def->fixed) {
+ // Don't generate code to copy if table is not copyable.
+ // TODO(wvo): make tables copyable instead.
+ for (auto fit = ev.union_type.struct_def->fields.vec.begin();
+ fit != ev.union_type.struct_def->fields.vec.end(); ++fit) {
+ const auto &field = **fit;
+ if (!field.deprecated && field.value.type.struct_def &&
+ !field.native_inline) {
+ copyable = false;
+ break;
+ }
+ }
+ }
+ if (copyable) {
+ code_ +=
+ " value = new {{TYPE}}(*reinterpret_cast<{{TYPE}} *>"
+ "(u.value));";
+ } else {
+ code_ +=
+ " FLATBUFFERS_ASSERT(false); // {{TYPE}} not copyable.";
+ }
+ code_ += " break;";
+ code_ += " }";
+ }
+ code_ += " default:";
+ code_ += " break;";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+
+ // Union Reset() function.
+ FLATBUFFERS_ASSERT(enum_def.Lookup("NONE"));
+ code_.SetValue("NONE", GetEnumValUse(enum_def, *enum_def.Lookup("NONE")));
+
+ code_ += "inline void {{ENUM_NAME}}Union::Reset() {";
+ code_ += " switch (type) {";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ if (ev.IsZero()) { continue; }
+ code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
+ code_.SetValue("TYPE", GetUnionElement(ev, true, opts_));
+ code_ += " case {{LABEL}}: {";
+ code_ += " auto ptr = reinterpret_cast<{{TYPE}} *>(value);";
+ code_ += " delete ptr;";
+ code_ += " break;";
+ code_ += " }";
+ }
+ code_ += " default: break;";
+ code_ += " }";
+ code_ += " value = nullptr;";
+ code_ += " type = {{NONE}};";
+ code_ += "}";
+ code_ += "";
+ }
+ }
+
+ // Generates a value with optionally a cast applied if the field has a
+ // different underlying type from its interface type (currently only the
+ // case for enums. "from" specify the direction, true meaning from the
+ // underlying type to the interface type.
+ std::string GenUnderlyingCast(const FieldDef &field, bool from,
+ const std::string &val) {
+ if (from && field.value.type.base_type == BASE_TYPE_BOOL) {
+ return val + " != 0";
+ } else if ((field.value.type.enum_def &&
+ IsScalar(field.value.type.base_type)) ||
+ field.value.type.base_type == BASE_TYPE_BOOL) {
+ return "static_cast<" + GenTypeBasic(field.value.type, from) + ">(" +
+ val + ")";
+ } else {
+ return val;
+ }
+ }
+
+ std::string GenFieldOffsetName(const FieldDef &field) {
+ std::string uname = Name(field);
+ std::transform(uname.begin(), uname.end(), uname.begin(), CharToUpper);
+ return "VT_" + uname;
+ }
+
+ void GenFullyQualifiedNameGetter(const StructDef &struct_def,
+ const std::string &name) {
+ if (!opts_.generate_name_strings) { return; }
+ auto fullname = struct_def.defined_namespace->GetFullyQualifiedName(name);
+ code_.SetValue("NAME", fullname);
+ code_.SetValue("CONSTEXPR", "FLATBUFFERS_CONSTEXPR");
+ code_ += " static {{CONSTEXPR}} const char *GetFullyQualifiedName() {";
+ code_ += " return \"{{NAME}}\";";
+ code_ += " }";
+ }
+
+ std::string GenDefaultConstant(const FieldDef &field) {
+ if (IsFloat(field.value.type.base_type))
+ return float_const_gen_.GenFloatConstant(field);
+ else
+ return NumToStringCpp(field.value.constant, field.value.type.base_type);
+ }
+
+ std::string GetDefaultScalarValue(const FieldDef &field, bool is_ctor) {
+ const auto &type = field.value.type;
+ if (field.IsScalarOptional()) {
+ return GenOptionalNull();
+ } else if (type.enum_def && IsScalar(type.base_type)) {
+ auto ev = type.enum_def->FindByValue(field.value.constant);
+ if (ev) {
+ return WrapInNameSpace(type.enum_def->defined_namespace,
+ GetEnumValUse(*type.enum_def, *ev));
+ } else {
+ return GenUnderlyingCast(
+ field, true, NumToStringCpp(field.value.constant, type.base_type));
+ }
+ } else if (type.base_type == BASE_TYPE_BOOL) {
+ return field.value.constant == "0" ? "false" : "true";
+ } else if (field.attributes.Lookup("cpp_type")) {
+ if (is_ctor) {
+ if (PtrType(&field) == "naked") {
+ return "nullptr";
+ } else {
+ return "";
+ }
+ } else {
+ return "0";
+ }
+ } else {
+ return GenDefaultConstant(field);
+ }
+ }
+
+ void GenParam(const FieldDef &field, bool direct, const char *prefix) {
+ code_.SetValue("PRE", prefix);
+ code_.SetValue("PARAM_NAME", Name(field));
+ if (direct && IsString(field.value.type)) {
+ code_.SetValue("PARAM_TYPE", "const char *");
+ code_.SetValue("PARAM_VALUE", "nullptr");
+ } else if (direct && IsVector(field.value.type)) {
+ const auto vtype = field.value.type.VectorType();
+ std::string type;
+ if (IsStruct(vtype)) {
+ type = WrapInNameSpace(*vtype.struct_def);
+ } else {
+ type = GenTypeWire(vtype, "", VectorElementUserFacing(vtype));
+ }
+ if (TypeHasKey(vtype)) {
+ code_.SetValue("PARAM_TYPE", "std::vector<" + type + "> *");
+ } else {
+ code_.SetValue("PARAM_TYPE", "const std::vector<" + type + "> *");
+ }
+ code_.SetValue("PARAM_VALUE", "nullptr");
+ } else {
+ const auto &type = field.value.type;
+ code_.SetValue("PARAM_VALUE", GetDefaultScalarValue(field, false));
+ if (field.IsScalarOptional())
+ code_.SetValue("PARAM_TYPE", GenOptionalDecl(type) + " ");
+ else
+ code_.SetValue("PARAM_TYPE", GenTypeWire(type, " ", true));
+ }
+ code_ += "{{PRE}}{{PARAM_TYPE}}{{PARAM_NAME}} = {{PARAM_VALUE}}\\";
+ }
+
+ // Generate a member, including a default value for scalars and raw pointers.
+ void GenMember(const FieldDef &field) {
+ if (!field.deprecated && // Deprecated fields won't be accessible.
+ field.value.type.base_type != BASE_TYPE_UTYPE &&
+ (field.value.type.base_type != BASE_TYPE_VECTOR ||
+ field.value.type.element != BASE_TYPE_UTYPE)) {
+ auto type = GenTypeNative(field.value.type, false, field);
+ auto cpp_type = field.attributes.Lookup("cpp_type");
+ auto full_type =
+ (cpp_type
+ ? (IsVector(field.value.type)
+ ? "std::vector<" +
+ GenTypeNativePtr(cpp_type->constant, &field,
+ false) +
+ "> "
+ : GenTypeNativePtr(cpp_type->constant, &field, false))
+ : type + " ");
+ // Generate default member initializers for >= C++11.
+ std::string field_di = "";
+ if (opts_.g_cpp_std >= cpp::CPP_STD_11) {
+ field_di = "{}";
+ auto native_default = field.attributes.Lookup("native_default");
+ // Scalar types get parsed defaults, raw pointers get nullptrs.
+ if (IsScalar(field.value.type.base_type)) {
+ field_di =
+ " = " + (native_default ? std::string(native_default->constant)
+ : GetDefaultScalarValue(field, true));
+ } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
+ if (IsStruct(field.value.type) && native_default) {
+ field_di = " = " + native_default->constant;
+ }
+ }
+ }
+ code_.SetValue("FIELD_TYPE", full_type);
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("FIELD_DI", field_di);
+ code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}{{FIELD_DI}};";
+ }
+ }
+
+ // Generate the default constructor for this struct. Properly initialize all
+ // scalar members with default values.
+ void GenDefaultConstructor(const StructDef &struct_def) {
+ code_.SetValue("NATIVE_NAME",
+ NativeName(Name(struct_def), &struct_def, opts_));
+ // In >= C++11, default member initializers are generated.
+ if (opts_.g_cpp_std >= cpp::CPP_STD_11) { return; }
+ std::string initializer_list;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (!field.deprecated && // Deprecated fields won't be accessible.
+ field.value.type.base_type != BASE_TYPE_UTYPE) {
+ auto cpp_type = field.attributes.Lookup("cpp_type");
+ auto native_default = field.attributes.Lookup("native_default");
+ // Scalar types get parsed defaults, raw pointers get nullptrs.
+ if (IsScalar(field.value.type.base_type)) {
+ if (!initializer_list.empty()) { initializer_list += ",\n "; }
+ initializer_list += Name(field);
+ initializer_list +=
+ "(" +
+ (native_default ? std::string(native_default->constant)
+ : GetDefaultScalarValue(field, true)) +
+ ")";
+ } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
+ if (IsStruct(field.value.type)) {
+ if (native_default) {
+ if (!initializer_list.empty()) {
+ initializer_list += ",\n ";
+ }
+ initializer_list +=
+ Name(field) + "(" + native_default->constant + ")";
+ }
+ }
+ } else if (cpp_type && field.value.type.base_type != BASE_TYPE_VECTOR) {
+ if (!initializer_list.empty()) { initializer_list += ",\n "; }
+ initializer_list += Name(field) + "(0)";
+ }
+ }
+ }
+ if (!initializer_list.empty()) {
+ initializer_list = "\n : " + initializer_list;
+ }
+
+ code_.SetValue("INIT_LIST", initializer_list);
+
+ code_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {";
+ code_ += " }";
+ }
+
+ void GenCompareOperator(const StructDef &struct_def,
+ std::string accessSuffix = "") {
+ std::string compare_op;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (!field.deprecated && // Deprecated fields won't be accessible.
+ field.value.type.base_type != BASE_TYPE_UTYPE &&
+ (field.value.type.base_type != BASE_TYPE_VECTOR ||
+ field.value.type.element != BASE_TYPE_UTYPE)) {
+ if (!compare_op.empty()) { compare_op += " &&\n "; }
+ auto accessor = Name(field) + accessSuffix;
+ compare_op += "(lhs." + accessor + " == rhs." + accessor + ")";
+ }
+ }
+
+ std::string cmp_lhs;
+ std::string cmp_rhs;
+ if (compare_op.empty()) {
+ cmp_lhs = "";
+ cmp_rhs = "";
+ compare_op = " return true;";
+ } else {
+ cmp_lhs = "lhs";
+ cmp_rhs = "rhs";
+ compare_op = " return\n " + compare_op + ";";
+ }
+
+ code_.SetValue("CMP_OP", compare_op);
+ code_.SetValue("CMP_LHS", cmp_lhs);
+ code_.SetValue("CMP_RHS", cmp_rhs);
+ code_ += "";
+ code_ +=
+ "inline bool operator==(const {{NATIVE_NAME}} &{{CMP_LHS}}, const "
+ "{{NATIVE_NAME}} &{{CMP_RHS}}) {";
+ code_ += "{{CMP_OP}}";
+ code_ += "}";
+
+ code_ += "";
+ code_ +=
+ "inline bool operator!=(const {{NATIVE_NAME}} &lhs, const "
+ "{{NATIVE_NAME}} &rhs) {";
+ code_ += " return !(lhs == rhs);";
+ code_ += "}";
+ code_ += "";
+ }
+
+ void GenOperatorNewDelete(const StructDef &struct_def) {
+ if (auto native_custom_alloc =
+ struct_def.attributes.Lookup("native_custom_alloc")) {
+ code_ += " inline void *operator new (std::size_t count) {";
+ code_ += " return " + native_custom_alloc->constant +
+ "<{{NATIVE_NAME}}>().allocate(count / sizeof({{NATIVE_NAME}}));";
+ code_ += " }";
+ code_ += " inline void operator delete (void *ptr) {";
+ code_ += " return " + native_custom_alloc->constant +
+ "<{{NATIVE_NAME}}>().deallocate(static_cast<{{NATIVE_NAME}}*>("
+ "ptr),1);";
+ code_ += " }";
+ }
+ }
+
+ void GenNativeTable(const StructDef &struct_def) {
+ const auto native_name = NativeName(Name(struct_def), &struct_def, opts_);
+ code_.SetValue("STRUCT_NAME", Name(struct_def));
+ code_.SetValue("NATIVE_NAME", native_name);
+
+ // Generate a C++ object that can hold an unpacked version of this table.
+ code_ += "struct {{NATIVE_NAME}} : public flatbuffers::NativeTable {";
+ code_ += " typedef {{STRUCT_NAME}} TableType;";
+ GenFullyQualifiedNameGetter(struct_def, native_name);
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ GenMember(**it);
+ }
+ GenOperatorNewDelete(struct_def);
+ GenDefaultConstructor(struct_def);
+ code_ += "};";
+ if (opts_.gen_compare) GenCompareOperator(struct_def);
+ code_ += "";
+ }
+
+ // Generate the code to call the appropriate Verify function(s) for a field.
+ void GenVerifyCall(const FieldDef &field, const char *prefix) {
+ code_.SetValue("PRE", prefix);
+ code_.SetValue("NAME", Name(field));
+ code_.SetValue("REQUIRED", field.IsRequired() ? "Required" : "");
+ code_.SetValue("SIZE", GenTypeSize(field.value.type));
+ code_.SetValue("OFFSET", GenFieldOffsetName(field));
+ if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) {
+ code_ +=
+ "{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, {{OFFSET}})\\";
+ } else {
+ code_ += "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\";
+ }
+
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_UNION: {
+ code_.SetValue("ENUM_NAME", field.value.type.enum_def->name);
+ code_.SetValue("SUFFIX", UnionTypeFieldSuffix());
+ code_ +=
+ "{{PRE}}Verify{{ENUM_NAME}}(verifier, {{NAME}}(), "
+ "{{NAME}}{{SUFFIX}}())\\";
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ if (!field.value.type.struct_def->fixed) {
+ code_ += "{{PRE}}verifier.VerifyTable({{NAME}}())\\";
+ }
+ break;
+ }
+ case BASE_TYPE_STRING: {
+ code_ += "{{PRE}}verifier.VerifyString({{NAME}}())\\";
+ break;
+ }
+ case BASE_TYPE_VECTOR: {
+ code_ += "{{PRE}}verifier.VerifyVector({{NAME}}())\\";
+
+ switch (field.value.type.element) {
+ case BASE_TYPE_STRING: {
+ code_ += "{{PRE}}verifier.VerifyVectorOfStrings({{NAME}}())\\";
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ if (!field.value.type.struct_def->fixed) {
+ code_ += "{{PRE}}verifier.VerifyVectorOfTables({{NAME}}())\\";
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ code_.SetValue("ENUM_NAME", field.value.type.enum_def->name);
+ code_ +=
+ "{{PRE}}Verify{{ENUM_NAME}}Vector(verifier, {{NAME}}(), "
+ "{{NAME}}_type())\\";
+ break;
+ }
+ default: break;
+ }
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
+
+ // Generate CompareWithValue method for a key field.
+ void GenKeyFieldMethods(const FieldDef &field) {
+ FLATBUFFERS_ASSERT(field.key);
+ const bool is_string = (IsString(field.value.type));
+
+ code_ += " bool KeyCompareLessThan(const {{STRUCT_NAME}} *o) const {";
+ if (is_string) {
+ // use operator< of flatbuffers::String
+ code_ += " return *{{FIELD_NAME}}() < *o->{{FIELD_NAME}}();";
+ } else {
+ code_ += " return {{FIELD_NAME}}() < o->{{FIELD_NAME}}();";
+ }
+ code_ += " }";
+
+ if (is_string) {
+ code_ += " int KeyCompareWithValue(const char *val) const {";
+ code_ += " return strcmp({{FIELD_NAME}}()->c_str(), val);";
+ code_ += " }";
+ } else {
+ FLATBUFFERS_ASSERT(IsScalar(field.value.type.base_type));
+ auto type = GenTypeBasic(field.value.type, false);
+ if (opts_.scoped_enums && field.value.type.enum_def &&
+ IsScalar(field.value.type.base_type)) {
+ type = GenTypeGet(field.value.type, " ", "const ", " *", true);
+ }
+ // Returns {field<val: -1, field==val: 0, field>val: +1}.
+ code_.SetValue("KEY_TYPE", type);
+ code_ += " int KeyCompareWithValue({{KEY_TYPE}} val) const {";
+ code_ +=
+ " return static_cast<int>({{FIELD_NAME}}() > val) - "
+ "static_cast<int>({{FIELD_NAME}}() < val);";
+ code_ += " }";
+ }
+ }
+
+ void GenTableUnionAsGetters(const FieldDef &field) {
+ const auto &type = field.value.type;
+ auto u = type.enum_def;
+
+ if (!type.enum_def->uses_multiple_type_instances)
+ code_ +=
+ " template<typename T> "
+ "const T *{{NULLABLE_EXT}}{{FIELD_NAME}}_as() const;";
+
+ for (auto u_it = u->Vals().begin(); u_it != u->Vals().end(); ++u_it) {
+ auto &ev = **u_it;
+ if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
+ auto full_struct_name = GetUnionElement(ev, false, opts_);
+
+ // @TODO: Mby make this decisions more universal? How?
+ code_.SetValue("U_GET_TYPE",
+ EscapeKeyword(field.name + UnionTypeFieldSuffix()));
+ code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(u->defined_namespace,
+ GetEnumValUse(*u, ev)));
+ code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
+ code_.SetValue("U_FIELD_NAME", Name(field) + "_as_" + Name(ev));
+ code_.SetValue("U_NULLABLE", NullableExtension());
+
+ // `const Type *union_name_asType() const` accessor.
+ code_ += " {{U_FIELD_TYPE}}{{U_NULLABLE}}{{U_FIELD_NAME}}() const {";
+ code_ +=
+ " return {{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}} ? "
+ "static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) "
+ ": nullptr;";
+ code_ += " }";
+ }
+ }
+
+ void GenTableFieldGetter(const FieldDef &field) {
+ const auto &type = field.value.type;
+ const auto offset_str = GenFieldOffsetName(field);
+
+ GenComment(field.doc_comment, " ");
+ // Call a different accessor for pointers, that indirects.
+ if (false == field.IsScalarOptional()) {
+ const bool is_scalar = IsScalar(type.base_type);
+ std::string accessor;
+ if (is_scalar)
+ accessor = "GetField<";
+ else if (IsStruct(type))
+ accessor = "GetStruct<";
+ else
+ accessor = "GetPointer<";
+ auto offset_type = GenTypeGet(type, "", "const ", " *", false);
+ auto call = accessor + offset_type + ">(" + offset_str;
+ // Default value as second arg for non-pointer types.
+ if (is_scalar) { call += ", " + GenDefaultConstant(field); }
+ call += ")";
+
+ std::string afterptr = " *" + NullableExtension();
+ code_.SetValue("FIELD_TYPE",
+ GenTypeGet(type, " ", "const ", afterptr.c_str(), true));
+ code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, call));
+ code_.SetValue("NULLABLE_EXT", NullableExtension());
+ code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
+ code_ += " return {{FIELD_VALUE}};";
+ code_ += " }";
+ } else {
+ auto wire_type = GenTypeBasic(type, false);
+ auto face_type = GenTypeBasic(type, true);
+ auto opt_value = "GetOptional<" + wire_type + ", " + face_type + ">(" +
+ offset_str + ")";
+ code_.SetValue("FIELD_TYPE", GenOptionalDecl(type));
+ code_ += " {{FIELD_TYPE}} {{FIELD_NAME}}() const {";
+ code_ += " return " + opt_value + ";";
+ code_ += " }";
+ }
+
+ if (type.base_type == BASE_TYPE_UNION) { GenTableUnionAsGetters(field); }
+ }
+
+ void GenTableFieldType(const FieldDef &field) {
+ const auto &type = field.value.type;
+ const auto offset_str = GenFieldOffsetName(field);
+ if (!field.IsScalarOptional()) {
+ std::string afterptr = " *" + NullableExtension();
+ code_.SetValue("FIELD_TYPE",
+ GenTypeGet(type, "", "const ", afterptr.c_str(), true));
+ code_ += " {{FIELD_TYPE}}\\";
+ } else {
+ code_.SetValue("FIELD_TYPE", GenOptionalDecl(type));
+ code_ += " {{FIELD_TYPE}}\\";
+ }
+ }
+
+ void GenStructFieldType(const FieldDef &field) {
+ const auto is_array = IsArray(field.value.type);
+ std::string field_type =
+ GenTypeGet(field.value.type, "", is_array ? "" : "const ",
+ is_array ? "" : " &", true);
+ code_.SetValue("FIELD_TYPE", field_type);
+ code_ += " {{FIELD_TYPE}}\\";
+ }
+
+ void GenFieldTypeHelper(const StructDef &struct_def) {
+ if (struct_def.fields.vec.empty()) { return; }
+ code_ += " template<size_t Index>";
+ code_ += " using FieldType = \\";
+ code_ += "decltype(std::declval<type>().get_field<Index>());";
+ }
+
+ void GenIndexBasedFieldGetter(const StructDef &struct_def) {
+ if (struct_def.fields.vec.empty()) { return; }
+ code_ += " template<size_t Index>";
+ code_ += " auto get_field() const {";
+
+ size_t index = 0;
+ bool need_else = false;
+ // Generate one index-based getter for each field.
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) {
+ // Deprecated fields won't be accessible.
+ continue;
+ }
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("FIELD_INDEX",
+ std::to_string(static_cast<long long>(index++)));
+ if (need_else) {
+ code_ += " else \\";
+ } else {
+ code_ += " \\";
+ }
+ need_else = true;
+ code_ += "if constexpr (Index == {{FIELD_INDEX}}) \\";
+ code_ += "return {{FIELD_NAME}}();";
+ }
+ code_ += " else static_assert(Index != Index, \"Invalid Field Index\");";
+ code_ += " }";
+ }
+
+ // Sample for Vec3:
+ //
+ // static constexpr std::array<const char *, 3> field_names = {
+ // "x",
+ // "y",
+ // "z"
+ // };
+ //
+ void GenFieldNames(const StructDef &struct_def) {
+ auto non_deprecated_field_count = std::count_if(
+ struct_def.fields.vec.begin(), struct_def.fields.vec.end(),
+ [](const FieldDef *field) { return !field->deprecated; });
+ code_ += " static constexpr std::array<\\";
+ code_.SetValue(
+ "FIELD_COUNT",
+ std::to_string(static_cast<long long>(non_deprecated_field_count)));
+ code_ += "const char *, {{FIELD_COUNT}}> field_names = {\\";
+ if (struct_def.fields.vec.empty()) {
+ code_ += "};";
+ return;
+ }
+ code_ += "";
+ // Generate the field_names elements.
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) {
+ // Deprecated fields won't be accessible.
+ continue;
+ }
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_ += " \"{{FIELD_NAME}}\"\\";
+ if (it + 1 != struct_def.fields.vec.end()) { code_ += ","; }
+ }
+ code_ += "\n };";
+ }
+
+ void GenFieldsNumber(const StructDef &struct_def) {
+ auto non_deprecated_field_count = std::count_if(
+ struct_def.fields.vec.begin(), struct_def.fields.vec.end(),
+ [](const FieldDef *field) { return !field->deprecated; });
+ code_.SetValue(
+ "FIELD_COUNT",
+ std::to_string(static_cast<long long>(non_deprecated_field_count)));
+ code_ += " static constexpr size_t fields_number = {{FIELD_COUNT}};";
+ }
+
+ void GenTraitsStruct(const StructDef &struct_def) {
+ code_.SetValue(
+ "FULLY_QUALIFIED_NAME",
+ struct_def.defined_namespace->GetFullyQualifiedName(Name(struct_def)));
+ code_ += "struct {{STRUCT_NAME}}::Traits {";
+ code_ += " using type = {{STRUCT_NAME}};";
+ if (!struct_def.fixed) {
+ // We have a table and not a struct.
+ code_ += " static auto constexpr Create = Create{{STRUCT_NAME}};";
+ }
+ if (opts_.cpp_static_reflection) {
+ code_ += " static constexpr auto name = \"{{STRUCT_NAME}}\";";
+ code_ +=
+ " static constexpr auto fully_qualified_name = "
+ "\"{{FULLY_QUALIFIED_NAME}}\";";
+ GenFieldNames(struct_def);
+ GenFieldTypeHelper(struct_def);
+ GenFieldsNumber(struct_def);
+ }
+ code_ += "};";
+ code_ += "";
+ }
+
+ void GenTableFieldSetter(const FieldDef &field) {
+ const auto &type = field.value.type;
+ const bool is_scalar = IsScalar(type.base_type);
+ if (is_scalar && IsUnion(type))
+ return; // changing of a union's type is forbidden
+
+ auto offset_str = GenFieldOffsetName(field);
+ if (is_scalar) {
+ const auto wire_type = GenTypeWire(type, "", false);
+ code_.SetValue("SET_FN", "SetField<" + wire_type + ">");
+ code_.SetValue("OFFSET_NAME", offset_str);
+ code_.SetValue("FIELD_TYPE", GenTypeBasic(type, true));
+ code_.SetValue("FIELD_VALUE",
+ GenUnderlyingCast(field, false, "_" + Name(field)));
+
+ code_ +=
+ " bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} "
+ "_{{FIELD_NAME}}) {";
+ if (false == field.IsScalarOptional()) {
+ code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field));
+ code_ +=
+ " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, "
+ "{{DEFAULT_VALUE}});";
+ } else {
+ code_ += " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}});";
+ }
+ code_ += " }";
+ } else {
+ auto postptr = " *" + NullableExtension();
+ auto wire_type = GenTypeGet(type, " ", "", postptr.c_str(), true);
+ std::string accessor = IsStruct(type) ? "GetStruct<" : "GetPointer<";
+ auto underlying = accessor + wire_type + ">(" + offset_str + ")";
+ code_.SetValue("FIELD_TYPE", wire_type);
+ code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, underlying));
+
+ code_ += " {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {";
+ code_ += " return {{FIELD_VALUE}};";
+ code_ += " }";
+ }
+ }
+
+ // Generate an accessor struct, builder structs & function for a table.
+ void GenTable(const StructDef &struct_def) {
+ if (opts_.generate_object_based_api) { GenNativeTable(struct_def); }
+
+ // Generate an accessor struct, with methods of the form:
+ // type name() const { return GetField<type>(offset, defaultval); }
+ GenComment(struct_def.doc_comment);
+
+ code_.SetValue("STRUCT_NAME", Name(struct_def));
+ code_ +=
+ "struct {{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS"
+ " : private flatbuffers::Table {";
+ if (opts_.generate_object_based_api) {
+ code_ += " typedef {{NATIVE_NAME}} NativeTableType;";
+ }
+ code_ += " typedef {{STRUCT_NAME}}Builder Builder;";
+ if (opts_.g_cpp_std >= cpp::CPP_STD_17) { code_ += " struct Traits;"; }
+ if (opts_.mini_reflect != IDLOptions::kNone) {
+ code_ +=
+ " static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
+ code_ += " return {{STRUCT_NAME}}TypeTable();";
+ code_ += " }";
+ }
+
+ GenFullyQualifiedNameGetter(struct_def, Name(struct_def));
+
+ // Generate field id constants.
+ if (struct_def.fields.vec.size() > 0) {
+ // We need to add a trailing comma to all elements except the last one as
+ // older versions of gcc complain about this.
+ code_.SetValue("SEP", "");
+ code_ +=
+ " enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) {
+ // Deprecated fields won't be accessible.
+ continue;
+ }
+
+ code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field));
+ code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
+ code_ += "{{SEP}} {{OFFSET_NAME}} = {{OFFSET_VALUE}}\\";
+ code_.SetValue("SEP", ",\n");
+ }
+ code_ += "";
+ code_ += " };";
+ }
+
+ // Generate the accessors.
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) {
+ // Deprecated fields won't be accessible.
+ continue;
+ }
+
+ code_.SetValue("FIELD_NAME", Name(field));
+ GenTableFieldGetter(field);
+ if (opts_.mutable_buffer) { GenTableFieldSetter(field); }
+
+ auto nested = field.attributes.Lookup("nested_flatbuffer");
+ if (nested) {
+ std::string qualified_name = nested->constant;
+ auto nested_root = parser_.LookupStruct(nested->constant);
+ if (nested_root == nullptr) {
+ qualified_name = parser_.current_namespace_->GetFullyQualifiedName(
+ nested->constant);
+ nested_root = parser_.LookupStruct(qualified_name);
+ }
+ FLATBUFFERS_ASSERT(nested_root); // Guaranteed to exist by parser.
+ (void)nested_root;
+ code_.SetValue("CPP_NAME", TranslateNameSpace(qualified_name));
+
+ code_ += " const {{CPP_NAME}} *{{FIELD_NAME}}_nested_root() const {";
+ code_ +=
+ " return "
+ "flatbuffers::GetRoot<{{CPP_NAME}}>({{FIELD_NAME}}()->Data());";
+ code_ += " }";
+ }
+
+ if (field.flexbuffer) {
+ code_ +=
+ " flexbuffers::Reference {{FIELD_NAME}}_flexbuffer_root()"
+ " const {";
+ // Both Data() and size() are const-methods, therefore call order
+ // doesn't matter.
+ code_ +=
+ " return flexbuffers::GetRoot({{FIELD_NAME}}()->Data(), "
+ "{{FIELD_NAME}}()->size());";
+ code_ += " }";
+ }
+
+ // Generate a comparison function for this field if it is a key.
+ if (field.key) { GenKeyFieldMethods(field); }
+ }
+
+ if (opts_.cpp_static_reflection) { GenIndexBasedFieldGetter(struct_def); }
+
+ // Generate a verifier function that can check a buffer from an untrusted
+ // source will never cause reads outside the buffer.
+ code_ += " bool Verify(flatbuffers::Verifier &verifier) const {";
+ code_ += " return VerifyTableStart(verifier)\\";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) { continue; }
+ GenVerifyCall(field, " &&\n ");
+ }
+
+ code_ += " &&\n verifier.EndTable();";
+ code_ += " }";
+
+ if (opts_.generate_object_based_api) {
+ // Generate the UnPack() pre declaration.
+ code_ += " " + TableUnPackSignature(struct_def, true, opts_) + ";";
+ code_ += " " + TableUnPackToSignature(struct_def, true, opts_) + ";";
+ code_ += " " + TablePackSignature(struct_def, true, opts_) + ";";
+ }
+
+ code_ += "};"; // End of table.
+ code_ += "";
+
+ // Explicit specializations for union accessors
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated || field.value.type.base_type != BASE_TYPE_UNION) {
+ continue;
+ }
+
+ auto u = field.value.type.enum_def;
+ if (u->uses_multiple_type_instances) continue;
+
+ code_.SetValue("FIELD_NAME", Name(field));
+
+ for (auto u_it = u->Vals().begin(); u_it != u->Vals().end(); ++u_it) {
+ auto &ev = **u_it;
+ if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
+
+ auto full_struct_name = GetUnionElement(ev, false, opts_);
+
+ code_.SetValue(
+ "U_ELEMENT_TYPE",
+ WrapInNameSpace(u->defined_namespace, GetEnumValUse(*u, ev)));
+ code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
+ code_.SetValue("U_ELEMENT_NAME", full_struct_name);
+ code_.SetValue("U_FIELD_NAME", Name(field) + "_as_" + Name(ev));
+
+ // `template<> const T *union_name_as<T>() const` accessor.
+ code_ +=
+ "template<> "
+ "inline {{U_FIELD_TYPE}}{{STRUCT_NAME}}::{{FIELD_NAME}}_as"
+ "<{{U_ELEMENT_NAME}}>() const {";
+ code_ += " return {{U_FIELD_NAME}}();";
+ code_ += "}";
+ code_ += "";
+ }
+ }
+
+ GenBuilders(struct_def);
+
+ if (opts_.generate_object_based_api) {
+ // Generate a pre-declaration for a CreateX method that works with an
+ // unpacked C++ object.
+ code_ += TableCreateSignature(struct_def, true, opts_) + ";";
+ code_ += "";
+ }
+ }
+
+ // Generate code to force vector alignment. Return empty string for vector
+ // that doesn't need alignment code.
+ std::string GenVectorForceAlign(const FieldDef &field,
+ const std::string &field_size) {
+ FLATBUFFERS_ASSERT(IsVector(field.value.type));
+ // Get the value of the force_align attribute.
+ const auto *force_align = field.attributes.Lookup("force_align");
+ const int align = force_align ? atoi(force_align->constant.c_str()) : 1;
+ // Generate code to do force_align for the vector.
+ if (align > 1) {
+ const auto vtype = field.value.type.VectorType();
+ const auto type = IsStruct(vtype) ? WrapInNameSpace(*vtype.struct_def)
+ : GenTypeWire(vtype, "", false);
+ return "_fbb.ForceVectorAlignment(" + field_size + ", sizeof(" + type +
+ "), " + std::to_string(static_cast<long long>(align)) + ");";
+ }
+ return "";
+ }
+
+ void GenBuilders(const StructDef &struct_def) {
+ code_.SetValue("STRUCT_NAME", Name(struct_def));
+
+ // Generate a builder struct:
+ code_ += "struct {{STRUCT_NAME}}Builder {";
+ code_ += " typedef {{STRUCT_NAME}} Table;";
+ code_ += " flatbuffers::FlatBufferBuilder &fbb_;";
+ code_ += " flatbuffers::uoffset_t start_;";
+
+ bool has_string_or_vector_fields = false;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) continue;
+ const bool is_scalar = IsScalar(field.value.type.base_type);
+ const bool is_default_scalar = is_scalar && !field.IsScalarOptional();
+ const bool is_string = IsString(field.value.type);
+ const bool is_vector = IsVector(field.value.type);
+ if (is_string || is_vector) { has_string_or_vector_fields = true; }
+
+ std::string offset = GenFieldOffsetName(field);
+ std::string name = GenUnderlyingCast(field, false, Name(field));
+ std::string value = is_default_scalar ? GenDefaultConstant(field) : "";
+
+ // Generate accessor functions of the form:
+ // void add_name(type name) {
+ // fbb_.AddElement<type>(offset, name, default);
+ // }
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true));
+ code_.SetValue("ADD_OFFSET", Name(struct_def) + "::" + offset);
+ code_.SetValue("ADD_NAME", name);
+ code_.SetValue("ADD_VALUE", value);
+ if (is_scalar) {
+ const auto type = GenTypeWire(field.value.type, "", false);
+ code_.SetValue("ADD_FN", "AddElement<" + type + ">");
+ } else if (IsStruct(field.value.type)) {
+ code_.SetValue("ADD_FN", "AddStruct");
+ } else {
+ code_.SetValue("ADD_FN", "AddOffset");
+ }
+
+ code_ += " void add_{{FIELD_NAME}}({{FIELD_TYPE}}{{FIELD_NAME}}) {";
+ code_ += " fbb_.{{ADD_FN}}(\\";
+ if (is_default_scalar) {
+ code_ += "{{ADD_OFFSET}}, {{ADD_NAME}}, {{ADD_VALUE}});";
+ } else {
+ code_ += "{{ADD_OFFSET}}, {{ADD_NAME}});";
+ }
+ code_ += " }";
+ }
+
+ // Builder constructor
+ code_ +=
+ " explicit {{STRUCT_NAME}}Builder(flatbuffers::FlatBufferBuilder "
+ "&_fbb)";
+ code_ += " : fbb_(_fbb) {";
+ code_ += " start_ = fbb_.StartTable();";
+ code_ += " }";
+
+ // Finish() function.
+ code_ += " flatbuffers::Offset<{{STRUCT_NAME}}> Finish() {";
+ code_ += " const auto end = fbb_.EndTable(start_);";
+ code_ += " auto o = flatbuffers::Offset<{{STRUCT_NAME}}>(end);";
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (!field.deprecated && field.IsRequired()) {
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field));
+ code_ += " fbb_.Required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}});";
+ }
+ }
+ code_ += " return o;";
+ code_ += " }";
+ code_ += "};";
+ code_ += "";
+
+ // Generate a convenient CreateX function that uses the above builder
+ // to create a table in one go.
+ code_ +=
+ "inline flatbuffers::Offset<{{STRUCT_NAME}}> "
+ "Create{{STRUCT_NAME}}(";
+ code_ += " flatbuffers::FlatBufferBuilder &_fbb\\";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (!field.deprecated) { GenParam(field, false, ",\n "); }
+ }
+ code_ += ") {";
+
+ code_ += " {{STRUCT_NAME}}Builder builder_(_fbb);";
+ for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
+ size; size /= 2) {
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ const auto &field = **it;
+ if (!field.deprecated && (!struct_def.sortbysize ||
+ size == SizeOf(field.value.type.base_type))) {
+ code_.SetValue("FIELD_NAME", Name(field));
+ if (field.IsScalarOptional()) {
+ code_ +=
+ " if({{FIELD_NAME}}) { "
+ "builder_.add_{{FIELD_NAME}}(*{{FIELD_NAME}}); }";
+ } else {
+ code_ += " builder_.add_{{FIELD_NAME}}({{FIELD_NAME}});";
+ }
+ }
+ }
+ }
+ code_ += " return builder_.Finish();";
+ code_ += "}";
+ code_ += "";
+
+ // Definition for type traits for this table type. This allows querying var-
+ // ious compile-time traits of the table.
+ if (opts_.g_cpp_std >= cpp::CPP_STD_17) { GenTraitsStruct(struct_def); }
+
+ // Generate a CreateXDirect function with vector types as parameters
+ if (opts_.cpp_direct_copy && has_string_or_vector_fields) {
+ code_ +=
+ "inline flatbuffers::Offset<{{STRUCT_NAME}}> "
+ "Create{{STRUCT_NAME}}Direct(";
+ code_ += " flatbuffers::FlatBufferBuilder &_fbb\\";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (!field.deprecated) { GenParam(field, true, ",\n "); }
+ }
+ // Need to call "Create" with the struct namespace.
+ const auto qualified_create_name =
+ struct_def.defined_namespace->GetFullyQualifiedName("Create");
+ code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name));
+ code_ += ") {";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (!field.deprecated) {
+ code_.SetValue("FIELD_NAME", Name(field));
+ if (IsString(field.value.type)) {
+ if (!field.shared) {
+ code_.SetValue("CREATE_STRING", "CreateString");
+ } else {
+ code_.SetValue("CREATE_STRING", "CreateSharedString");
+ }
+ code_ +=
+ " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
+ "_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : 0;";
+ } else if (IsVector(field.value.type)) {
+ const std::string force_align_code =
+ GenVectorForceAlign(field, Name(field) + "->size()");
+ if (!force_align_code.empty()) {
+ code_ += " if ({{FIELD_NAME}}) { " + force_align_code + " }";
+ }
+ code_ += " auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? \\";
+ const auto vtype = field.value.type.VectorType();
+ const auto has_key = TypeHasKey(vtype);
+ if (IsStruct(vtype)) {
+ const auto type = WrapInNameSpace(*vtype.struct_def);
+ code_ += (has_key ? "_fbb.CreateVectorOfSortedStructs<"
+ : "_fbb.CreateVectorOfStructs<") +
+ type + ">\\";
+ } else if (has_key) {
+ const auto type = WrapInNameSpace(*vtype.struct_def);
+ code_ += "_fbb.CreateVectorOfSortedTables<" + type + ">\\";
+ } else {
+ const auto type =
+ GenTypeWire(vtype, "", VectorElementUserFacing(vtype));
+ code_ += "_fbb.CreateVector<" + type + ">\\";
+ }
+ code_ +=
+ has_key ? "({{FIELD_NAME}}) : 0;" : "(*{{FIELD_NAME}}) : 0;";
+ }
+ }
+ }
+ code_ += " return {{CREATE_NAME}}{{STRUCT_NAME}}(";
+ code_ += " _fbb\\";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (!field.deprecated) {
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_ += ",\n {{FIELD_NAME}}\\";
+ if (IsString(field.value.type) || IsVector(field.value.type)) {
+ code_ += "__\\";
+ }
+ }
+ }
+ code_ += ");";
+ code_ += "}";
+ code_ += "";
+ }
+ }
+
+ std::string GenUnionUnpackVal(const FieldDef &afield,
+ const char *vec_elem_access,
+ const char *vec_type_access) {
+ auto type_name = WrapInNameSpace(*afield.value.type.enum_def);
+ return type_name + "Union::UnPack(" + "_e" + vec_elem_access + ", " +
+ EscapeKeyword(afield.name + UnionTypeFieldSuffix()) + "()" +
+ vec_type_access + ", _resolver)";
+ }
+
+ std::string GenUnpackVal(const Type &type, const std::string &val,
+ bool invector, const FieldDef &afield) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: {
+ if (FlexibleStringConstructor(&afield)) {
+ return NativeString(&afield) + "(" + val + "->c_str(), " + val +
+ "->size())";
+ } else {
+ return val + "->str()";
+ }
+ }
+ case BASE_TYPE_STRUCT: {
+ if (IsStruct(type)) {
+ const auto &struct_attrs = type.struct_def->attributes;
+ const auto native_type = struct_attrs.Lookup("native_type");
+ if (native_type) {
+ std::string unpack_call = "flatbuffers::UnPack";
+ const auto pack_name = struct_attrs.Lookup("native_type_pack_name");
+ if (pack_name) { unpack_call += pack_name->constant; }
+ unpack_call += "(*" + val + ")";
+ return unpack_call;
+ } else if (invector || afield.native_inline) {
+ return "*" + val;
+ } else {
+ const auto name = WrapInNameSpace(*type.struct_def);
+ const auto ptype = GenTypeNativePtr(name, &afield, true);
+ return ptype + "(new " + name + "(*" + val + "))";
+ }
+ } else {
+ const auto ptype = GenTypeNativePtr(
+ WrapNativeNameInNameSpace(*type.struct_def, opts_), &afield,
+ true);
+ return ptype + "(" + val + "->UnPack(_resolver))";
+ }
+ }
+ case BASE_TYPE_UNION: {
+ return GenUnionUnpackVal(
+ afield, invector ? "->Get(_i)" : "",
+ invector ? ("->GetEnum<" + type.enum_def->name + ">(_i)").c_str()
+ : "");
+ }
+ default: {
+ return val;
+ break;
+ }
+ }
+ }
+
+ std::string GenUnpackFieldStatement(const FieldDef &field,
+ const FieldDef *union_field) {
+ std::string code;
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_VECTOR: {
+ auto name = Name(field);
+ if (field.value.type.element == BASE_TYPE_UTYPE) {
+ name = StripUnionType(Name(field));
+ }
+ code += "{ _o->" + name + ".resize(_e->size()); ";
+ if (!field.value.type.enum_def && !IsBool(field.value.type.element) &&
+ IsOneByte(field.value.type.element)) {
+ // For vectors of bytes, std::copy is used to improve performance.
+ // This doesn't work for:
+ // - enum types because they have to be explicitly static_cast.
+ // - vectors of bool, since they are a template specialization.
+ // - multiple-byte types due to endianness.
+ code +=
+ "std::copy(_e->begin(), _e->end(), _o->" + name + ".begin()); }";
+ } else {
+ std::string indexing;
+ if (field.value.type.enum_def) {
+ indexing += "static_cast<" +
+ WrapInNameSpace(*field.value.type.enum_def) + ">(";
+ }
+ indexing += "_e->Get(_i)";
+ if (field.value.type.enum_def) { indexing += ")"; }
+ if (field.value.type.element == BASE_TYPE_BOOL) {
+ indexing += " != 0";
+ }
+ // Generate code that pushes data from _e to _o in the form:
+ // for (uoffset_t i = 0; i < _e->size(); ++i) {
+ // _o->field.push_back(_e->Get(_i));
+ // }
+ auto access =
+ field.value.type.element == BASE_TYPE_UTYPE
+ ? ".type"
+ : (field.value.type.element == BASE_TYPE_UNION ? ".value"
+ : "");
+
+ code += "for (flatbuffers::uoffset_t _i = 0;";
+ code += " _i < _e->size(); _i++) { ";
+ auto cpp_type = field.attributes.Lookup("cpp_type");
+ if (cpp_type) {
+ // Generate code that resolves the cpp pointer type, of the form:
+ // if (resolver)
+ // (*resolver)(&_o->field, (hash_value_t)(_e));
+ // else
+ // _o->field = nullptr;
+ code += "//vector resolver, " + PtrType(&field) + "\n";
+ code += "if (_resolver) ";
+ code += "(*_resolver)";
+ code += "(reinterpret_cast<void **>(&_o->" + name + "[_i]" +
+ access + "), ";
+ code +=
+ "static_cast<flatbuffers::hash_value_t>(" + indexing + "));";
+ if (PtrType(&field) == "naked") {
+ code += " else ";
+ code += "_o->" + name + "[_i]" + access + " = nullptr";
+ } else {
+ // code += " else ";
+ // code += "_o->" + name + "[_i]" + access + " = " +
+ // GenTypeNativePtr(cpp_type->constant, &field, true) + "();";
+ code += "/* else do nothing */";
+ }
+ } else {
+ code += "_o->" + name + "[_i]" + access + " = ";
+ code += GenUnpackVal(field.value.type.VectorType(), indexing, true,
+ field);
+ }
+ code += "; } }";
+ }
+ break;
+ }
+ case BASE_TYPE_UTYPE: {
+ FLATBUFFERS_ASSERT(union_field->value.type.base_type ==
+ BASE_TYPE_UNION);
+ // Generate code that sets the union type, of the form:
+ // _o->field.type = _e;
+ code += "_o->" + union_field->name + ".type = _e;";
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ // Generate code that sets the union value, of the form:
+ // _o->field.value = Union::Unpack(_e, field_type(), resolver);
+ code += "_o->" + Name(field) + ".value = ";
+ code += GenUnionUnpackVal(field, "", "");
+ code += ";";
+ break;
+ }
+ default: {
+ auto cpp_type = field.attributes.Lookup("cpp_type");
+ if (cpp_type) {
+ // Generate code that resolves the cpp pointer type, of the form:
+ // if (resolver)
+ // (*resolver)(&_o->field, (hash_value_t)(_e));
+ // else
+ // _o->field = nullptr;
+ code += "//scalar resolver, " + PtrType(&field) + " \n";
+ code += "if (_resolver) ";
+ code += "(*_resolver)";
+ code += "(reinterpret_cast<void **>(&_o->" + Name(field) + "), ";
+ code += "static_cast<flatbuffers::hash_value_t>(_e));";
+ if (PtrType(&field) == "naked") {
+ code += " else ";
+ code += "_o->" + Name(field) + " = nullptr;";
+ } else {
+ // code += " else ";
+ // code += "_o->" + Name(field) + " = " +
+ // GenTypeNativePtr(cpp_type->constant, &field, true) + "();";
+ code += "/* else do nothing */;";
+ }
+ } else {
+ // Generate code for assigning the value, of the form:
+ // _o->field = value;
+ code += "_o->" + Name(field) + " = ";
+ code += GenUnpackVal(field.value.type, "_e", false, field) + ";";
+ }
+ break;
+ }
+ }
+ return code;
+ }
+
+ std::string GenCreateParam(const FieldDef &field) {
+ std::string value = "_o->";
+ if (field.value.type.base_type == BASE_TYPE_UTYPE) {
+ value += StripUnionType(Name(field));
+ value += ".type";
+ } else {
+ value += Name(field);
+ }
+ if (field.value.type.base_type != BASE_TYPE_VECTOR &&
+ field.attributes.Lookup("cpp_type")) {
+ auto type = GenTypeBasic(field.value.type, false);
+ value =
+ "_rehasher ? "
+ "static_cast<" +
+ type + ">((*_rehasher)(" + value + GenPtrGet(field) + ")) : 0";
+ }
+
+ std::string code;
+ switch (field.value.type.base_type) {
+ // String fields are of the form:
+ // _fbb.CreateString(_o->field)
+ // or
+ // _fbb.CreateSharedString(_o->field)
+ case BASE_TYPE_STRING: {
+ if (!field.shared) {
+ code += "_fbb.CreateString(";
+ } else {
+ code += "_fbb.CreateSharedString(";
+ }
+ code += value;
+ code.push_back(')');
+
+ // For optional fields, check to see if there actually is any data
+ // in _o->field before attempting to access it. If there isn't,
+ // depending on set_empty_strings_to_null either set it to 0 or an empty
+ // string.
+ if (!field.IsRequired()) {
+ auto empty_value = opts_.set_empty_strings_to_null
+ ? "0"
+ : "_fbb.CreateSharedString(\"\")";
+ code = value + ".empty() ? " + empty_value + " : " + code;
+ }
+ break;
+ }
+ // Vector fields come in several flavours, of the forms:
+ // _fbb.CreateVector(_o->field);
+ // _fbb.CreateVector((const utype*)_o->field.data(),
+ // _o->field.size()); _fbb.CreateVectorOfStrings(_o->field)
+ // _fbb.CreateVectorOfStructs(_o->field)
+ // _fbb.CreateVector<Offset<T>>(_o->field.size() [&](size_t i) {
+ // return CreateT(_fbb, _o->Get(i), rehasher);
+ // });
+ case BASE_TYPE_VECTOR: {
+ auto vector_type = field.value.type.VectorType();
+ switch (vector_type.base_type) {
+ case BASE_TYPE_STRING: {
+ if (NativeString(&field) == "std::string") {
+ code += "_fbb.CreateVectorOfStrings(" + value + ")";
+ } else {
+ // Use by-function serialization to emulate
+ // CreateVectorOfStrings(); this works also with non-std strings.
+ code +=
+ "_fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>"
+ " ";
+ code += "(" + value + ".size(), ";
+ code += "[](size_t i, _VectorArgs *__va) { ";
+ code +=
+ "return __va->__fbb->CreateString(__va->_" + value + "[i]);";
+ code += " }, &_va )";
+ }
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ if (IsStruct(vector_type)) {
+ const auto &struct_attrs =
+ field.value.type.struct_def->attributes;
+ const auto native_type = struct_attrs.Lookup("native_type");
+ if (native_type) {
+ code += "_fbb.CreateVectorOfNativeStructs<";
+ code += WrapInNameSpace(*vector_type.struct_def) + ", " +
+ native_type->constant + ">";
+ code += "(" + value;
+ const auto pack_name =
+ struct_attrs.Lookup("native_type_pack_name");
+ if (pack_name) {
+ code += ", flatbuffers::Pack" + pack_name->constant;
+ }
+ code += ")";
+ } else {
+ code += "_fbb.CreateVectorOfStructs";
+ code += "(" + value + ")";
+ }
+ } else {
+ code += "_fbb.CreateVector<flatbuffers::Offset<";
+ code += WrapInNameSpace(*vector_type.struct_def) + ">> ";
+ code += "(" + value + ".size(), ";
+ code += "[](size_t i, _VectorArgs *__va) { ";
+ code += "return Create" + vector_type.struct_def->name;
+ code += "(*__va->__fbb, __va->_" + value + "[i]" +
+ GenPtrGet(field) + ", ";
+ code += "__va->__rehasher); }, &_va )";
+ }
+ break;
+ }
+ case BASE_TYPE_BOOL: {
+ code += "_fbb.CreateVector(" + value + ")";
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ code +=
+ "_fbb.CreateVector<flatbuffers::"
+ "Offset<void>>(" +
+ value +
+ ".size(), [](size_t i, _VectorArgs *__va) { "
+ "return __va->_" +
+ value + "[i].Pack(*__va->__fbb, __va->__rehasher); }, &_va)";
+ break;
+ }
+ case BASE_TYPE_UTYPE: {
+ value = StripUnionType(value);
+ code += "_fbb.CreateVector<uint8_t>(" + value +
+ ".size(), [](size_t i, _VectorArgs *__va) { "
+ "return static_cast<uint8_t>(__va->_" +
+ value + "[i].type); }, &_va)";
+ break;
+ }
+ default: {
+ if (field.value.type.enum_def &&
+ !VectorElementUserFacing(vector_type)) {
+ // For enumerations, we need to get access to the array data for
+ // the underlying storage type (eg. uint8_t).
+ const auto basetype = GenTypeBasic(
+ field.value.type.enum_def->underlying_type, false);
+ code += "_fbb.CreateVectorScalarCast<" + basetype +
+ ">(flatbuffers::data(" + value + "), " + value +
+ ".size())";
+ } else if (field.attributes.Lookup("cpp_type")) {
+ auto type = GenTypeBasic(vector_type, false);
+ code += "_fbb.CreateVector<" + type + ">(" + value + ".size(), ";
+ code += "[](size_t i, _VectorArgs *__va) { ";
+ code += "return __va->__rehasher ? ";
+ code += "static_cast<" + type + ">((*__va->__rehasher)";
+ code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0";
+ code += "; }, &_va )";
+ } else {
+ code += "_fbb.CreateVector(" + value + ")";
+ }
+ break;
+ }
+ }
+
+ // If set_empty_vectors_to_null option is enabled, for optional fields,
+ // check to see if there actually is any data in _o->field before
+ // attempting to access it.
+ if (opts_.set_empty_vectors_to_null && !field.IsRequired()) {
+ code = value + ".size() ? " + code + " : 0";
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ // _o->field.Pack(_fbb);
+ code += value + ".Pack(_fbb)";
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ if (IsStruct(field.value.type)) {
+ const auto &struct_attribs = field.value.type.struct_def->attributes;
+ const auto native_type = struct_attribs.Lookup("native_type");
+ if (native_type) {
+ code += "flatbuffers::Pack";
+ const auto pack_name =
+ struct_attribs.Lookup("native_type_pack_name");
+ if (pack_name) { code += pack_name->constant; }
+ code += "(" + value + ")";
+ } else if (field.native_inline) {
+ code += "&" + value;
+ } else {
+ code += value + " ? " + value + GenPtrGet(field) + " : 0";
+ }
+ } else {
+ // _o->field ? CreateT(_fbb, _o->field.get(), _rehasher);
+ const auto type = field.value.type.struct_def->name;
+ code += value + " ? Create" + type;
+ code += "(_fbb, " + value + GenPtrGet(field) + ", _rehasher)";
+ code += " : 0";
+ }
+ break;
+ }
+ default: {
+ code += value;
+ break;
+ }
+ }
+ return code;
+ }
+
+ // Generate code for tables that needs to come after the regular definition.
+ void GenTablePost(const StructDef &struct_def) {
+ code_.SetValue("STRUCT_NAME", Name(struct_def));
+ code_.SetValue("NATIVE_NAME",
+ NativeName(Name(struct_def), &struct_def, opts_));
+
+ if (opts_.generate_object_based_api) {
+ // Generate the X::UnPack() method.
+ code_ +=
+ "inline " + TableUnPackSignature(struct_def, false, opts_) + " {";
+
+ if (opts_.g_cpp_std == cpp::CPP_STD_X0) {
+ auto native_name = WrapNativeNameInNameSpace(struct_def, parser_.opts);
+ code_.SetValue("POINTER_TYPE",
+ GenTypeNativePtr(native_name, nullptr, false));
+ code_ +=
+ " {{POINTER_TYPE}} _o = {{POINTER_TYPE}}(new {{NATIVE_NAME}}());";
+ } else if (opts_.g_cpp_std == cpp::CPP_STD_11) {
+ code_ +=
+ " auto _o = std::unique_ptr<{{NATIVE_NAME}}>(new "
+ "{{NATIVE_NAME}}());";
+ } else {
+ code_ += " auto _o = std::make_unique<{{NATIVE_NAME}}>();";
+ }
+ code_ += " UnPackTo(_o.get(), _resolver);";
+ code_ += " return _o.release();";
+ code_ += "}";
+ code_ += "";
+ code_ +=
+ "inline " + TableUnPackToSignature(struct_def, false, opts_) + " {";
+ code_ += " (void)_o;";
+ code_ += " (void)_resolver;";
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) { continue; }
+
+ // Assign a value from |this| to |_o|. Values from |this| are stored
+ // in a variable |_e| by calling this->field_type(). The value is then
+ // assigned to |_o| using the GenUnpackFieldStatement.
+ const bool is_union = field.value.type.base_type == BASE_TYPE_UTYPE;
+ const auto statement =
+ GenUnpackFieldStatement(field, is_union ? *(it + 1) : nullptr);
+
+ code_.SetValue("FIELD_NAME", Name(field));
+ auto prefix = " { auto _e = {{FIELD_NAME}}(); ";
+ auto check = IsScalar(field.value.type.base_type) ? "" : "if (_e) ";
+ auto postfix = " }";
+ code_ += std::string(prefix) + check + statement + postfix;
+ }
+ code_ += "}";
+ code_ += "";
+
+ // Generate the X::Pack member function that simply calls the global
+ // CreateX function.
+ code_ += "inline " + TablePackSignature(struct_def, false, opts_) + " {";
+ code_ += " return Create{{STRUCT_NAME}}(_fbb, _o, _rehasher);";
+ code_ += "}";
+ code_ += "";
+
+ // Generate a CreateX method that works with an unpacked C++ object.
+ code_ +=
+ "inline " + TableCreateSignature(struct_def, false, opts_) + " {";
+ code_ += " (void)_rehasher;";
+ code_ += " (void)_o;";
+
+ code_ +=
+ " struct _VectorArgs "
+ "{ flatbuffers::FlatBufferBuilder *__fbb; "
+ "const " +
+ NativeName(Name(struct_def), &struct_def, opts_) +
+ "* __o; "
+ "const flatbuffers::rehasher_function_t *__rehasher; } _va = { "
+ "&_fbb, _o, _rehasher}; (void)_va;";
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) { continue; }
+ if (IsVector(field.value.type)) {
+ const std::string force_align_code =
+ GenVectorForceAlign(field, "_o->" + Name(field) + ".size()");
+ if (!force_align_code.empty()) { code_ += " " + force_align_code; }
+ }
+ code_ += " auto _" + Name(field) + " = " + GenCreateParam(field) + ";";
+ }
+ // Need to call "Create" with the struct namespace.
+ const auto qualified_create_name =
+ struct_def.defined_namespace->GetFullyQualifiedName("Create");
+ code_.SetValue("CREATE_NAME", TranslateNameSpace(qualified_create_name));
+
+ code_ += " return {{CREATE_NAME}}{{STRUCT_NAME}}(";
+ code_ += " _fbb\\";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) { continue; }
+
+ bool pass_by_address = false;
+ if (field.value.type.base_type == BASE_TYPE_STRUCT) {
+ if (IsStruct(field.value.type)) {
+ auto native_type =
+ field.value.type.struct_def->attributes.Lookup("native_type");
+ if (native_type) { pass_by_address = true; }
+ }
+ }
+
+ // Call the CreateX function using values from |_o|.
+ if (pass_by_address) {
+ code_ += ",\n &_" + Name(field) + "\\";
+ } else {
+ code_ += ",\n _" + Name(field) + "\\";
+ }
+ }
+ code_ += ");";
+ code_ += "}";
+ code_ += "";
+ }
+ }
+
+ static void GenPadding(
+ const FieldDef &field, std::string *code_ptr, int *id,
+ const std::function<void(int bits, std::string *code_ptr, int *id)> &f) {
+ if (field.padding) {
+ for (int i = 0; i < 4; i++) {
+ if (static_cast<int>(field.padding) & (1 << i)) {
+ f((1 << i) * 8, code_ptr, id);
+ }
+ }
+ FLATBUFFERS_ASSERT(!(field.padding & ~0xF));
+ }
+ }
+
+ static void PaddingDefinition(int bits, std::string *code_ptr, int *id) {
+ *code_ptr += " int" + NumToString(bits) + "_t padding" +
+ NumToString((*id)++) + "__;";
+ }
+
+ static void PaddingInitializer(int bits, std::string *code_ptr, int *id) {
+ (void)bits;
+ if (!code_ptr->empty()) *code_ptr += ",\n ";
+ *code_ptr += "padding" + NumToString((*id)++) + "__(0)";
+ }
+
+ static void PaddingNoop(int bits, std::string *code_ptr, int *id) {
+ (void)bits;
+ if (!code_ptr->empty()) *code_ptr += '\n';
+ *code_ptr += " (void)padding" + NumToString((*id)++) + "__;";
+ }
+
+ void GenStructDefaultConstructor(const StructDef &struct_def) {
+ std::string init_list;
+ std::string body;
+ bool first_in_init_list = true;
+ int padding_initializer_id = 0;
+ int padding_body_id = 0;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto field = *it;
+ const auto field_name = field->name + "_";
+
+ if (first_in_init_list) {
+ first_in_init_list = false;
+ } else {
+ init_list += ",";
+ init_list += "\n ";
+ }
+
+ init_list += field_name;
+ if (IsStruct(field->value.type) || IsArray(field->value.type)) {
+ // this is either default initialization of struct
+ // or
+ // implicit initialization of array
+ // for each object in array it:
+ // * sets it as zeros for POD types (integral, floating point, etc)
+ // * calls default constructor for classes/structs
+ init_list += "()";
+ } else {
+ init_list += "(0)";
+ }
+ if (field->padding) {
+ GenPadding(*field, &init_list, &padding_initializer_id,
+ PaddingInitializer);
+ GenPadding(*field, &body, &padding_body_id, PaddingNoop);
+ }
+ }
+
+ if (init_list.empty()) {
+ code_ += " {{STRUCT_NAME}}()";
+ code_ += " {}";
+ } else {
+ code_.SetValue("INIT_LIST", init_list);
+ code_ += " {{STRUCT_NAME}}()";
+ code_ += " : {{INIT_LIST}} {";
+ if (!body.empty()) { code_ += body; }
+ code_ += " }";
+ }
+ }
+
+ void GenStructConstructor(const StructDef &struct_def,
+ GenArrayArgMode array_mode) {
+ std::string arg_list;
+ std::string init_list;
+ int padding_id = 0;
+ auto first = struct_def.fields.vec.begin();
+ // skip arrays if generate ctor without array assignment
+ const auto init_arrays = (array_mode != kArrayArgModeNone);
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ const auto &type = field.value.type;
+ const auto is_array = IsArray(type);
+ const auto arg_name = "_" + Name(field);
+ if (!is_array || init_arrays) {
+ if (it != first && !arg_list.empty()) { arg_list += ", "; }
+ arg_list += !is_array ? GenTypeGet(type, " ", "const ", " &", true)
+ : GenTypeSpan(type, true, type.fixed_length);
+ arg_list += arg_name;
+ }
+ // skip an array with initialization from span
+ if (false == (is_array && init_arrays)) {
+ if (it != first && !init_list.empty()) { init_list += ",\n "; }
+ init_list += Name(field) + "_";
+ if (IsScalar(type.base_type)) {
+ auto scalar_type = GenUnderlyingCast(field, false, arg_name);
+ init_list += "(flatbuffers::EndianScalar(" + scalar_type + "))";
+ } else {
+ FLATBUFFERS_ASSERT((is_array && !init_arrays) || IsStruct(type));
+ if (!is_array)
+ init_list += "(" + arg_name + ")";
+ else
+ init_list += "()";
+ }
+ }
+ if (field.padding)
+ GenPadding(field, &init_list, &padding_id, PaddingInitializer);
+ }
+
+ if (!arg_list.empty()) {
+ code_.SetValue("ARG_LIST", arg_list);
+ code_.SetValue("INIT_LIST", init_list);
+ if (!init_list.empty()) {
+ code_ += " {{STRUCT_NAME}}({{ARG_LIST}})";
+ code_ += " : {{INIT_LIST}} {";
+ } else {
+ code_ += " {{STRUCT_NAME}}({{ARG_LIST}}) {";
+ }
+ padding_id = 0;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ const auto &type = field.value.type;
+ if (IsArray(type) && init_arrays) {
+ const auto &element_type = type.VectorType();
+ const auto is_enum = IsEnum(element_type);
+ FLATBUFFERS_ASSERT(
+ (IsScalar(element_type.base_type) || IsStruct(element_type)) &&
+ "invalid declaration");
+ const auto face_type = GenTypeGet(type, " ", "", "", is_enum);
+ std::string get_array =
+ is_enum ? "CastToArrayOfEnum<" + face_type + ">" : "CastToArray";
+ const auto field_name = Name(field) + "_";
+ const auto arg_name = "_" + Name(field);
+ code_ += " flatbuffers::" + get_array + "(" + field_name +
+ ").CopyFromSpan(" + arg_name + ");";
+ }
+ if (field.padding) {
+ std::string padding;
+ GenPadding(field, &padding, &padding_id, PaddingNoop);
+ code_ += padding;
+ }
+ }
+ code_ += " }";
+ }
+ }
+
+ void GenArrayAccessor(const Type &type, bool mutable_accessor) {
+ FLATBUFFERS_ASSERT(IsArray(type));
+ const auto is_enum = IsEnum(type.VectorType());
+ // The Array<bool,N> is a tricky case, like std::vector<bool>.
+ // It requires a specialization of Array class.
+ // Generate Array<uint8_t> for Array<bool>.
+ const auto face_type = GenTypeGet(type, " ", "", "", is_enum);
+ std::string ret_type = "flatbuffers::Array<" + face_type + ", " +
+ NumToString(type.fixed_length) + ">";
+ if (mutable_accessor)
+ code_ += " " + ret_type + " *mutable_{{FIELD_NAME}}() {";
+ else
+ code_ += " const " + ret_type + " *{{FIELD_NAME}}() const {";
+
+ std::string get_array =
+ is_enum ? "CastToArrayOfEnum<" + face_type + ">" : "CastToArray";
+ code_ += " return &flatbuffers::" + get_array + "({{FIELD_VALUE}});";
+ code_ += " }";
+ }
+
+ // Generate an accessor struct with constructor for a flatbuffers struct.
+ void GenStruct(const StructDef &struct_def) {
+ // Generate an accessor struct, with private variables of the form:
+ // type name_;
+ // Generates manual padding and alignment.
+ // Variables are private because they contain little endian data on all
+ // platforms.
+ GenComment(struct_def.doc_comment);
+ code_.SetValue("ALIGN", NumToString(struct_def.minalign));
+ code_.SetValue("STRUCT_NAME", Name(struct_def));
+
+ code_ +=
+ "FLATBUFFERS_MANUALLY_ALIGNED_STRUCT({{ALIGN}}) "
+ "{{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS {";
+ code_ += " private:";
+
+ int padding_id = 0;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ const auto &field_type = field.value.type;
+ code_.SetValue("FIELD_TYPE", GenTypeGet(field_type, " ", "", " ", false));
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("ARRAY",
+ IsArray(field_type)
+ ? "[" + NumToString(field_type.fixed_length) + "]"
+ : "");
+ code_ += (" {{FIELD_TYPE}}{{FIELD_NAME}}_{{ARRAY}};");
+
+ if (field.padding) {
+ std::string padding;
+ GenPadding(field, &padding, &padding_id, PaddingDefinition);
+ code_ += padding;
+ }
+ }
+
+ // Generate GetFullyQualifiedName
+ code_ += "";
+ code_ += " public:";
+
+ if (opts_.g_cpp_std >= cpp::CPP_STD_17) { code_ += " struct Traits;"; }
+
+ // Make TypeTable accessible via the generated struct.
+ if (opts_.mini_reflect != IDLOptions::kNone) {
+ code_ +=
+ " static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
+ code_ += " return {{STRUCT_NAME}}TypeTable();";
+ code_ += " }";
+ }
+
+ GenFullyQualifiedNameGetter(struct_def, Name(struct_def));
+
+ // Generate a default constructor.
+ GenStructDefaultConstructor(struct_def);
+
+ // Generate a constructor that takes all fields as arguments,
+ // excluding arrays.
+ GenStructConstructor(struct_def, kArrayArgModeNone);
+
+ auto arrays_num = std::count_if(struct_def.fields.vec.begin(),
+ struct_def.fields.vec.end(),
+ [](const flatbuffers::FieldDef *fd) {
+ return IsArray(fd->value.type);
+ });
+ if (arrays_num > 0) {
+ GenStructConstructor(struct_def, kArrayArgModeSpanStatic);
+ }
+
+ // Generate accessor methods of the form:
+ // type name() const { return flatbuffers::EndianScalar(name_); }
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ const auto &type = field.value.type;
+ const auto is_scalar = IsScalar(type.base_type);
+ const auto is_array = IsArray(type);
+
+ const auto field_type = GenTypeGet(type, " ", is_array ? "" : "const ",
+ is_array ? "" : " &", true);
+ auto member = Name(field) + "_";
+ auto value =
+ is_scalar ? "flatbuffers::EndianScalar(" + member + ")" : member;
+
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("FIELD_TYPE", field_type);
+ code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value));
+
+ GenComment(field.doc_comment, " ");
+
+ // Generate a const accessor function.
+ if (is_array) {
+ GenArrayAccessor(type, false);
+ } else {
+ code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
+ code_ += " return {{FIELD_VALUE}};";
+ code_ += " }";
+ }
+
+ // Generate a mutable accessor function.
+ if (opts_.mutable_buffer) {
+ auto mut_field_type =
+ GenTypeGet(type, " ", "", is_array ? "" : " &", true);
+ code_.SetValue("FIELD_TYPE", mut_field_type);
+ if (is_scalar) {
+ code_.SetValue("ARG", GenTypeBasic(type, true));
+ code_.SetValue("FIELD_VALUE",
+ GenUnderlyingCast(field, false, "_" + Name(field)));
+
+ code_ += " void mutate_{{FIELD_NAME}}({{ARG}} _{{FIELD_NAME}}) {";
+ code_ +=
+ " flatbuffers::WriteScalar(&{{FIELD_NAME}}_, "
+ "{{FIELD_VALUE}});";
+ code_ += " }";
+ } else if (is_array) {
+ GenArrayAccessor(type, true);
+ } else {
+ code_ += " {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {";
+ code_ += " return {{FIELD_VALUE}};";
+ code_ += " }";
+ }
+ }
+
+ // Generate a comparison function for this field if it is a key.
+ if (field.key) { GenKeyFieldMethods(field); }
+ }
+ code_.SetValue("NATIVE_NAME", Name(struct_def));
+ GenOperatorNewDelete(struct_def);
+
+ if (opts_.cpp_static_reflection) { GenIndexBasedFieldGetter(struct_def); }
+
+ code_ += "};";
+
+ code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize));
+ code_ += "FLATBUFFERS_STRUCT_END({{STRUCT_NAME}}, {{STRUCT_BYTE_SIZE}});";
+ if (opts_.gen_compare) GenCompareOperator(struct_def, "()");
+ code_ += "";
+
+ // Definition for type traits for this table type. This allows querying var-
+ // ious compile-time traits of the table.
+ if (opts_.g_cpp_std >= cpp::CPP_STD_17) { GenTraitsStruct(struct_def); }
+ }
+
+ // Set up the correct namespace. Only open a namespace if the existing one is
+ // different (closing/opening only what is necessary).
+ //
+ // The file must start and end with an empty (or null) namespace so that
+ // namespaces are properly opened and closed.
+ void SetNameSpace(const Namespace *ns) {
+ if (cur_name_space_ == ns) { return; }
+
+ // Compute the size of the longest common namespace prefix.
+ // If cur_name_space is A::B::C::D and ns is A::B::E::F::G,
+ // the common prefix is A::B:: and we have old_size = 4, new_size = 5
+ // and common_prefix_size = 2
+ size_t old_size = cur_name_space_ ? cur_name_space_->components.size() : 0;
+ size_t new_size = ns ? ns->components.size() : 0;
+
+ size_t common_prefix_size = 0;
+ while (common_prefix_size < old_size && common_prefix_size < new_size &&
+ ns->components[common_prefix_size] ==
+ cur_name_space_->components[common_prefix_size]) {
+ common_prefix_size++;
+ }
+
+ // Close cur_name_space in reverse order to reach the common prefix.
+ // In the previous example, D then C are closed.
+ for (size_t j = old_size; j > common_prefix_size; --j) {
+ code_ += "} // namespace " + cur_name_space_->components[j - 1];
+ }
+ if (old_size != common_prefix_size) { code_ += ""; }
+
+ // open namespace parts to reach the ns namespace
+ // in the previous example, E, then F, then G are opened
+ for (auto j = common_prefix_size; j != new_size; ++j) {
+ code_ += "namespace " + ns->components[j] + " {";
+ }
+ if (new_size != common_prefix_size) { code_ += ""; }
+
+ cur_name_space_ = ns;
+ }
+};
+
+} // namespace cpp
+
+bool GenerateCPP(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ cpp::IDLOptionsCpp opts(parser.opts);
+ // The '--cpp_std' argument could be extended (like ASAN):
+ // Example: "flatc --cpp_std c++17:option1:option2".
+ auto cpp_std = !opts.cpp_std.empty() ? opts.cpp_std : "C++11";
+ std::transform(cpp_std.begin(), cpp_std.end(), cpp_std.begin(), CharToUpper);
+ if (cpp_std == "C++0X") {
+ opts.g_cpp_std = cpp::CPP_STD_X0;
+ opts.g_only_fixed_enums = false;
+ } else if (cpp_std == "C++11") {
+ // Use the standard C++11 code generator.
+ opts.g_cpp_std = cpp::CPP_STD_11;
+ opts.g_only_fixed_enums = true;
+ } else if (cpp_std == "C++17") {
+ opts.g_cpp_std = cpp::CPP_STD_17;
+ // With c++17 generate strong enums only.
+ opts.scoped_enums = true;
+ // By default, prefixed_enums==true, reset it.
+ opts.prefixed_enums = false;
+ } else {
+ LogCompilerError("Unknown value of the '--cpp-std' switch: " +
+ opts.cpp_std);
+ return false;
+ }
+ // The opts.scoped_enums has priority.
+ opts.g_only_fixed_enums |= opts.scoped_enums;
+
+ if (opts.cpp_static_reflection && opts.g_cpp_std < cpp::CPP_STD_17) {
+ LogCompilerError(
+ "--cpp-static-reflection requires using --cpp-std at \"C++17\" or "
+ "higher.");
+ return false;
+ }
+
+ cpp::CppGenerator generator(parser, path, file_name, opts);
+ return generator.generate();
+}
+
+std::string CPPMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ const auto filebase =
+ flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
+ cpp::CppGenerator geneartor(parser, path, file_name, parser.opts);
+ const auto included_files = parser.GetIncludedFilesRecursive(file_name);
+ std::string make_rule =
+ geneartor.GeneratedFileName(path, filebase, parser.opts) + ": ";
+ for (auto it = included_files.begin(); it != included_files.end(); ++it) {
+ make_rule += " " + *it;
+ }
+ return make_rule;
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp b/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp
new file mode 100644
index 0000000000..1ba2ef3e4a
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_cpp_yandex_maps_iter.cpp
@@ -0,0 +1,731 @@
+/*
+ * 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 <unordered_set>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/flatc.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+// Pedantic warning free version of toupper().
+inline char ToUpper(char c) {
+ return static_cast<char>(::toupper(static_cast<unsigned char>(c)));
+}
+
+static std::string GeneratedIterFileName(const std::string &path,
+ const std::string &file_name) {
+ return path + file_name + ".iter.fbs.h";
+}
+
+namespace cpp_yandex_maps_iter {
+class CppIterGenerator : public BaseGenerator {
+ public:
+ CppIterGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", "::", "h"),
+ cur_name_space_(nullptr) {
+ static const char *const keywords[] = {
+ "alignas",
+ "alignof",
+ "and",
+ "and_eq",
+ "asm",
+ "atomic_cancel",
+ "atomic_commit",
+ "atomic_noexcept",
+ "auto",
+ "bitand",
+ "bitor",
+ "bool",
+ "break",
+ "case",
+ "catch",
+ "char",
+ "char16_t",
+ "char32_t",
+ "class",
+ "compl",
+ "concept",
+ "const",
+ "constexpr",
+ "const_cast",
+ "continue",
+ "co_await",
+ "co_return",
+ "co_yield",
+ "decltype",
+ "default",
+ "delete",
+ "do",
+ "double",
+ "dynamic_cast",
+ "else",
+ "enum",
+ "explicit",
+ "export",
+ "extern",
+ "false",
+ "float",
+ "for",
+ "friend",
+ "goto",
+ "if",
+ "import",
+ "inline",
+ "int",
+ "long",
+ "module",
+ "mutable",
+ "namespace",
+ "new",
+ "noexcept",
+ "not",
+ "not_eq",
+ "nullptr",
+ "operator",
+ "or",
+ "or_eq",
+ "private",
+ "protected",
+ "public",
+ "register",
+ "reinterpret_cast",
+ "requires",
+ "return",
+ "short",
+ "signed",
+ "sizeof",
+ "static",
+ "static_assert",
+ "static_cast",
+ "struct",
+ "switch",
+ "synchronized",
+ "template",
+ "this",
+ "thread_local",
+ "throw",
+ "true",
+ "try",
+ "typedef",
+ "typeid",
+ "typename",
+ "union",
+ "unsigned",
+ "using",
+ "virtual",
+ "void",
+ "volatile",
+ "wchar_t",
+ "while",
+ "xor",
+ "xor_eq",
+ nullptr,
+ };
+ for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
+ }
+
+ std::string GenIncludeGuard() const {
+ // Generate include guard.
+ std::string guard = file_name_;
+ // Remove any non-alpha-numeric characters that may appear in a filename.
+ struct IsAlnum {
+ bool operator()(char c) const { return !isalnum(c); }
+ };
+ guard.erase(std::remove_if(guard.begin(), guard.end(), IsAlnum()),
+ guard.end());
+ guard = "FLATBUFFERS_GENERATED_" + guard;
+ guard += "_";
+ // For further uniqueness, also add the namespace.
+ auto name_space = parser_.current_namespace_;
+ for (auto it = name_space->components.begin();
+ it != name_space->components.end(); ++it) {
+ guard += *it + "_";
+ }
+ guard += "ITER_";
+ guard += "H_";
+ std::transform(guard.begin(), guard.end(), guard.begin(), ToUpper);
+ return guard;
+ }
+
+ void GenIncludeDependencies() {
+ int num_includes = 0;
+ for (auto it = parser_.native_included_files_.begin();
+ it != parser_.native_included_files_.end(); ++it) {
+ code_ += "#include \"" + *it + "\"";
+ num_includes++;
+ }
+ for (auto it = parser_.included_files_.begin();
+ it != parser_.included_files_.end(); ++it) {
+ if (it->second.empty()) continue;
+ auto noext = flatbuffers::StripExtension(it->second);
+ auto basename = flatbuffers::StripPath(noext);
+
+ code_ += "#include \"" + parser_.opts.include_prefix +
+ (parser_.opts.keep_include_path ? noext : basename) +
+ ".iter.fbs.h\"";
+ num_includes++;
+ }
+ if (num_includes) code_ += "";
+ }
+
+ std::string EscapeKeyword(const std::string &name) const {
+ return keywords_.find(name) == keywords_.end() ? name : name + "_";
+ }
+
+ std::string Name(const Definition &def) const {
+ return EscapeKeyword(def.name);
+ }
+
+ std::string Name(const EnumVal &ev) const { return EscapeKeyword(ev.name); }
+
+ // Iterate through all definitions we haven't generate code for (enums,
+ // structs, and tables) and output them to a single file.
+ bool generate() {
+ code_.Clear();
+ code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
+
+ const auto include_guard = GenIncludeGuard();
+ code_ += "#ifndef " + include_guard;
+ code_ += "#define " + include_guard;
+ code_ += "";
+
+ if (parser_.opts.gen_nullable) {
+ code_ += "#pragma clang system_header\n\n";
+ }
+
+ code_ += "#include \"" + file_name_ + ".fbs.h\"";
+ code_ += "#include \"contrib/libs/flatbuffers/include/flatbuffers/flatbuffers_iter.h\"";
+ code_ += "";
+
+ if (parser_.opts.include_dependence_headers) { GenIncludeDependencies(); }
+
+ FLATBUFFERS_ASSERT(!cur_name_space_);
+
+ // Generate forward declarations for all structs/tables, since they may
+ // have circular references.
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (!struct_def.generated && !struct_def.fixed) {
+ SetNameSpace(struct_def.defined_namespace);
+ code_ += "template <typename Iter>";
+ code_ += "struct " + Name(struct_def) + ";";
+ code_ += "";
+ }
+ }
+
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (!struct_def.fixed && !struct_def.generated) {
+ SetNameSpace(struct_def.defined_namespace);
+ GenTable(struct_def);
+ }
+ }
+
+ // Generate convenient global helper functions:
+ if (parser_.root_struct_def_ && !parser_.root_struct_def_->fixed) {
+ auto &struct_def = *parser_.root_struct_def_;
+ SetNameSpace(struct_def.defined_namespace);
+ auto name = Name(struct_def);
+ auto qualified_name = cur_name_space_->GetFullyQualifiedName(name);
+ auto cpp_name = TranslateNameSpace(qualified_name, true);
+ const auto cpp_non_iter_name = TranslateNameSpace(qualified_name);
+ const auto cpp_non_iter_getter = TranslateNameSpace(
+ parser_.namespaces_.back()->GetFullyQualifiedName("Get"+name));
+
+ code_.SetValue("STRUCT_NAME", name);
+ code_.SetValue("CPP_NAME", cpp_name);
+ code_.SetValue("CPP_NON_ITER_NAME", cpp_non_iter_name);
+ code_.SetValue("CPP_NON_ITER_GETTER", cpp_non_iter_getter);
+
+ // The root datatype accessor:
+ code_ += "template <typename Iter>";
+ code_ += "inline \\";
+ code_ += "std::optional<{{CPP_NAME}}<Iter>> Get{{STRUCT_NAME}}(const Iter& buf) {";
+ code_ += " return yandex::maps::flatbuffers_iter::GetRoot<{{CPP_NAME}}<Iter>, Iter>(buf);";
+ code_ += "}";
+ code_ += "";
+
+ // The non_iter datatype accessor:
+ code_ += "inline \\";
+ code_ += "const {{CPP_NON_ITER_NAME}} *Get{{STRUCT_NAME}}(const char *buf) {";
+ code_ += " return {{CPP_NON_ITER_GETTER}}(buf);";
+ code_ += "}";
+ code_ += "";
+
+ if (parser_.file_identifier_.length()) {
+ // Return the identifier
+ code_ += "inline const char *{{STRUCT_NAME}}Identifier() {";
+ code_ += " return \"" + parser_.file_identifier_ + "\";";
+ code_ += "}";
+ code_ += "";
+
+ // Check if a buffer has the identifier.
+ code_ += "template <typename Iter>";
+ code_ += "inline \\";
+ code_ += "bool {{STRUCT_NAME}}BufferHasIdentifier(const Iter& buf) {";
+ code_ += " return yandex::maps::flatbuffers_iter::BufferHasIdentifier(";
+ code_ += " buf, {{STRUCT_NAME}}Identifier());";
+ code_ += "}";
+ code_ += "";
+ }
+
+ // The root verifier.
+ if (parser_.file_identifier_.length()) {
+ code_.SetValue("ID", name + "Identifier()");
+ } else {
+ code_.SetValue("ID", "nullptr");
+ }
+
+ code_ += "template <typename Iter>";
+ code_ += "inline bool Verify{{STRUCT_NAME}}Buffer(";
+ code_ += " yandex::maps::flatbuffers_iter::Verifier<Iter> &verifier) {";
+ code_ += " return verifier.template VerifyBuffer<{{CPP_NAME}}<Iter>>({{ID}});";
+ code_ += "}";
+ code_ += "";
+
+ if (parser_.file_extension_.length()) {
+ // Return the extension
+ code_ += "inline const char *{{STRUCT_NAME}}Extension() {";
+ code_ += " return \"" + parser_.file_extension_ + "\";";
+ code_ += "}";
+ code_ += "";
+ }
+ }
+
+ if (cur_name_space_) SetNameSpace(nullptr);
+
+ // Close the include guard.
+ code_ += "#endif // " + include_guard;
+
+ const auto file_path = GeneratedIterFileName(path_, file_name_);
+ const auto final_code = code_.ToString();
+ return SaveFile(file_path.c_str(), final_code, false);
+ }
+
+ private:
+ CodeWriter code_;
+
+ std::unordered_set<std::string> keywords_;
+
+ // This tracks the current namespace so we can insert namespace declarations.
+ const Namespace *cur_name_space_;
+
+ const Namespace *CurrentNameSpace() const { return cur_name_space_; }
+
+// Ensure that a type is prefixed with its namespace whenever it is used
+// outside of its namespace.
+ std::string WrapInNameSpace(const Namespace *ns,
+ const std::string &name, bool needIter = false) const {
+ if (CurrentNameSpace() == ns) return name;
+ std::string qualified_name = qualifying_start_;
+ for (auto it = ns->components.begin(); it != ns->components.end(); ++it)
+ qualified_name += *it + qualifying_separator_;
+ if (needIter)
+ qualified_name += "iter" + qualifying_separator_;
+ return qualified_name + name;
+ }
+
+ std::string WrapInNameSpace(const Definition &def, bool needIter = false) const {
+ return WrapInNameSpace(def.defined_namespace, def.name, needIter);
+ }
+
+ // Translates a qualified name in flatbuffer text format to the same name in
+ // the equivalent C++ namespace.
+ static std::string TranslateNameSpace(const std::string &qualified_name, bool needIter = false) {
+ std::string cpp_qualified_name = qualified_name;
+ size_t start_pos = 0;
+ while ((start_pos = cpp_qualified_name.find(".", start_pos)) !=
+ std::string::npos) {
+ cpp_qualified_name.replace(start_pos, 1, "::");
+ }
+ if (needIter)
+ {
+ start_pos = cpp_qualified_name.rfind("::");
+ if (start_pos != std::string::npos)
+ cpp_qualified_name.replace(start_pos, 2, "::iter::");
+ }
+ return cpp_qualified_name;
+ }
+
+ void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
+ std::string text;
+ ::flatbuffers::GenComment(dc, &text, nullptr, prefix);
+ code_ += text + "\\";
+ }
+
+ // Return a C++ type from the table in idl.h
+ std::string GenTypeBasic(const Type &type, bool user_facing_type) const {
+ // clang-format off
+ static const char * const ctypename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ #CTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+ if (user_facing_type) {
+ if (type.enum_def) return WrapInNameSpace(*type.enum_def);
+ if (type.base_type == BASE_TYPE_BOOL) return "bool";
+ }
+ return ctypename[type.base_type];
+ }
+
+ // Return a C++ pointer type, specialized to the actual struct/table types,
+ // and vector element types.
+ std::string GenTypePointer(const Type &type) const {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: {
+ return "yandex::maps::flatbuffers_iter::String<Iter>";
+ }
+ case BASE_TYPE_VECTOR: {
+ const auto type_name = GenTypeWire(type.VectorType(), "", false);
+ return "yandex::maps::flatbuffers_iter::Vector<" + type_name + ", Iter>";
+ }
+ case BASE_TYPE_STRUCT: {
+ if (IsStruct(type))
+ return WrapInNameSpace(*type.struct_def, !type.struct_def->fixed);
+ return WrapInNameSpace(*type.struct_def, !type.struct_def->fixed) + "<Iter>";
+ }
+ case BASE_TYPE_UNION:
+ // fall through
+ default: { return "void"; }
+ }
+ }
+
+ // Return a C++ type for any type (scalar/pointer) specifically for
+ // building a flatbuffer.
+ std::string GenTypeWire(const Type &type, const char *postfix,
+ bool user_facing_type) const {
+ if (IsScalar(type.base_type)) {
+ return GenTypeBasic(type, user_facing_type) + postfix;
+ } else if (IsStruct(type)) {
+ return GenTypePointer(type);
+ } else {
+ return "yandex::maps::flatbuffers_iter::Offset<" + GenTypePointer(type) + ">" + postfix;
+ }
+ }
+
+ // Return a C++ type for any type (scalar/pointer) that reflects its
+ // serialized size.
+ std::string GenTypeSize(const Type &type) const {
+ if (IsScalar(type.base_type)) {
+ return GenTypeBasic(type, false);
+ } else if (IsStruct(type)) {
+ return GenTypePointer(type);
+ } else {
+ return "yandex::maps::flatbuffers_iter::uoffset_t";
+ }
+ }
+
+ // Return a C++ type for any type (scalar/pointer) specifically for
+ // using a flatbuffer.
+ std::string GenTypeGet(const Type &type, const char *afterbasic,
+ const char *beforeptr, const char *afterptr,
+ bool user_facing_type) {
+ if (IsScalar(type.base_type)) {
+ return GenTypeBasic(type, user_facing_type) + afterbasic;
+ } else {
+ return beforeptr + GenTypePointer(type) + afterptr;
+ }
+ }
+
+ // Generates a value with optionally a cast applied if the field has a
+ // different underlying type from its interface type (currently only the
+ // case for enums. "from" specify the direction, true meaning from the
+ // underlying type to the interface type.
+ std::string GenUnderlyingCast(const FieldDef &field, bool from,
+ const std::string &val) {
+ if (from && field.value.type.base_type == BASE_TYPE_BOOL) {
+ return val + " != 0";
+ } else if ((field.value.type.enum_def &&
+ IsScalar(field.value.type.base_type)) ||
+ field.value.type.base_type == BASE_TYPE_BOOL) {
+ return "static_cast<" + GenTypeBasic(field.value.type, from) + ">(" +
+ val + ")";
+ } else {
+ return val;
+ }
+ }
+
+ std::string GenFieldOffsetName(const FieldDef &field) {
+ std::string uname = Name(field);
+ std::transform(uname.begin(), uname.end(), uname.begin(), ToUpper);
+ return "VT_" + uname;
+ }
+
+ std::string GenDefaultConstant(const FieldDef &field) {
+ return field.value.type.base_type == BASE_TYPE_FLOAT
+ ? field.value.constant + "f"
+ : field.value.constant;
+ }
+
+ // Generate the code to call the appropriate Verify function(s) for a field.
+ void GenVerifyCall(const FieldDef &field, const char *prefix) {
+ code_.SetValue("PRE", prefix);
+ code_.SetValue("NAME", Name(field));
+ code_.SetValue("REQUIRED", field.IsRequired() ? "Required" : "");
+ code_.SetValue("SIZE", GenTypeSize(field.value.type));
+ code_.SetValue("OFFSET", GenFieldOffsetName(field));
+ code_ += "{{PRE}}this->template VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, {{OFFSET}})\\";
+
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_UNION: {
+ code_.SetValue("ENUM_NAME", field.value.type.enum_def->name);
+ code_.SetValue("SUFFIX", UnionTypeFieldSuffix());
+ code_ +=
+ "{{PRE}}Verify{{ENUM_NAME}}(verifier, {{NAME}}(), "
+ "{{NAME}}{{SUFFIX}}())\\";
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ if (!field.value.type.struct_def->fixed) {
+ code_ += "{{PRE}}verifier.VerifyTable({{NAME}}())\\";
+ }
+ break;
+ }
+ case BASE_TYPE_STRING: {
+ code_ += "{{PRE}}verifier.Verify({{NAME}}())\\";
+ break;
+ }
+ case BASE_TYPE_VECTOR: {
+ code_ += "{{PRE}}verifier.Verify({{NAME}}())\\";
+
+ switch (field.value.type.element) {
+ case BASE_TYPE_STRING: {
+ code_ += "{{PRE}}verifier.VerifyVectorOfStrings({{NAME}}())\\";
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ if (!field.value.type.struct_def->fixed) {
+ code_ += "{{PRE}}verifier.VerifyVectorOfTables({{NAME}}())\\";
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ code_.SetValue("ENUM_NAME", field.value.type.enum_def->name);
+ code_ +=
+ "{{PRE}}Verify{{ENUM_NAME}}Vector(verifier, {{NAME}}(), "
+ "{{NAME}}_type())\\";
+ break;
+ }
+ default: break;
+ }
+ break;
+ }
+ default: { break; }
+ }
+ }
+
+ // Generate CompareWithValue method for a key field.
+ void GenKeyFieldMethods(const FieldDef &field) {
+ FLATBUFFERS_ASSERT(field.key);
+ const bool is_string = (field.value.type.base_type == BASE_TYPE_STRING);
+
+ code_ += " bool KeyCompareLessThan(const std::optional<{{STRUCT_NAME}}<Iter>>& o) const {";
+ if (is_string) {
+ // use operator< of flatbuffers::String
+ code_ += " return {{FIELD_NAME}}() < o->{{FIELD_NAME}}();";
+ } else {
+ code_ += " return {{FIELD_NAME}}() < o->{{FIELD_NAME}}();";
+ }
+ code_ += " }";
+
+ if (is_string) {
+ code_ += " int KeyCompareWithValue(const char *val) const {";
+ code_ += " return strcmp({{FIELD_NAME}}()->str().c_str(), val);";
+ code_ += " }";
+ } else {
+ FLATBUFFERS_ASSERT(IsScalar(field.value.type.base_type));
+ auto type = GenTypeBasic(field.value.type, false);
+ if (parser_.opts.scoped_enums && field.value.type.enum_def &&
+ IsScalar(field.value.type.base_type)) {
+ type = GenTypeGet(field.value.type, " ", "const ", " *", true);
+ }
+ // Returns {field<val: -1, field==val: 0, field>val: +1}.
+ code_.SetValue("KEY_TYPE", type);
+ code_ += " int KeyCompareWithValue({{KEY_TYPE}} val) const {";
+ code_ +=
+ " return static_cast<int>({{FIELD_NAME}}() > val) - "
+ "static_cast<int>({{FIELD_NAME}}() < val);";
+ code_ += " }";
+ }
+ }
+
+
+ // Generate an accessor struct, builder structs & function for a table.
+ void GenTable(const StructDef &struct_def) {
+ // Generate an accessor struct, with methods of the form:
+ // type name() const { return GetField<type>(offset, defaultval); }
+ GenComment(struct_def.doc_comment);
+
+ code_.SetValue("STRUCT_NAME", Name(struct_def));
+ code_ += "template <typename Iter>";
+ code_ +=
+ "struct {{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS"
+ " : private yandex::maps::flatbuffers_iter::Table<Iter> {";
+
+ // Generate field id constants.
+ if (struct_def.fields.vec.size() > 0) {
+ // We need to add a trailing comma to all elements except the last one as
+ // older versions of gcc complain about this.
+ code_.SetValue("SEP", "");
+ code_ += " enum {";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) {
+ // Deprecated fields won't be accessible.
+ continue;
+ }
+
+ code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field));
+ code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
+ code_ += "{{SEP}} {{OFFSET_NAME}} = {{OFFSET_VALUE}}\\";
+ code_.SetValue("SEP", ",\n");
+ }
+ code_ += "";
+ code_ += " };";
+ }
+
+ code_ += "";
+ code_ += " using yandex::maps::flatbuffers_iter::Table<Iter>::Table;";
+
+ // Generate the accessors.
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) {
+ // Deprecated fields won't be accessible.
+ continue;
+ }
+
+ const bool is_struct = IsStruct(field.value.type);
+ const bool is_scalar = IsScalar(field.value.type.base_type);
+ code_.SetValue("FIELD_NAME", Name(field));
+
+ // Call a different accessor for pointers, that indirects.
+ std::string accessor = "";
+ if (is_scalar) {
+ accessor = "this->template GetField<";
+ } else if (is_struct) {
+ accessor = "this->template GetStruct<";
+ } else {
+ accessor = "this->template GetPointer<";
+ }
+ auto offset_str = GenFieldOffsetName(field);
+ auto offset_type =
+ GenTypeGet(field.value.type, "", "", "", false);
+
+ auto call = accessor + offset_type + ">(" + offset_str;
+ // Default value as second arg for non-pointer types.
+ if (is_scalar) { call += ", " + GenDefaultConstant(field); }
+ call += ")";
+
+ GenComment(field.doc_comment, " ");
+ code_.SetValue("FIELD_TYPE",
+ GenTypeGet(field.value.type, " ", "std::optional<", "> ", true));
+ code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, call));
+
+ code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
+ code_ += " return {{FIELD_VALUE}};";
+ code_ += " }";
+
+ // Generate a comparison function for this field if it is a key.
+ if (field.key) {
+ GenKeyFieldMethods(field);
+ }
+ }
+
+ // Generate a verifier function that can check a buffer from an untrusted
+ // source will never cause reads outside the buffer.
+ code_ += " bool Verify(yandex::maps::flatbuffers_iter::Verifier<Iter> &verifier) const {";
+ code_ += " return this->VerifyTableStart(verifier)\\";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) { continue; }
+ GenVerifyCall(field, " &&\n ");
+ }
+
+ code_ += " &&\n verifier.EndTable();";
+ code_ += " }";
+
+ code_ += "};"; // End of table.
+ code_ += "";
+ }
+
+ // Set up the correct namespace. Only open a namespace if the existing one is
+ // different (closing/opening only what is necessary).
+ //
+ // The file must start and end with an empty (or null) namespace so that
+ // namespaces are properly opened and closed.
+ void SetNameSpace(const Namespace *ns) {
+ if (cur_name_space_ == ns) { return; }
+
+ // Compute the size of the longest common namespace prefix.
+ // If cur_name_space is A::B::C::D and ns is A::B::E::F::G,
+ // the common prefix is A::B:: and we have old_size = 4, new_size = 5
+ // and common_prefix_size = 2
+ size_t old_size = cur_name_space_ ? cur_name_space_->components.size() : 0;
+ size_t new_size = ns ? ns->components.size() : 0;
+
+ size_t common_prefix_size = 0;
+ while (common_prefix_size < old_size && common_prefix_size < new_size &&
+ ns->components[common_prefix_size] ==
+ cur_name_space_->components[common_prefix_size]) {
+ common_prefix_size++;
+ }
+
+ // Close cur_name_space in reverse order to reach the common prefix.
+ // In the previous example, D then C are closed.
+ if (old_size > 0)
+ code_ += "} // namespace iter";
+ for (size_t j = old_size; j > common_prefix_size; --j) {
+ code_ += "} // namespace " + cur_name_space_->components[j - 1];
+ }
+ if (old_size != common_prefix_size) { code_ += ""; }
+
+ // open namespace parts to reach the ns namespace
+ // in the previous example, E, then F, then G are opened
+ for (auto j = common_prefix_size; j != new_size; ++j) {
+ code_ += "namespace " + ns->components[j] + " {";
+ }
+ if (new_size > 0)
+ code_ += "namespace iter {";
+ if (new_size != common_prefix_size) { code_ += ""; }
+
+ cur_name_space_ = ns;
+ }
+};
+
+} // namespace cpp_yandex_maps_iter
+
+bool GenerateCPPYandexMapsIter(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ cpp_yandex_maps_iter::CppIterGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp b/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp
new file mode 100644
index 0000000000..681ab6d642
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_csharp.cpp
@@ -0,0 +1,2100 @@
+/*
+ * 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 "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+#if defined(FLATBUFFERS_CPP98_STL)
+# include <cctype>
+#endif // defined(FLATBUFFERS_CPP98_STL)
+
+namespace flatbuffers {
+
+static TypedFloatConstantGenerator CSharpFloatGen("Double.", "Single.", "NaN",
+ "PositiveInfinity",
+ "NegativeInfinity");
+static CommentConfig comment_config = {
+ nullptr,
+ "///",
+ nullptr,
+};
+
+namespace csharp {
+class CSharpGenerator : public BaseGenerator {
+ struct FieldArrayLength {
+ std::string name;
+ int length;
+ };
+
+ public:
+ CSharpGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", ".", "cs"),
+ cur_name_space_(nullptr) {}
+
+ CSharpGenerator &operator=(const CSharpGenerator &);
+
+ bool generate() {
+ std::string one_file_code;
+ cur_name_space_ = parser_.current_namespace_;
+
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ std::string enumcode;
+ auto &enum_def = **it;
+ if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace;
+ GenEnum(enum_def, &enumcode, parser_.opts);
+ if (parser_.opts.one_file) {
+ one_file_code += enumcode;
+ } else {
+ if (!SaveType(enum_def.name, *enum_def.defined_namespace, enumcode,
+ false))
+ return false;
+ }
+ }
+
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ std::string declcode;
+ auto &struct_def = **it;
+ if (!parser_.opts.one_file)
+ cur_name_space_ = struct_def.defined_namespace;
+ GenStruct(struct_def, &declcode, parser_.opts);
+ if (parser_.opts.one_file) {
+ one_file_code += declcode;
+ } else {
+ if (!SaveType(struct_def.name, *struct_def.defined_namespace, declcode,
+ true))
+ return false;
+ }
+ }
+
+ if (parser_.opts.one_file) {
+ return SaveType(file_name_, *parser_.current_namespace_, one_file_code,
+ true);
+ }
+ return true;
+ }
+
+ // 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 =
+ "// <auto-generated>\n"
+ "// " +
+ std::string(FlatBuffersGeneratedWarning()) +
+ "\n"
+ "// </auto-generated>\n\n";
+
+ std::string namespace_name = FullNamespace(".", ns);
+ if (!namespace_name.empty()) {
+ code += "namespace " + namespace_name + "\n{\n\n";
+ }
+ if (needs_includes) {
+ code += "using global::System;\n";
+ code += "using global::System.Collections.Generic;\n";
+ code += "using global::FlatBuffers;\n\n";
+ }
+ code += classcode;
+ if (!namespace_name.empty()) { code += "\n}\n"; }
+ auto filename = NamespaceDir(ns) + defname + ".cs";
+ return SaveFile(filename.c_str(), code, false);
+ }
+
+ const Namespace *CurrentNameSpace() const { return cur_name_space_; }
+
+ std::string GenTypeBasic(const Type &type, bool enableLangOverrides) const {
+ // clang-format off
+ static const char * const csharp_typename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, ...) \
+ #NTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+
+ if (enableLangOverrides) {
+ if (IsEnum(type)) return WrapInNameSpace(*type.enum_def);
+ if (type.base_type == BASE_TYPE_STRUCT) {
+ return "Offset<" + WrapInNameSpace(*type.struct_def) + ">";
+ }
+ }
+
+ return csharp_typename[type.base_type];
+ }
+
+ inline std::string GenTypeBasic(const Type &type) const {
+ return GenTypeBasic(type, true);
+ }
+
+ 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 WrapInNameSpace(*type.struct_def);
+ case BASE_TYPE_UNION: return "TTable";
+ default: return "Table";
+ }
+ }
+
+ std::string GenTypeGet(const Type &type) const {
+ return IsScalar(type.base_type)
+ ? GenTypeBasic(type)
+ : (IsArray(type) ? GenTypeGet(type.VectorType())
+ : GenTypePointer(type));
+ }
+
+ std::string GenOffsetType(const StructDef &struct_def) const {
+ return "Offset<" + WrapInNameSpace(struct_def) + ">";
+ }
+
+ std::string GenOffsetConstruct(const StructDef &struct_def,
+ const std::string &variable_name) const {
+ return "new Offset<" + WrapInNameSpace(struct_def) + ">(" + variable_name +
+ ")";
+ }
+
+ // Casts necessary to correctly read serialized data
+ std::string DestinationCast(const Type &type) const {
+ if (IsSeries(type)) {
+ return DestinationCast(type.VectorType());
+ } else {
+ if (IsEnum(type)) return "(" + WrapInNameSpace(*type.enum_def) + ")";
+ }
+ return "";
+ }
+
+ // Cast statements for mutator method parameters.
+ // In Java, parameters representing unsigned numbers need to be cast down to
+ // their respective type. For example, a long holding an unsigned int value
+ // would be cast down to int before being put onto the buffer. In C#, one cast
+ // directly cast an Enum to its underlying type, which is essential before
+ // putting it onto the buffer.
+ std::string SourceCast(const Type &type) const {
+ if (IsSeries(type)) {
+ return SourceCast(type.VectorType());
+ } else {
+ if (IsEnum(type)) return "(" + GenTypeBasic(type, false) + ")";
+ }
+ return "";
+ }
+
+ std::string SourceCastBasic(const Type &type) const {
+ return IsScalar(type.base_type) ? SourceCast(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 ? (WrapInNameSpace(enum_def) + "." + enum_val->name)
+ : value.constant;
+ }
+
+ std::string GenDefaultValue(const FieldDef &field,
+ bool enableLangOverrides) const {
+ // If it is an optional scalar field, the default is null
+ if (field.IsScalarOptional()) { return "null"; }
+
+ auto &value = field.value;
+ if (enableLangOverrides) {
+ // handles both enum case and vector of enum case
+ if (value.type.enum_def != nullptr &&
+ value.type.base_type != BASE_TYPE_UNION) {
+ return GenEnumDefaultValue(field);
+ }
+ }
+
+ auto longSuffix = "";
+ switch (value.type.base_type) {
+ case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true";
+ case BASE_TYPE_ULONG: return value.constant;
+ case BASE_TYPE_UINT:
+ case BASE_TYPE_LONG: return value.constant + longSuffix;
+ default:
+ if (IsFloat(value.type.base_type))
+ return CSharpFloatGen.GenFloatConstant(field);
+ else
+ return value.constant;
+ }
+ }
+
+ std::string GenDefaultValue(const FieldDef &field) const {
+ return GenDefaultValue(field, true);
+ }
+
+ std::string GenDefaultValueBasic(const FieldDef &field,
+ bool enableLangOverrides) const {
+ auto &value = field.value;
+ if (!IsScalar(value.type.base_type)) {
+ if (enableLangOverrides) {
+ switch (value.type.base_type) {
+ case BASE_TYPE_STRING: return "default(StringOffset)";
+ case BASE_TYPE_STRUCT:
+ return "default(Offset<" + WrapInNameSpace(*value.type.struct_def) +
+ ">)";
+ case BASE_TYPE_VECTOR: return "default(VectorOffset)";
+ default: break;
+ }
+ }
+ return "0";
+ }
+ return GenDefaultValue(field, enableLangOverrides);
+ }
+
+ std::string GenDefaultValueBasic(const FieldDef &field) const {
+ return GenDefaultValueBasic(field, true);
+ }
+
+ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
+ const IDLOptions &opts) const {
+ std::string &code = *code_ptr;
+ if (enum_def.generated) return;
+
+ // Generate enum definitions of the form:
+ // public static (final) int name = value;
+ // In Java, we use ints rather than the Enum feature, because we want them
+ // to map directly to how they're used in C/C++ and file formats.
+ // That, and Java Enums are expensive, and not universally liked.
+ GenComment(enum_def.doc_comment, code_ptr, &comment_config);
+
+ if (opts.cs_gen_json_serializer && opts.generate_object_based_api) {
+ code +=
+ "[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters."
+ "StringEnumConverter))]\n";
+ }
+ // In C# this indicates enumeration values can be treated as bit flags.
+ if (enum_def.attributes.Lookup("bit_flags")) {
+ code += "[System.FlagsAttribute]\n";
+ }
+ if (enum_def.attributes.Lookup("private")) {
+ code += "internal ";
+ } else {
+ code += "public ";
+ }
+ code += "enum " + enum_def.name;
+ code += " : " + GenTypeBasic(enum_def.underlying_type, false);
+ code += "\n{\n";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ GenComment(ev.doc_comment, code_ptr, &comment_config, " ");
+ code += " ";
+ code += ev.name + " = ";
+ code += enum_def.ToString(ev);
+ code += ",\n";
+ }
+ // Close the class
+ code += "};\n\n";
+
+ if (opts.generate_object_based_api) {
+ GenEnum_ObjectAPI(enum_def, code_ptr, opts);
+ }
+ }
+
+ bool HasUnionStringValue(const EnumDef &enum_def) const {
+ if (!enum_def.is_union) return false;
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &val = **it;
+ if (IsString(val.union_type)) { return true; }
+ }
+ return false;
+ }
+
+ // Returns the function name that is able to read a value of the given type.
+ std::string GenGetter(const Type &type) const {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return "__p.__string";
+ case BASE_TYPE_STRUCT: return "__p.__struct";
+ case BASE_TYPE_UNION: return "__p.__union";
+ case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
+ case BASE_TYPE_ARRAY: return GenGetter(type.VectorType());
+ default: {
+ std::string getter = "__p.bb.Get";
+ if (type.base_type == BASE_TYPE_BOOL) {
+ getter = "0!=" + getter;
+ } else if (GenTypeBasic(type, false) != "byte") {
+ getter += MakeCamel(GenTypeBasic(type, false));
+ }
+ return getter;
+ }
+ }
+ }
+
+ // Returns the function name that is able to read a value of the given type.
+ std::string GenGetterForLookupByKey(flatbuffers::FieldDef *key_field,
+ const std::string &data_buffer,
+ const char *num = nullptr) const {
+ auto type = key_field->value.type;
+ auto dest_mask = "";
+ auto dest_cast = DestinationCast(type);
+ auto getter = data_buffer + ".Get";
+ if (GenTypeBasic(type, false) != "byte") {
+ getter += MakeCamel(GenTypeBasic(type, false));
+ }
+ getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")" +
+ dest_mask;
+ return getter;
+ }
+
+ // Direct mutation is only allowed for scalar fields.
+ // Hence a setter method will only be generated for such fields.
+ std::string GenSetter(const Type &type) const {
+ if (IsScalar(type.base_type)) {
+ std::string setter = "__p.bb.Put";
+ if (GenTypeBasic(type, false) != "byte" &&
+ type.base_type != BASE_TYPE_BOOL) {
+ setter += MakeCamel(GenTypeBasic(type, false));
+ }
+ return setter;
+ } else {
+ return "";
+ }
+ }
+
+ // Returns the method name for use with add/put calls.
+ std::string GenMethod(const Type &type) const {
+ return IsScalar(type.base_type) ? MakeCamel(GenTypeBasic(type, false))
+ : (IsStruct(type) ? "Struct" : "Offset");
+ }
+
+ // Recursively generate arguments for a constructor, to deal with nested
+ // structs.
+ void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
+ const char *nameprefix, size_t array_count = 0) const {
+ std::string &code = *code_ptr;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ const auto &field_type = field.value.type;
+ const auto array_field = IsArray(field_type);
+ const auto &type = array_field ? field_type.VectorType() : field_type;
+ const auto array_cnt = array_field ? (array_count + 1) : array_count;
+ if (IsStruct(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_type.struct_def, code_ptr,
+ (nameprefix + (field.name + "_")).c_str(), array_cnt);
+ } else {
+ code += ", ";
+ code += GenTypeBasic(type);
+ if (field.IsScalarOptional()) { code += "?"; }
+ if (array_cnt > 0) {
+ code += "[";
+ for (size_t i = 1; i < array_cnt; i++) code += ",";
+ code += "]";
+ }
+ code += " ";
+ code += nameprefix;
+ code += MakeCamel(field.name, true);
+ }
+ }
+ }
+
+ // Recusively generate struct construction statements of the form:
+ // builder.putType(name);
+ // and insert manual padding.
+ void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
+ const char *nameprefix, size_t index = 0,
+ bool in_array = false) const {
+ std::string &code = *code_ptr;
+ std::string indent((index + 1) * 2, ' ');
+ code += indent + " builder.Prep(";
+ code += NumToString(struct_def.minalign) + ", ";
+ code += NumToString(struct_def.bytesize) + ");\n";
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ auto &field = **it;
+ const auto &field_type = field.value.type;
+ if (field.padding) {
+ code += indent + " builder.Pad(";
+ code += NumToString(field.padding) + ");\n";
+ }
+ if (IsStruct(field_type)) {
+ GenStructBody(*field_type.struct_def, code_ptr,
+ (nameprefix + (field.name + "_")).c_str(), index,
+ in_array);
+ } else {
+ const auto &type =
+ IsArray(field_type) ? field_type.VectorType() : field_type;
+ const auto index_var = "_idx" + NumToString(index);
+ if (IsArray(field_type)) {
+ code += indent + " for (int " + index_var + " = ";
+ code += NumToString(field_type.fixed_length);
+ code += "; " + index_var + " > 0; " + index_var + "--) {\n";
+ in_array = true;
+ }
+ if (IsStruct(type)) {
+ GenStructBody(*field_type.struct_def, code_ptr,
+ (nameprefix + (field.name + "_")).c_str(), index + 1,
+ in_array);
+ } else {
+ code += IsArray(field_type) ? " " : "";
+ code += indent + " builder.Put";
+ code += GenMethod(type) + "(";
+ code += SourceCast(type);
+ auto argname = nameprefix + MakeCamel(field.name, true);
+ code += argname;
+ size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
+ if (array_cnt > 0) {
+ code += "[";
+ for (size_t i = 0; in_array && i < array_cnt; i++) {
+ code += "_idx" + NumToString(i) + "-1";
+ if (i != (array_cnt - 1)) code += ",";
+ }
+ code += "]";
+ }
+ code += ");\n";
+ }
+ if (IsArray(field_type)) { code += indent + " }\n"; }
+ }
+ }
+ }
+ std::string GenOffsetGetter(flatbuffers::FieldDef *key_field,
+ const char *num = nullptr) const {
+ std::string key_offset =
+ "Table.__offset(" + NumToString(key_field->value.offset) + ", ";
+ if (num) {
+ key_offset += num;
+ key_offset += ".Value, builder.DataBuffer)";
+ } else {
+ key_offset += "bb.Length";
+ key_offset += " - tableOffset, bb)";
+ }
+ return key_offset;
+ }
+
+ std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) const {
+ std::string key_getter = " ";
+ key_getter += "int tableOffset = Table.";
+ key_getter += "__indirect(vectorLocation + 4 * (start + middle)";
+ key_getter += ", bb);\n ";
+ if (IsString(key_field->value.type)) {
+ key_getter += "int comp = Table.";
+ key_getter += "CompareStrings(";
+ key_getter += GenOffsetGetter(key_field);
+ key_getter += ", byteKey, bb);\n";
+ } else {
+ auto get_val = GenGetterForLookupByKey(key_field, "bb");
+ key_getter += "int comp = " + get_val + ".CompareTo(key);\n";
+ }
+ return key_getter;
+ }
+
+ std::string GenKeyGetter(flatbuffers::FieldDef *key_field) const {
+ std::string key_getter = "";
+ auto data_buffer = "builder.DataBuffer";
+ if (IsString(key_field->value.type)) {
+ key_getter += "Table.CompareStrings(";
+ key_getter += GenOffsetGetter(key_field, "o1") + ", ";
+ key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")";
+ } else {
+ auto field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o1");
+ key_getter += field_getter;
+ field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2");
+ key_getter += ".CompareTo(" + field_getter + ")";
+ }
+ return key_getter;
+ }
+
+ void GenStruct(StructDef &struct_def, std::string *code_ptr,
+ const IDLOptions &opts) const {
+ if (struct_def.generated) return;
+ std::string &code = *code_ptr;
+
+ // Generate a struct accessor class, with methods of the form:
+ // public type name() { return bb.getType(i + offset); }
+ // or for tables of the form:
+ // public type name() {
+ // int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default;
+ // }
+ GenComment(struct_def.doc_comment, code_ptr, &comment_config);
+ if (struct_def.attributes.Lookup("private")) {
+ code += "internal ";
+ } else {
+ code += "public ";
+ }
+ if (struct_def.attributes.Lookup("csharp_partial")) {
+ // generate a partial class for this C# struct/table
+ code += "partial ";
+ }
+ code += "struct " + struct_def.name;
+ code += " : IFlatbufferObject";
+ code += "\n{\n";
+ code += " private ";
+ code += struct_def.fixed ? "Struct" : "Table";
+ code += " __p;\n";
+
+ code += " public ByteBuffer ByteBuffer { get { return __p.bb; } }\n";
+
+ if (!struct_def.fixed) {
+ // Generate verson check method.
+ // Force compile time error if not using the same version runtime.
+ code += " public static void ValidateVersion() {";
+ code += " FlatBufferConstants.";
+ code += "FLATBUFFERS_2_0_0(); ";
+ code += "}\n";
+
+ // Generate a special accessor for the table that when used as the root
+ // of a FlatBuffer
+ std::string method_name = "GetRootAs" + struct_def.name;
+ std::string method_signature =
+ " public static " + struct_def.name + " " + method_name;
+
+ // create convenience method that doesn't require an existing object
+ code += method_signature + "(ByteBuffer _bb) ";
+ code += "{ return " + method_name + "(_bb, new " + struct_def.name +
+ "()); }\n";
+
+ // create method that allows object reuse
+ code +=
+ method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { ";
+ code += "return (obj.__assign(_bb.GetInt(_bb.Position";
+ code += ") + _bb.Position";
+ code += ", _bb)); }\n";
+ if (parser_.root_struct_def_ == &struct_def) {
+ if (parser_.file_identifier_.length()) {
+ // Check if a buffer has the identifier.
+ code += " public static ";
+ code += "bool " + struct_def.name;
+ code += "BufferHasIdentifier(ByteBuffer _bb) { return ";
+ code += "Table.__has_identifier(_bb, \"";
+ code += parser_.file_identifier_;
+ code += "\"); }\n";
+ }
+ }
+ }
+ // Generate the __init method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ code += " public void __init(int _i, ByteBuffer _bb) ";
+ code += "{ ";
+ code += "__p = new ";
+ code += struct_def.fixed ? "Struct" : "Table";
+ code += "(_i, _bb); ";
+ code += "}\n";
+ code +=
+ " public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) ";
+ code += "{ __init(_i, _bb); return this; }\n\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ GenComment(field.doc_comment, code_ptr, &comment_config, " ");
+ std::string type_name = GenTypeGet(field.value.type);
+ std::string type_name_dest = GenTypeGet(field.value.type);
+ std::string conditional_cast = "";
+ std::string optional = "";
+ if (!struct_def.fixed &&
+ (field.value.type.base_type == BASE_TYPE_STRUCT ||
+ field.value.type.base_type == BASE_TYPE_UNION ||
+ (IsVector(field.value.type) &&
+ (field.value.type.element == BASE_TYPE_STRUCT ||
+ field.value.type.element == BASE_TYPE_UNION)))) {
+ optional = "?";
+ conditional_cast = "(" + type_name_dest + optional + ")";
+ }
+ if (field.IsScalarOptional()) { optional = "?"; }
+ std::string dest_mask = "";
+ std::string dest_cast = DestinationCast(field.value.type);
+ std::string src_cast = SourceCast(field.value.type);
+ std::string field_name_camel = MakeCamel(field.name, true);
+ std::string method_start =
+ " public " + type_name_dest + optional + " " + field_name_camel;
+ std::string obj = "(new " + type_name + "())";
+
+ // Most field accessors need to retrieve and test the field offset first,
+ // this is the prefix code for that:
+ auto offset_prefix =
+ IsArray(field.value.type)
+ ? " { return "
+ : (" { int o = __p.__offset(" + NumToString(field.value.offset) +
+ "); return o != 0 ? ");
+ // Generate the accessors that don't do object reuse.
+ if (field.value.type.base_type == BASE_TYPE_STRUCT) {
+ } else if (IsVector(field.value.type) &&
+ field.value.type.element == BASE_TYPE_STRUCT) {
+ } else if (field.value.type.base_type == BASE_TYPE_UNION ||
+ (IsVector(field.value.type) &&
+ field.value.type.VectorType().base_type == BASE_TYPE_UNION)) {
+ method_start += "<TTable>";
+ type_name = type_name_dest;
+ }
+ std::string getter = dest_cast + GenGetter(field.value.type);
+ code += method_start;
+ std::string default_cast = "";
+ // only create default casts for c# scalars or vectors of scalars
+ if ((IsScalar(field.value.type.base_type) ||
+ (IsVector(field.value.type) &&
+ IsScalar(field.value.type.element)))) {
+ // For scalars, default value will be returned by GetDefaultValue().
+ // If the scalar is an enum, GetDefaultValue() returns an actual c# enum
+ // that doesn't need to be casted. However, default values for enum
+ // elements of vectors are integer literals ("0") and are still casted
+ // for clarity.
+ // If the scalar is optional and enum, we still need the cast.
+ if ((field.value.type.enum_def == nullptr ||
+ IsVector(field.value.type)) ||
+ (IsEnum(field.value.type) && field.IsScalarOptional())) {
+ default_cast = "(" + type_name_dest + optional + ")";
+ }
+ }
+ std::string member_suffix = "; ";
+ if (IsScalar(field.value.type.base_type)) {
+ code += " { get";
+ member_suffix += "} ";
+ if (struct_def.fixed) {
+ code += " { return " + getter;
+ code += "(__p.bb_pos + ";
+ code += NumToString(field.value.offset) + ")";
+ code += dest_mask;
+ } else {
+ code += offset_prefix + getter;
+ code += "(o + __p.bb_pos)" + dest_mask;
+ code += " : " + default_cast;
+ code += GenDefaultValue(field);
+ }
+ } else {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT:
+ code += " { get";
+ member_suffix += "} ";
+ if (struct_def.fixed) {
+ code += " { return " + obj + ".__assign(" + "__p.";
+ code += "bb_pos + " + NumToString(field.value.offset) + ", ";
+ code += "__p.bb)";
+ } else {
+ code += offset_prefix + conditional_cast;
+ code += obj + ".__assign(";
+ code += field.value.type.struct_def->fixed
+ ? "o + __p.bb_pos"
+ : "__p.__indirect(o + __p.bb_pos)";
+ code += ", __p.bb) : null";
+ }
+ break;
+ case BASE_TYPE_STRING:
+ code += " { get";
+ member_suffix += "} ";
+ code += offset_prefix + getter + "(o + " + "__p.";
+ code += "bb_pos) : null";
+ break;
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ if (vectortype.base_type == BASE_TYPE_UNION) {
+ conditional_cast = "(TTable?)";
+ getter += "<TTable>";
+ }
+ code += "(";
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ getter = obj + ".__assign";
+ } else if (vectortype.base_type == BASE_TYPE_UNION) {
+ }
+ code += "int j)";
+ const auto body = offset_prefix + conditional_cast + getter + "(";
+ if (vectortype.base_type == BASE_TYPE_UNION) {
+ code += " where TTable : struct, IFlatbufferObject" + body;
+ } else {
+ code += body;
+ }
+ std::string index = "__p.";
+ if (IsArray(field.value.type)) {
+ index += "bb_pos + " + NumToString(field.value.offset) + " + ";
+ } else {
+ index += "__vector(o) + ";
+ }
+ index += "j * " + NumToString(InlineSize(vectortype));
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ code += vectortype.struct_def->fixed
+ ? index
+ : "__p.__indirect(" + index + ")";
+ code += ", __p.bb";
+ } else {
+ code += index;
+ }
+ code += ")" + dest_mask;
+ if (!IsArray(field.value.type)) {
+ code += " : ";
+ code +=
+ field.value.type.element == BASE_TYPE_BOOL
+ ? "false"
+ : (IsScalar(field.value.type.element) ? default_cast + "0"
+ : "null");
+ }
+ if (vectortype.base_type == BASE_TYPE_UNION &&
+ HasUnionStringValue(*vectortype.enum_def)) {
+ code += member_suffix;
+ code += "}\n";
+ code += " public string " + MakeCamel(field.name, true) +
+ "AsString(int j)";
+ code += offset_prefix + GenGetter(Type(BASE_TYPE_STRING));
+ code += "(" + index + ") : null";
+ }
+ break;
+ }
+ case BASE_TYPE_UNION:
+ code += "() where TTable : struct, IFlatbufferObject";
+ code += offset_prefix + "(TTable?)" + getter;
+ code += "<TTable>(o + __p.bb_pos) : null";
+ if (HasUnionStringValue(*field.value.type.enum_def)) {
+ code += member_suffix;
+ code += "}\n";
+ code += " public string " + MakeCamel(field.name, true) +
+ "AsString()";
+ code += offset_prefix + GenGetter(Type(BASE_TYPE_STRING));
+ code += "(o + __p.bb_pos) : null";
+ }
+ // As<> accesors for Unions
+ // Loop through all the possible union types and generate an As
+ // accessor that casts to the correct type.
+ for (auto uit = field.value.type.enum_def->Vals().begin();
+ uit != field.value.type.enum_def->Vals().end(); ++uit) {
+ auto val = *uit;
+ if (val->union_type.base_type == BASE_TYPE_NONE) { continue; }
+ auto union_field_type_name = GenTypeGet(val->union_type);
+ code += member_suffix + "}\n";
+ if (val->union_type.base_type == BASE_TYPE_STRUCT &&
+ val->union_type.struct_def->attributes.Lookup("private")) {
+ code += " internal ";
+ } else {
+ code += " public ";
+ }
+ code += union_field_type_name + " ";
+ code += field_name_camel + "As" + val->name + "() { return ";
+ code += field_name_camel;
+ if (IsString(val->union_type)) {
+ code += "AsString()";
+ } else {
+ code += "<" + union_field_type_name + ">().Value";
+ }
+ }
+ break;
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+ code += member_suffix;
+ code += "}\n";
+ if (IsVector(field.value.type)) {
+ code += " public int " + MakeCamel(field.name, true);
+ code += "Length";
+ code += " { get";
+ code += offset_prefix;
+ code += "__p.__vector_len(o) : 0; ";
+ code += "} ";
+ code += "}\n";
+ // 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 &key_field = **kit;
+ if (key_field.key) {
+ auto qualified_name = WrapInNameSpace(sd);
+ code += " public " + qualified_name + "? ";
+ code += MakeCamel(field.name, true) + "ByKey(";
+ code += GenTypeGet(key_field.value.type) + " key)";
+ code += offset_prefix;
+ code += qualified_name + ".__lookup_by_key(";
+ code += "__p.__vector(o), key, ";
+ code += "__p.bb) : null; ";
+ code += "}\n";
+ break;
+ }
+ }
+ }
+ }
+ // Generate a ByteBuffer accessor for strings & vectors of scalars.
+ if ((IsVector(field.value.type) &&
+ IsScalar(field.value.type.VectorType().base_type)) ||
+ IsString(field.value.type)) {
+ code += "#if ENABLE_SPAN_T\n";
+ code += " public Span<" + GenTypeBasic(field.value.type.VectorType()) +
+ "> Get";
+ code += MakeCamel(field.name, true);
+ code += "Bytes() { return ";
+ code += "__p.__vector_as_span<" +
+ GenTypeBasic(field.value.type.VectorType()) + ">(";
+ code += NumToString(field.value.offset);
+ code +=
+ ", " + NumToString(SizeOf(field.value.type.VectorType().base_type));
+ code += "); }\n";
+ code += "#else\n";
+ code += " public ArraySegment<byte>? Get";
+ code += MakeCamel(field.name, true);
+ code += "Bytes() { return ";
+ code += "__p.__vector_as_arraysegment(";
+ code += NumToString(field.value.offset);
+ code += "); }\n";
+ code += "#endif\n";
+
+ // For direct blockcopying the data into a typed array
+ code += " public ";
+ code += GenTypeBasic(field.value.type.VectorType());
+ code += "[] Get";
+ code += MakeCamel(field.name, true);
+ code += "Array() { ";
+ if (IsEnum(field.value.type.VectorType())) {
+ // Since __vector_as_array does not work for enum types,
+ // fill array using an explicit loop.
+ code += "int o = __p.__offset(";
+ code += NumToString(field.value.offset);
+ code += "); if (o == 0) return null; int p = ";
+ code += "__p.__vector(o); int l = ";
+ code += "__p.__vector_len(o); ";
+ code += GenTypeBasic(field.value.type.VectorType());
+ code += "[] a = new ";
+ code += GenTypeBasic(field.value.type.VectorType());
+ code += "[l]; for (int i = 0; i < l; i++) { a[i] = " + getter;
+ code += "(p + i * ";
+ code += NumToString(InlineSize(field.value.type.VectorType()));
+ code += "); } return a;";
+ } else {
+ code += "return ";
+ code += "__p.__vector_as_array<";
+ code += GenTypeBasic(field.value.type.VectorType());
+ code += ">(";
+ code += NumToString(field.value.offset);
+ code += ");";
+ }
+ code += " }\n";
+ }
+ // generate object accessors if is nested_flatbuffer
+ if (field.nested_flatbuffer) {
+ auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
+ auto nested_method_name =
+ MakeCamel(field.name, true) + "As" + field.nested_flatbuffer->name;
+ auto get_nested_method_name = nested_method_name;
+ get_nested_method_name = "Get" + nested_method_name;
+ conditional_cast = "(" + nested_type_name + "?)";
+ obj = "(new " + nested_type_name + "())";
+ code += " public " + nested_type_name + "? ";
+ code += get_nested_method_name + "(";
+ code += ") { int o = __p.__offset(";
+ code += NumToString(field.value.offset) + "); ";
+ code += "return o != 0 ? " + conditional_cast + obj + ".__assign(";
+ code += "__p.";
+ code += "__indirect(__p.__vector(o)), ";
+ code += "__p.bb) : null; }\n";
+ }
+ // Generate mutators for scalar fields or vectors of scalars.
+ if (parser_.opts.mutable_buffer) {
+ auto is_series = (IsSeries(field.value.type));
+ const auto &underlying_type =
+ is_series ? field.value.type.VectorType() : field.value.type;
+ // Boolean parameters have to be explicitly converted to byte
+ // representation.
+ auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL
+ ? "(byte)(" + field.name + " ? 1 : 0)"
+ : field.name;
+ auto mutator_prefix = MakeCamel("mutate", true);
+ // A vector mutator also needs the index of the vector element it should
+ // mutate.
+ auto mutator_params = (is_series ? "(int j, " : "(") +
+ GenTypeGet(underlying_type) + " " + field.name +
+ ") { ";
+ auto setter_index =
+ is_series
+ ? "__p." +
+ (IsArray(field.value.type)
+ ? "bb_pos + " + NumToString(field.value.offset)
+ : "__vector(o)") +
+ +" + j * " + NumToString(InlineSize(underlying_type))
+ : (struct_def.fixed
+ ? "__p.bb_pos + " + NumToString(field.value.offset)
+ : "o + __p.bb_pos");
+ if (IsScalar(underlying_type.base_type) && !IsUnion(field.value.type)) {
+ code += " public ";
+ code += struct_def.fixed ? "void " : "bool ";
+ code += mutator_prefix + MakeCamel(field.name, true);
+ code += mutator_params;
+ if (struct_def.fixed) {
+ code += GenSetter(underlying_type) + "(" + setter_index + ", ";
+ code += src_cast + setter_parameter + "); }\n";
+ } else {
+ code += "int o = __p.__offset(";
+ code += NumToString(field.value.offset) + ");";
+ code += " if (o != 0) { " + GenSetter(underlying_type);
+ code += "(" + setter_index + ", " + src_cast + setter_parameter +
+ "); return true; } else { return false; } }\n";
+ }
+ }
+ }
+ if (parser_.opts.java_primitive_has_method &&
+ IsScalar(field.value.type.base_type) && !struct_def.fixed) {
+ auto vt_offset_constant = " public static final int VT_" +
+ MakeScreamingCamel(field.name) + " = " +
+ NumToString(field.value.offset) + ";";
+
+ code += vt_offset_constant;
+ code += "\n";
+ }
+ }
+ code += "\n";
+ auto struct_has_create = false;
+ std::set<flatbuffers::FieldDef *> field_has_create_set;
+ flatbuffers::FieldDef *key_field = nullptr;
+ if (struct_def.fixed) {
+ struct_has_create = true;
+ // create a struct constructor function
+ code += " public static " + GenOffsetType(struct_def) + " ";
+ code += "Create";
+ code += struct_def.name + "(FlatBufferBuilder builder";
+ GenStructArgs(struct_def, code_ptr, "");
+ code += ") {\n";
+ GenStructBody(struct_def, code_ptr, "");
+ code += " return ";
+ code += GenOffsetConstruct(struct_def, "builder.Offset");
+ code += ";\n }\n";
+ } else {
+ // 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;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.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 || opts.generate_object_based_api) &&
+ num_fields && num_fields < 127) {
+ struct_has_create = true;
+ // Generate a table constructor of the form:
+ // public static int createName(FlatBufferBuilder builder, args...)
+ code += " public static " + GenOffsetType(struct_def) + " ";
+ code += "Create" + struct_def.name;
+ code += "(FlatBufferBuilder builder";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ code += ",\n ";
+ if (IsStruct(field.value.type) && opts.generate_object_based_api) {
+ code += WrapInNameSpace(
+ field.value.type.struct_def->defined_namespace,
+ GenTypeName_ObjectAPI(field.value.type.struct_def->name, opts));
+ code += " ";
+ code += field.name;
+ code += " = null";
+ } else {
+ code += GenTypeBasic(field.value.type);
+ if (field.IsScalarOptional()) { code += "?"; }
+ code += " ";
+ code += field.name;
+ if (!IsScalar(field.value.type.base_type)) code += "Offset";
+
+ code += " = ";
+ code += GenDefaultValueBasic(field);
+ }
+ }
+ code += ") {\n builder.";
+ code += "StartTable(";
+ code += NumToString(struct_def.fields.vec.size()) + ");\n";
+ for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
+ size; size /= 2) {
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ auto &field = **it;
+ if (!field.deprecated &&
+ (!struct_def.sortbysize ||
+ size == SizeOf(field.value.type.base_type))) {
+ code += " " + struct_def.name + ".";
+ code += "Add";
+ code += MakeCamel(field.name) + "(builder, ";
+ if (IsStruct(field.value.type) &&
+ opts.generate_object_based_api) {
+ code += GenTypePointer(field.value.type) + ".Pack(builder, " +
+ field.name + ")";
+ } else {
+ code += field.name;
+ if (!IsScalar(field.value.type.base_type)) code += "Offset";
+ }
+
+ code += ");\n";
+ }
+ }
+ }
+ code += " return " + struct_def.name + ".";
+ code += "End" + struct_def.name;
+ code += "(builder);\n }\n\n";
+ }
+ // Generate a set of static methods that allow table construction,
+ // of the form:
+ // public static void addName(FlatBufferBuilder builder, short name)
+ // { builder.addShort(id, name, default); }
+ // Unlike the Create function, these always work.
+ code += " public static void Start";
+ code += struct_def.name;
+ code += "(FlatBufferBuilder builder) { builder.";
+ code += "StartTable(";
+ code += NumToString(struct_def.fields.vec.size()) + "); }\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ if (field.key) key_field = &field;
+ code += " public static void Add";
+ code += MakeCamel(field.name);
+ code += "(FlatBufferBuilder builder, ";
+ code += GenTypeBasic(field.value.type);
+ auto argname = MakeCamel(field.name, false);
+ if (!IsScalar(field.value.type.base_type)) argname += "Offset";
+ if (field.IsScalarOptional()) { code += "?"; }
+ code += " " + argname + ") { builder.Add";
+ code += GenMethod(field.value.type) + "(";
+ code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
+ code += SourceCastBasic(field.value.type);
+ code += argname;
+ if (!IsScalar(field.value.type.base_type) &&
+ field.value.type.base_type != BASE_TYPE_UNION) {
+ code += ".Value";
+ }
+ if (!field.IsScalarOptional()) {
+ // When the scalar is optional, use the builder method that doesn't
+ // supply a default value. Otherwise, we to continue to use the
+ // default value method.
+ code += ", ";
+ code += GenDefaultValue(field, false);
+ }
+ code += "); }\n";
+ if (IsVector(field.value.type)) {
+ auto vector_type = field.value.type.VectorType();
+ auto alignment = InlineAlignment(vector_type);
+ auto elem_size = InlineSize(vector_type);
+ if (!IsStruct(vector_type)) {
+ field_has_create_set.insert(&field);
+ code += " public static VectorOffset ";
+ code += "Create";
+ code += MakeCamel(field.name);
+ code += "Vector(FlatBufferBuilder builder, ";
+ code += GenTypeBasic(vector_type) + "[] data) ";
+ code += "{ builder.StartVector(";
+ code += NumToString(elem_size);
+ code += ", data.Length, ";
+ code += NumToString(alignment);
+ code += "); for (int i = data.";
+ code += "Length - 1; i >= 0; i--) builder.";
+ code += "Add";
+ code += GenMethod(vector_type);
+ code += "(";
+ code += SourceCastBasic(vector_type);
+ code += "data[i]";
+ if (vector_type.base_type == BASE_TYPE_STRUCT ||
+ IsString(vector_type))
+ code += ".Value";
+ code += "); return ";
+ code += "builder.EndVector(); }\n";
+
+ code += " public static VectorOffset ";
+ code += "Create";
+ code += MakeCamel(field.name);
+ code += "VectorBlock(FlatBufferBuilder builder, ";
+ code += GenTypeBasic(vector_type) + "[] data) ";
+ code += "{ builder.StartVector(";
+ code += NumToString(elem_size);
+ code += ", data.Length, ";
+ code += NumToString(alignment);
+ code += "); builder.Add(data); return builder.EndVector(); }\n";
+ }
+ // Generate a method to start a vector, data to be added manually
+ // after.
+ code += " public static void Start";
+ code += MakeCamel(field.name);
+ code += "Vector(FlatBufferBuilder builder, int numElems) ";
+ code += "{ builder.StartVector(";
+ code += NumToString(elem_size);
+ code += ", numElems, " + NumToString(alignment);
+ code += "); }\n";
+ }
+ }
+ code += " public static " + GenOffsetType(struct_def) + " ";
+ code += "End" + struct_def.name;
+ code += "(FlatBufferBuilder builder) {\n int o = builder.";
+ code += "EndTable();\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (!field.deprecated && field.IsRequired()) {
+ code += " builder.Required(o, ";
+ code += NumToString(field.value.offset);
+ code += "); // " + field.name + "\n";
+ }
+ }
+ code += " return " + GenOffsetConstruct(struct_def, "o") + ";\n }\n";
+ if (parser_.root_struct_def_ == &struct_def) {
+ std::string size_prefix[] = { "", "SizePrefixed" };
+ for (int i = 0; i < 2; ++i) {
+ code += " public static void ";
+ code += "Finish" + size_prefix[i] + struct_def.name;
+ code +=
+ "Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def);
+ code += " offset) {";
+ code += " builder.Finish" + size_prefix[i] + "(offset";
+ code += ".Value";
+
+ if (parser_.file_identifier_.length())
+ code += ", \"" + parser_.file_identifier_ + "\"";
+ code += "); }\n";
+ }
+ }
+ }
+ // Only generate key compare function for table,
+ // because `key_field` is not set for struct
+ if (struct_def.has_key && !struct_def.fixed) {
+ FLATBUFFERS_ASSERT(key_field);
+ code += "\n public static VectorOffset ";
+ code += "CreateSortedVectorOf" + struct_def.name;
+ code += "(FlatBufferBuilder builder, ";
+ code += "Offset<" + struct_def.name + ">";
+ code += "[] offsets) {\n";
+ code += " Array.Sort(offsets, (Offset<" + struct_def.name +
+ "> o1, Offset<" + struct_def.name + "> o2) => " +
+ GenKeyGetter(key_field);
+ code += ");\n";
+ code += " return builder.CreateVectorOfTables(offsets);\n }\n";
+
+ code += "\n public static " + struct_def.name + "?";
+ code += " __lookup_by_key(";
+ code += "int vectorLocation, ";
+ code += GenTypeGet(key_field->value.type);
+ code += " key, ByteBuffer bb) {\n";
+ if (IsString(key_field->value.type)) {
+ code += " byte[] byteKey = ";
+ code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
+ }
+ code += " int span = ";
+ code += "bb.GetInt(vectorLocation - 4);\n";
+ code += " int start = 0;\n";
+ code += " while (span != 0) {\n";
+ code += " int middle = span / 2;\n";
+ code += GenLookupKeyGetter(key_field);
+ code += " if (comp > 0) {\n";
+ code += " span = middle;\n";
+ code += " } else if (comp < 0) {\n";
+ code += " middle++;\n";
+ code += " start += middle;\n";
+ code += " span -= middle;\n";
+ code += " } else {\n";
+ code += " return ";
+ code += "new " + struct_def.name + "()";
+ code += ".__assign(tableOffset, bb);\n";
+ code += " }\n }\n";
+ code += " return null;\n";
+ code += " }\n";
+ }
+
+ if (opts.generate_object_based_api) {
+ GenPackUnPack_ObjectAPI(struct_def, code_ptr, opts, struct_has_create,
+ field_has_create_set);
+ }
+ code += "};\n\n";
+
+ if (opts.generate_object_based_api) {
+ GenStruct_ObjectAPI(struct_def, code_ptr, opts);
+ }
+ }
+
+ void GenVectorAccessObject(StructDef &struct_def,
+ std::string *code_ptr) const {
+ auto &code = *code_ptr;
+ // Generate a vector of structs accessor class.
+ code += "\n";
+ code += " ";
+ if (!struct_def.attributes.Lookup("private")) code += "public ";
+ code += "static struct Vector : BaseVector\n{\n";
+
+ // Generate the __assign method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ std::string method_indent = " ";
+ code += method_indent + "public Vector ";
+ code += "__assign(int _vector, int _element_size, ByteBuffer _bb) { ";
+ code += "__reset(_vector, _element_size, _bb); return this; }\n\n";
+
+ auto type_name = struct_def.name;
+ auto method_start = method_indent + "public " + type_name + " Get";
+ // Generate the accessors that don't do object reuse.
+ code += method_start + "(int j) { return Get";
+ code += "(new " + type_name + "(), j); }\n";
+ code += method_start + "(" + type_name + " obj, int j) { ";
+ code += " return obj.__assign(";
+ code += struct_def.fixed ? "__p.__element(j)"
+ : "__p.__indirect(__p.__element(j), bb)";
+ code += ", __p.bb); }\n";
+ // See if we should generate a by-key accessor.
+ if (!struct_def.fixed) {
+ auto &fields = struct_def.fields.vec;
+ for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
+ auto &key_field = **kit;
+ if (key_field.key) {
+ auto nullable_annotation =
+ parser_.opts.gen_nullable ? "@Nullable " : "";
+ code += method_indent + nullable_annotation;
+ code += "public " + type_name + "? ";
+ code += "GetByKey(";
+ code += GenTypeGet(key_field.value.type) + " key) { ";
+ code += " return __lookup_by_key(null, ";
+ code += "__p.__vector(), key, ";
+ code += "__p.bb); ";
+ code += "}\n";
+ code += method_indent + nullable_annotation;
+ code += "public " + type_name + "?" + " ";
+ code += "GetByKey(";
+ code += type_name + "? obj, ";
+ code += GenTypeGet(key_field.value.type) + " key) { ";
+ code += " return __lookup_by_key(obj, ";
+ code += "__p.__vector(), key, ";
+ code += "__p.bb); ";
+ code += "}\n";
+ break;
+ }
+ }
+ }
+ code += " }\n";
+ }
+
+ void GenEnum_ObjectAPI(EnumDef &enum_def, std::string *code_ptr,
+ const IDLOptions &opts) const {
+ auto &code = *code_ptr;
+ if (enum_def.generated) return;
+ if (!enum_def.is_union) return;
+ if (enum_def.attributes.Lookup("private")) {
+ code += "internal ";
+ } else {
+ code += "public ";
+ }
+ auto union_name = enum_def.name + "Union";
+ code += "class " + union_name + " {\n";
+ // Type
+ code += " public " + enum_def.name + " Type { get; set; }\n";
+ // Value
+ code += " public object Value { get; set; }\n";
+ code += "\n";
+ // Constructor
+ code += " public " + union_name + "() {\n";
+ code += " this.Type = " + enum_def.name + "." +
+ enum_def.Vals()[0]->name + ";\n";
+ code += " this.Value = null;\n";
+ code += " }\n\n";
+ // As<T>
+ code += " public T As<T>() where T : class { return this.Value as T; }\n";
+ // As
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ if (ev.union_type.base_type == BASE_TYPE_NONE) continue;
+ auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts);
+ if (ev.union_type.base_type == BASE_TYPE_STRUCT &&
+ ev.union_type.struct_def->attributes.Lookup("private")) {
+ code += " internal ";
+ } else {
+ code += " public ";
+ }
+ code += type_name + " As" + ev.name + "() { return this.As<" + type_name +
+ ">(); }\n";
+ }
+ code += "\n";
+ // Pack()
+ code += " public static int Pack(FlatBuffers.FlatBufferBuilder builder, " +
+ union_name + " _o) {\n";
+ code += " switch (_o.Type) {\n";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ if (ev.union_type.base_type == BASE_TYPE_NONE) {
+ code += " default: return 0;\n";
+ } else {
+ code += " case " + enum_def.name + "." + ev.name + ": return ";
+ if (IsString(ev.union_type)) {
+ code += "builder.CreateString(_o.As" + ev.name + "()).Value;\n";
+ } else {
+ code += GenTypeGet(ev.union_type) + ".Pack(builder, _o.As" + ev.name +
+ "()).Value;\n";
+ }
+ }
+ }
+ code += " }\n";
+ code += " }\n";
+ code += "}\n\n";
+ // JsonConverter
+ if (opts.cs_gen_json_serializer) {
+ if (enum_def.attributes.Lookup("private")) {
+ code += "internal ";
+ } else {
+ code += "public ";
+ }
+ code += "class " + union_name +
+ "_JsonConverter : Newtonsoft.Json.JsonConverter {\n";
+ code += " public override bool CanConvert(System.Type objectType) {\n";
+ code += " return objectType == typeof(" + union_name +
+ ") || objectType == typeof(System.Collections.Generic.List<" +
+ union_name + ">);\n";
+ code += " }\n";
+ code +=
+ " public override void WriteJson(Newtonsoft.Json.JsonWriter writer, "
+ "object value, "
+ "Newtonsoft.Json.JsonSerializer serializer) {\n";
+ code += " var _olist = value as System.Collections.Generic.List<" +
+ union_name + ">;\n";
+ code += " if (_olist != null) {\n";
+ code += " writer.WriteStartArray();\n";
+ code +=
+ " foreach (var _o in _olist) { this.WriteJson(writer, _o, "
+ "serializer); }\n";
+ code += " writer.WriteEndArray();\n";
+ code += " } else {\n";
+ code += " this.WriteJson(writer, value as " + union_name +
+ ", serializer);\n";
+ code += " }\n";
+ code += " }\n";
+ code += " public void WriteJson(Newtonsoft.Json.JsonWriter writer, " +
+ union_name +
+ " _o, "
+ "Newtonsoft.Json.JsonSerializer serializer) {\n";
+ code += " if (_o == null) return;\n";
+ code += " serializer.Serialize(writer, _o.Value);\n";
+ code += " }\n";
+ code +=
+ " public override object ReadJson(Newtonsoft.Json.JsonReader "
+ "reader, "
+ "System.Type objectType, "
+ "object existingValue, Newtonsoft.Json.JsonSerializer serializer) "
+ "{\n";
+ code +=
+ " var _olist = existingValue as System.Collections.Generic.List<" +
+ union_name + ">;\n";
+ code += " if (_olist != null) {\n";
+ code += " for (var _j = 0; _j < _olist.Count; ++_j) {\n";
+ code += " reader.Read();\n";
+ code +=
+ " _olist[_j] = this.ReadJson(reader, _olist[_j], "
+ "serializer);\n";
+ code += " }\n";
+ code += " reader.Read();\n";
+ code += " return _olist;\n";
+ code += " } else {\n";
+ code += " return this.ReadJson(reader, existingValue as " +
+ union_name + ", serializer);\n";
+ code += " }\n";
+ code += " }\n";
+ code += " public " + union_name +
+ " ReadJson(Newtonsoft.Json.JsonReader reader, " + union_name +
+ " _o, Newtonsoft.Json.JsonSerializer serializer) {\n";
+ code += " if (_o == null) return null;\n";
+ code += " switch (_o.Type) {\n";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ auto &ev = **it;
+ if (ev.union_type.base_type == BASE_TYPE_NONE) {
+ code += " default: break;\n";
+ } else {
+ auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts);
+ code += " case " + enum_def.name + "." + ev.name +
+ ": _o.Value = serializer.Deserialize<" + type_name +
+ ">(reader); break;\n";
+ }
+ }
+ code += " }\n";
+ code += " return _o;\n";
+ code += " }\n";
+ code += "}\n\n";
+ }
+ }
+
+ std::string GenTypeName_ObjectAPI(const std::string &name,
+ const IDLOptions &opts) const {
+ return opts.object_prefix + name + opts.object_suffix;
+ }
+
+ void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string *code_ptr,
+ const std::string &camel_name,
+ bool is_vector) const {
+ auto &code = *code_ptr;
+ std::string varialbe_name = "_o." + camel_name;
+ std::string type_suffix = "";
+ std::string func_suffix = "()";
+ std::string indent = " ";
+ if (is_vector) {
+ varialbe_name = "_o_" + camel_name;
+ type_suffix = "(_j)";
+ func_suffix = "(_j)";
+ indent = " ";
+ }
+ if (is_vector) {
+ code += indent + "var " + varialbe_name + " = new ";
+ } else {
+ code += indent + varialbe_name + " = new ";
+ }
+ code += WrapInNameSpace(enum_def) + "Union();\n";
+ code += indent + varialbe_name + ".Type = this." + camel_name + "Type" +
+ type_suffix + ";\n";
+ code +=
+ indent + "switch (this." + camel_name + "Type" + type_suffix + ") {\n";
+ for (auto eit = enum_def.Vals().begin(); eit != enum_def.Vals().end();
+ ++eit) {
+ auto &ev = **eit;
+ if (ev.union_type.base_type == BASE_TYPE_NONE) {
+ code += indent + " default: break;\n";
+ } else {
+ code += indent + " case " + WrapInNameSpace(enum_def) + "." + ev.name +
+ ":\n";
+ code += indent + " " + varialbe_name + ".Value = this." + camel_name;
+ if (IsString(ev.union_type)) {
+ code += "AsString" + func_suffix + ";\n";
+ } else {
+ code += "<" + GenTypeGet(ev.union_type) + ">" + func_suffix;
+ code += ".HasValue ? this." + camel_name;
+ code += "<" + GenTypeGet(ev.union_type) + ">" + func_suffix +
+ ".Value.UnPack() : null;\n";
+ }
+ code += indent + " break;\n";
+ }
+ }
+ code += indent + "}\n";
+ if (is_vector) {
+ code += indent + "_o." + camel_name + ".Add(" + varialbe_name + ");\n";
+ }
+ }
+
+ void GenPackUnPack_ObjectAPI(
+ StructDef &struct_def, std::string *code_ptr, const IDLOptions &opts,
+ bool struct_has_create,
+ const std::set<FieldDef *> &field_has_create) const {
+ auto &code = *code_ptr;
+ auto struct_name = GenTypeName_ObjectAPI(struct_def.name, opts);
+ // UnPack()
+ code += " public " + struct_name + " UnPack() {\n";
+ code += " var _o = new " + struct_name + "();\n";
+ code += " this.UnPackTo(_o);\n";
+ code += " return _o;\n";
+ code += " }\n";
+ // UnPackTo()
+ code += " public void UnPackTo(" + struct_name + " _o) {\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto camel_name = MakeCamel(field.name);
+ auto start = " _o." + camel_name + " = ";
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ auto fixed = struct_def.fixed && field.value.type.struct_def->fixed;
+ if (fixed) {
+ code += start + "this." + camel_name + ".UnPack();\n";
+ } else {
+ code += start + "this." + camel_name + ".HasValue ? this." +
+ camel_name + ".Value.UnPack() : null;\n";
+ }
+ break;
+ }
+ case BASE_TYPE_ARRAY: {
+ auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
+ auto length_str = NumToString(field.value.type.fixed_length);
+ auto unpack_method = field.value.type.struct_def == nullptr
+ ? ""
+ : field.value.type.struct_def->fixed
+ ? ".UnPack()"
+ : "?.UnPack()";
+ code += start + "new " + type_name.substr(0, type_name.length() - 1) +
+ length_str + "];\n";
+ code += " for (var _j = 0; _j < " + length_str + "; ++_j) { _o." +
+ camel_name + "[_j] = this." + camel_name + "(_j)" +
+ unpack_method + "; }\n";
+ break;
+ }
+ case BASE_TYPE_VECTOR:
+ if (field.value.type.element == BASE_TYPE_UNION) {
+ code += start + "new " +
+ GenTypeGet_ObjectAPI(field.value.type, opts) + "();\n";
+ code += " for (var _j = 0; _j < this." + camel_name +
+ "Length; ++_j) {\n";
+ GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
+ camel_name, true);
+ code += " }\n";
+ } else if (field.value.type.element != BASE_TYPE_UTYPE) {
+ auto fixed = field.value.type.struct_def == nullptr;
+ code += start + "new " +
+ GenTypeGet_ObjectAPI(field.value.type, opts) + "();\n";
+ code += " for (var _j = 0; _j < this." + camel_name +
+ "Length; ++_j) {";
+ code += "_o." + camel_name + ".Add(";
+ if (fixed) {
+ code += "this." + camel_name + "(_j)";
+ } else {
+ code += "this." + camel_name + "(_j).HasValue ? this." +
+ camel_name + "(_j).Value.UnPack() : null";
+ }
+ code += ");}\n";
+ }
+ break;
+ case BASE_TYPE_UTYPE: break;
+ case BASE_TYPE_UNION: {
+ GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
+ camel_name, false);
+ break;
+ }
+ default: {
+ code += start + "this." + camel_name + ";\n";
+ break;
+ }
+ }
+ }
+ code += " }\n";
+ // Pack()
+ code += " public static " + GenOffsetType(struct_def) +
+ " Pack(FlatBufferBuilder builder, " + struct_name + " _o) {\n";
+ code += " if (_o == null) return default(" + GenOffsetType(struct_def) +
+ ");\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto camel_name = MakeCamel(field.name);
+ // pre
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ if (!field.value.type.struct_def->fixed) {
+ code += " var _" + field.name + " = _o." + camel_name +
+ " == null ? default(" +
+ GenOffsetType(*field.value.type.struct_def) +
+ ") : " + GenTypeGet(field.value.type) +
+ ".Pack(builder, _o." + camel_name + ");\n";
+ } else if (struct_def.fixed && struct_has_create) {
+ std::vector<FieldArrayLength> array_lengths;
+ FieldArrayLength tmp_array_length = {
+ field.name,
+ field.value.type.fixed_length,
+ };
+ array_lengths.push_back(tmp_array_length);
+ GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
+ array_lengths);
+ }
+ break;
+ }
+ case BASE_TYPE_STRING: {
+ std::string create_string =
+ field.shared ? "CreateSharedString" : "CreateString";
+ code += " var _" + field.name + " = _o." + camel_name +
+ " == null ? default(StringOffset) : "
+ "builder." +
+ create_string + "(_o." + camel_name + ");\n";
+ break;
+ }
+ case BASE_TYPE_VECTOR: {
+ if (field_has_create.find(&field) != field_has_create.end()) {
+ auto property_name = camel_name;
+ auto gen_for_loop = true;
+ std::string array_name = "__" + field.name;
+ std::string array_type = "";
+ std::string to_array = "";
+ switch (field.value.type.element) {
+ case BASE_TYPE_STRING: {
+ std::string create_string =
+ field.shared ? "CreateSharedString" : "CreateString";
+ array_type = "StringOffset";
+ to_array += "builder." + create_string + "(_o." +
+ property_name + "[_j])";
+ break;
+ }
+ case BASE_TYPE_STRUCT:
+ array_type = "Offset<" + GenTypeGet(field.value.type) + ">";
+ to_array = GenTypeGet(field.value.type) + ".Pack(builder, _o." +
+ property_name + "[_j])";
+ break;
+ case BASE_TYPE_UTYPE:
+ property_name = camel_name.substr(0, camel_name.size() - 4);
+ array_type = WrapInNameSpace(*field.value.type.enum_def);
+ to_array = "_o." + property_name + "[_j].Type";
+ break;
+ case BASE_TYPE_UNION:
+ array_type = "int";
+ to_array = WrapInNameSpace(*field.value.type.enum_def) +
+ "Union.Pack(builder, _o." + property_name + "[_j])";
+ break;
+ default: gen_for_loop = false; break;
+ }
+ code += " var _" + field.name + " = default(VectorOffset);\n";
+ code += " if (_o." + property_name + " != null) {\n";
+ if (gen_for_loop) {
+ code += " var " + array_name + " = new " + array_type +
+ "[_o." + property_name + ".Count];\n";
+ code += " for (var _j = 0; _j < " + array_name +
+ ".Length; ++_j) { ";
+ code += array_name + "[_j] = " + to_array + "; }\n";
+ } else {
+ code += " var " + array_name + " = _o." + property_name +
+ ".ToArray();\n";
+ }
+ code += " _" + field.name + " = Create" + camel_name +
+ "Vector(builder, " + array_name + ");\n";
+ code += " }\n";
+ } else {
+ auto pack_method =
+ field.value.type.struct_def == nullptr
+ ? "builder.Add" + GenMethod(field.value.type.VectorType()) +
+ "(_o." + camel_name + "[_j]);"
+ : GenTypeGet(field.value.type) + ".Pack(builder, _o." +
+ camel_name + "[_j]);";
+ code += " var _" + field.name + " = default(VectorOffset);\n";
+ code += " if (_o." + camel_name + " != null) {\n";
+ code += " Start" + camel_name + "Vector(builder, _o." +
+ camel_name + ".Count);\n";
+ code += " for (var _j = _o." + camel_name +
+ ".Count - 1; _j >= 0; --_j) { " + pack_method + " }\n";
+ code += " _" + field.name + " = builder.EndVector();\n";
+ code += " }\n";
+ }
+ break;
+ }
+ case BASE_TYPE_ARRAY: {
+ if (field.value.type.struct_def != nullptr) {
+ std::vector<FieldArrayLength> array_lengths;
+ FieldArrayLength tmp_array_length = {
+ field.name,
+ field.value.type.fixed_length,
+ };
+ array_lengths.push_back(tmp_array_length);
+ GenStructPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
+ array_lengths);
+ } else {
+ code += " var _" + field.name + " = _o." + camel_name + ";\n";
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ code += " var _" + field.name + "_type = _o." + camel_name +
+ " == null ? " + WrapInNameSpace(*field.value.type.enum_def) +
+ ".NONE : " + "_o." + camel_name + ".Type;\n";
+ code +=
+ " var _" + field.name + " = _o." + camel_name +
+ " == null ? 0 : " + GenTypeGet_ObjectAPI(field.value.type, opts) +
+ ".Pack(builder, _o." + camel_name + ");\n";
+ break;
+ }
+ default: break;
+ }
+ }
+ if (struct_has_create) {
+ // Create
+ code += " return Create" + struct_def.name + "(\n";
+ code += " builder";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto camel_name = MakeCamel(field.name);
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ if (struct_def.fixed) {
+ GenStructPackCall_ObjectAPI(*field.value.type.struct_def,
+ code_ptr,
+ " _" + field.name + "_");
+ } else {
+ code += ",\n";
+ if (field.value.type.struct_def->fixed) {
+ if (opts.generate_object_based_api)
+ code += " _o." + camel_name;
+ else
+ code += " " + GenTypeGet(field.value.type) +
+ ".Pack(builder, _o." + camel_name + ")";
+ } else {
+ code += " _" + field.name;
+ }
+ }
+ break;
+ }
+ case BASE_TYPE_ARRAY: {
+ if (field.value.type.struct_def != nullptr) {
+ GenStructPackCall_ObjectAPI(*field.value.type.struct_def,
+ code_ptr,
+ " _" + field.name + "_");
+ } else {
+ code += ",\n";
+ code += " _" + field.name;
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_UTYPE: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_VECTOR: {
+ code += ",\n";
+ code += " _" + field.name;
+ break;
+ }
+ default: // scalar
+ code += ",\n";
+ code += " _o." + camel_name;
+ break;
+ }
+ }
+ code += ");\n";
+ } else {
+ // Start, End
+ code += " Start" + struct_def.name + "(builder);\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto camel_name = MakeCamel(field.name);
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ if (field.value.type.struct_def->fixed) {
+ code += " Add" + camel_name + "(builder, " +
+ GenTypeGet(field.value.type) + ".Pack(builder, _o." +
+ camel_name + "));\n";
+ } else {
+ code +=
+ " Add" + camel_name + "(builder, _" + field.name + ");\n";
+ }
+ break;
+ }
+ case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_VECTOR: {
+ code +=
+ " Add" + camel_name + "(builder, _" + field.name + ");\n";
+ break;
+ }
+ case BASE_TYPE_UTYPE: break;
+ case BASE_TYPE_UNION: {
+ code += " Add" + camel_name + "Type(builder, _" + field.name +
+ "_type);\n";
+ code +=
+ " Add" + camel_name + "(builder, _" + field.name + ");\n";
+ break;
+ }
+ // scalar
+ default: {
+ code +=
+ " Add" + camel_name + "(builder, _o." + camel_name + ");\n";
+ break;
+ }
+ }
+ }
+ code += " return End" + struct_def.name + "(builder);\n";
+ }
+ code += " }\n";
+ }
+
+ void GenStructPackDecl_ObjectAPI(
+ const StructDef &struct_def, std::string *code_ptr,
+ std::vector<FieldArrayLength> &array_lengths) const {
+ auto &code = *code_ptr;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ auto is_array = IsArray(field.value.type);
+ const auto &field_type =
+ is_array ? field.value.type.VectorType() : field.value.type;
+ FieldArrayLength tmp_array_length = {
+ field.name,
+ field_type.fixed_length,
+ };
+ array_lengths.push_back(tmp_array_length);
+ if (field_type.struct_def != nullptr) {
+ GenStructPackDecl_ObjectAPI(*field_type.struct_def, code_ptr,
+ array_lengths);
+ } else {
+ std::vector<FieldArrayLength> array_only_lengths;
+ for (size_t i = 0; i < array_lengths.size(); ++i) {
+ if (array_lengths[i].length > 0) {
+ array_only_lengths.push_back(array_lengths[i]);
+ }
+ }
+ std::string name;
+ for (size_t i = 0; i < array_lengths.size(); ++i) {
+ name += "_" + array_lengths[i].name;
+ }
+ code += " var " + name + " = ";
+ if (array_only_lengths.size() > 0) {
+ code += "new " + GenTypeBasic(field_type) + "[";
+ for (size_t i = 0; i < array_only_lengths.size(); ++i) {
+ if (i != 0) { code += ","; }
+ code += NumToString(array_only_lengths[i].length);
+ }
+ code += "];\n";
+ code += " ";
+ // initialize array
+ for (size_t i = 0; i < array_only_lengths.size(); ++i) {
+ auto idx = "idx" + NumToString(i);
+ code += "for (var " + idx + " = 0; " + idx + " < " +
+ NumToString(array_only_lengths[i].length) + "; ++" + idx +
+ ") {";
+ }
+ for (size_t i = 0; i < array_only_lengths.size(); ++i) {
+ auto idx = "idx" + NumToString(i);
+ if (i == 0) {
+ code += name + "[" + idx;
+ } else {
+ code += "," + idx;
+ }
+ }
+ code += "] = _o";
+ for (size_t i = 0, j = 0; i < array_lengths.size(); ++i) {
+ code += "." + MakeCamel(array_lengths[i].name);
+ if (array_lengths[i].length <= 0) continue;
+ code += "[idx" + NumToString(j++) + "]";
+ }
+ code += ";";
+ for (size_t i = 0; i < array_only_lengths.size(); ++i) {
+ code += "}";
+ }
+ } else {
+ code += "_o";
+ for (size_t i = 0; i < array_lengths.size(); ++i) {
+ code += "." + MakeCamel(array_lengths[i].name);
+ }
+ code += ";";
+ }
+ code += "\n";
+ }
+ array_lengths.pop_back();
+ }
+ }
+
+ void GenStructPackCall_ObjectAPI(const StructDef &struct_def,
+ std::string *code_ptr,
+ std::string prefix) const {
+ auto &code = *code_ptr;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ const auto &field_type = field.value.type;
+ if (field_type.struct_def != nullptr) {
+ GenStructPackCall_ObjectAPI(*field_type.struct_def, code_ptr,
+ prefix + field.name + "_");
+ } else {
+ code += ",\n";
+ code += prefix + field.name;
+ }
+ }
+ }
+
+ std::string GenTypeGet_ObjectAPI(flatbuffers::Type type,
+ const IDLOptions &opts) const {
+ auto type_name = GenTypeGet(type);
+ // Replace to ObjectBaseAPI Type Name
+ switch (type.base_type) {
+ case BASE_TYPE_STRUCT: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_VECTOR: {
+ if (type.struct_def != nullptr) {
+ auto type_name_length = type.struct_def->name.length();
+ auto new_type_name =
+ GenTypeName_ObjectAPI(type.struct_def->name, opts);
+ type_name.replace(type_name.length() - type_name_length,
+ type_name_length, new_type_name);
+ } else if (type.element == BASE_TYPE_UNION) {
+ type_name = WrapInNameSpace(*type.enum_def) + "Union";
+ }
+ break;
+ }
+
+ case BASE_TYPE_UNION: {
+ type_name = WrapInNameSpace(*type.enum_def) + "Union";
+ break;
+ }
+ default: break;
+ }
+
+ switch (type.base_type) {
+ case BASE_TYPE_ARRAY: {
+ type_name = type_name + "[]";
+ break;
+ }
+ case BASE_TYPE_VECTOR: {
+ type_name = "List<" + type_name + ">";
+ break;
+ }
+ default: break;
+ }
+ return type_name;
+ }
+
+ void GenStruct_ObjectAPI(StructDef &struct_def, std::string *code_ptr,
+ const IDLOptions &opts) const {
+ auto &code = *code_ptr;
+ if (struct_def.attributes.Lookup("private")) {
+ code += "internal ";
+ } else {
+ code += "public ";
+ }
+ if (struct_def.attributes.Lookup("csharp_partial")) {
+ // generate a partial class for this C# struct/table
+ code += "partial ";
+ }
+ auto class_name = GenTypeName_ObjectAPI(struct_def.name, opts);
+ code += "class " + class_name;
+ code += "\n{\n";
+ // Generate Properties
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
+ if (field.value.type.element == BASE_TYPE_UTYPE) continue;
+ auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
+ if (field.IsScalarOptional()) type_name += "?";
+ auto camel_name = MakeCamel(field.name, true);
+ if (opts.cs_gen_json_serializer) {
+ if (IsUnion(field.value.type)) {
+ auto utype_name = WrapInNameSpace(*field.value.type.enum_def);
+ code +=
+ " [Newtonsoft.Json.JsonProperty(\"" + field.name + "_type\")]\n";
+ if (IsVector(field.value.type)) {
+ code += " private " + utype_name + "[] " + camel_name + "Type {\n";
+ code += " get {\n";
+ code += " if (this." + camel_name + " == null) return null;\n";
+ code += " var _o = new " + utype_name + "[this." + camel_name +
+ ".Count];\n";
+ code +=
+ " for (var _j = 0; _j < _o.Length; ++_j) { _o[_j] = "
+ "this." +
+ camel_name + "[_j].Type; }\n";
+ code += " return _o;\n";
+ code += " }\n";
+ code += " set {\n";
+ code += " this." + camel_name + " = new List<" + utype_name +
+ "Union>();\n";
+ code += " for (var _j = 0; _j < value.Length; ++_j) {\n";
+ code += " var _o = new " + utype_name + "Union();\n";
+ code += " _o.Type = value[_j];\n";
+ code += " this." + camel_name + ".Add(_o);\n";
+ code += " }\n";
+ code += " }\n";
+ code += " }\n";
+ } else {
+ code += " private " + utype_name + " " + camel_name + "Type {\n";
+ code += " get {\n";
+ code += " return this." + camel_name + " != null ? this." +
+ camel_name + ".Type : " + utype_name + ".NONE;\n";
+ code += " }\n";
+ code += " set {\n";
+ code += " this." + camel_name + " = new " + utype_name +
+ "Union();\n";
+ code += " this." + camel_name + ".Type = value;\n";
+ code += " }\n";
+ code += " }\n";
+ }
+ }
+ code += " [Newtonsoft.Json.JsonProperty(\"" + field.name + "\")]\n";
+ if (IsUnion(field.value.type)) {
+ auto union_name =
+ (IsVector(field.value.type))
+ ? GenTypeGet_ObjectAPI(field.value.type.VectorType(), opts)
+ : type_name;
+ code += " [Newtonsoft.Json.JsonConverter(typeof(" + union_name +
+ "_JsonConverter))]\n";
+ }
+ if (field.attributes.Lookup("hash")) {
+ code += " [Newtonsoft.Json.JsonIgnore()]\n";
+ }
+ }
+ code += " public " + type_name + " " + camel_name + " { get; set; }\n";
+ }
+ // Generate Constructor
+ code += "\n";
+ code += " public " + class_name + "() {\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
+ if (field.value.type.element == BASE_TYPE_UTYPE) continue;
+ code += " this." + MakeCamel(field.name) + " = ";
+ auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
+ if (IsScalar(field.value.type.base_type)) {
+ code += GenDefaultValue(field) + ";\n";
+ } else {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ if (IsStruct(field.value.type)) {
+ code += "new " + type_name + "();\n";
+ } else {
+ code += "null;\n";
+ }
+ break;
+ }
+ case BASE_TYPE_ARRAY: {
+ code += "new " + type_name.substr(0, type_name.length() - 1) +
+ NumToString(field.value.type.fixed_length) + "];\n";
+ break;
+ }
+ default: {
+ code += "null;\n";
+ break;
+ }
+ }
+ }
+ }
+ code += " }\n";
+ // Generate Serialization
+ if (opts.cs_gen_json_serializer &&
+ parser_.root_struct_def_ == &struct_def) {
+ code += "\n";
+ code += " public static " + class_name +
+ " DeserializeFromJson(string jsonText) {\n";
+ code += " return Newtonsoft.Json.JsonConvert.DeserializeObject<" +
+ class_name + ">(jsonText);\n";
+ code += " }\n";
+ code += " public string SerializeToJson() {\n";
+ code +=
+ " return Newtonsoft.Json.JsonConvert.SerializeObject(this, "
+ "Newtonsoft.Json.Formatting.Indented);\n";
+ code += " }\n";
+ }
+ if (parser_.root_struct_def_ == &struct_def) {
+ code += " public static " + class_name +
+ " DeserializeFromBinary(byte[] fbBuffer) {\n";
+ code += " return " + struct_def.name + ".GetRootAs" + struct_def.name +
+ "(new ByteBuffer(fbBuffer)).UnPack();\n";
+ code += " }\n";
+ code += " public byte[] SerializeToBinary() {\n";
+ code += " var fbb = new FlatBufferBuilder(0x10000);\n";
+ code += " " + struct_def.name + ".Finish" + struct_def.name +
+ "Buffer(fbb, " + struct_def.name + ".Pack(fbb, this));\n";
+ code += " return fbb.DataBuffer.ToSizedArray();\n";
+ code += " }\n";
+ }
+ code += "}\n\n";
+ }
+
+ // This tracks the current namespace used to determine if a type need to be
+ // prefixed by its namespace
+ const Namespace *cur_name_space_;
+};
+} // namespace csharp
+
+bool GenerateCSharp(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ csharp::CSharpGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_dart.cpp b/contrib/libs/flatbuffers/src/idl_gen_dart.cpp
new file mode 100644
index 0000000000..56c4a82555
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_dart.cpp
@@ -0,0 +1,955 @@
+/*
+ * Copyright 2018 Dan Field
+ *
+ * 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 <cassert>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+namespace dart {
+
+const std::string _kFb = "fb";
+// see https://www.dartlang.org/guides/language/language-tour#keywords
+// yeild*, async*, and sync* shouldn't be problems anyway but keeping them in
+static const char *keywords[] = {
+ "abstract", "deferred", "if", "super", "as", "do",
+ "implements", "switch", "assert", "dynamic", "import", "sync*",
+ "async", "else", "in", "this", "async*", "enum",
+ "is", "throw", "await", "export", "library", "true",
+ "break", "external", "new", "try", "case", "extends",
+ "null", "typedef", "catch", "factory", "operator", "var",
+ "class", "false", "part", "void", "const", "final",
+ "rethrow", "while", "continue", "finally", "return", "with",
+ "covariant", "for", "set", "yield", "default", "get",
+ "static", "yield*"
+};
+
+// Iterate through all definitions we haven't generate code for (enums, structs,
+// and tables) and output them to a single file.
+class DartGenerator : public BaseGenerator {
+ public:
+ typedef std::map<std::string, std::string> namespace_code_map;
+
+ DartGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", ".", "dart") {}
+ // Iterate through all definitions we haven't generate code for (enums,
+ // structs, and tables) and output them to a single file.
+ bool generate() {
+ std::string code;
+ namespace_code_map namespace_code;
+ GenerateEnums(&namespace_code);
+ GenerateStructs(&namespace_code);
+
+ for (auto kv = namespace_code.begin(); kv != namespace_code.end(); ++kv) {
+ code.clear();
+ code = code + "// " + FlatBuffersGeneratedWarning() + "\n";
+ code = code +
+ "// ignore_for_file: unused_import, unused_field, "
+ "unused_local_variable\n\n";
+
+ if (!kv->first.empty()) { code += "library " + kv->first + ";\n\n"; }
+
+ code += "import 'dart:typed_data' show Uint8List;\n";
+ code += "import 'package:flat_buffers/flat_buffers.dart' as " + _kFb +
+ ";\n\n";
+
+ for (auto kv2 = namespace_code.begin(); kv2 != namespace_code.end();
+ ++kv2) {
+ if (kv2->first != kv->first) {
+ code +=
+ "import '" +
+ GeneratedFileName(
+ "./",
+ file_name_ + (!kv2->first.empty() ? "_" + kv2->first : ""),
+ parser_.opts) +
+ "' as " + ImportAliasName(kv2->first) + ";\n";
+ }
+ }
+ code += "\n";
+ code += kv->second;
+
+ if (!SaveFile(
+ GeneratedFileName(
+ path_,
+ file_name_ + (!kv->first.empty() ? "_" + kv->first : ""),
+ parser_.opts)
+ .c_str(),
+ code, false)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private:
+ static std::string ImportAliasName(const std::string &ns) {
+ std::string ret;
+ ret.assign(ns);
+ size_t pos = ret.find('.');
+ while (pos != std::string::npos) {
+ ret.replace(pos, 1, "_");
+ pos = ret.find('.', pos + 1);
+ }
+
+ return ret;
+ }
+
+ static std::string BuildNamespaceName(const Namespace &ns) {
+ if (ns.components.empty()) { return ""; }
+ std::stringstream sstream;
+ std::copy(ns.components.begin(), ns.components.end() - 1,
+ std::ostream_iterator<std::string>(sstream, "."));
+
+ auto ret = sstream.str() + ns.components.back();
+ for (size_t i = 0; i < ret.size(); i++) {
+ auto lower = CharToLower(ret[i]);
+ if (lower != ret[i]) {
+ ret[i] = lower;
+ if (i != 0 && ret[i - 1] != '.') {
+ ret.insert(i, "_");
+ i++;
+ }
+ }
+ }
+ // std::transform(ret.begin(), ret.end(), ret.begin(), CharToLower);
+ return ret;
+ }
+
+ void GenIncludeDependencies(std::string *code,
+ const std::string &the_namespace) {
+ for (auto it = parser_.included_files_.begin();
+ it != parser_.included_files_.end(); ++it) {
+ if (it->second.empty()) continue;
+
+ auto noext = flatbuffers::StripExtension(it->second);
+ auto basename = flatbuffers::StripPath(noext);
+
+ *code +=
+ "import '" +
+ GeneratedFileName(
+ "", basename + (the_namespace == "" ? "" : "_" + the_namespace),
+ parser_.opts) +
+ "';\n";
+ }
+ }
+
+ static std::string EscapeKeyword(const std::string &name) {
+ for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
+ if (name == keywords[i]) { return MakeCamel(name + "_", false); }
+ }
+
+ return MakeCamel(name, false);
+ }
+
+ void GenerateEnums(namespace_code_map *namespace_code) {
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ auto &enum_def = **it;
+ GenEnum(enum_def, namespace_code); // enum_code_ptr);
+ }
+ }
+
+ void GenerateStructs(namespace_code_map *namespace_code) {
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ auto &struct_def = **it;
+ GenStruct(struct_def, namespace_code);
+ }
+ }
+
+ // Generate a documentation comment, if available.
+ static void GenDocComment(const std::vector<std::string> &dc,
+ std::string *code_ptr,
+ const std::string &extra_lines,
+ const char *indent = nullptr) {
+ if (dc.empty() && extra_lines.empty()) {
+ // Don't output empty comment blocks with 0 lines of comment content.
+ return;
+ }
+
+ auto &code = *code_ptr;
+
+ for (auto it = dc.begin(); it != dc.end(); ++it) {
+ if (indent) code += indent;
+ code += "/// " + *it + "\n";
+ }
+ if (!extra_lines.empty()) {
+ if (!dc.empty()) {
+ if (indent) code += indent;
+ code += "///\n";
+ }
+ if (indent) code += indent;
+ std::string::size_type start = 0;
+ for (;;) {
+ auto end = extra_lines.find('\n', start);
+ if (end != std::string::npos) {
+ code += "/// " + extra_lines.substr(start, end - start) + "\n";
+ start = end + 1;
+ } else {
+ code += "/// " + extra_lines.substr(start) + "\n";
+ break;
+ }
+ }
+ }
+ }
+
+ static void GenDocComment(std::string *code_ptr,
+ const std::string &extra_lines) {
+ GenDocComment(std::vector<std::string>(), code_ptr, extra_lines);
+ }
+
+ // Generate an enum declaration and an enum string lookup table.
+ void GenEnum(EnumDef &enum_def, namespace_code_map *namespace_code) {
+ if (enum_def.generated) return;
+ auto ns = BuildNamespaceName(*enum_def.defined_namespace);
+ std::string code;
+ GenDocComment(enum_def.doc_comment, &code, "");
+
+ auto name = enum_def.is_union ? enum_def.name + "TypeId" : enum_def.name;
+ auto is_bit_flags = enum_def.attributes.Lookup("bit_flags");
+
+ code += "class " + name + " {\n";
+ code += " final int value;\n";
+ code += " const " + name + "._(this.value);\n\n";
+ code += " factory " + name + ".fromValue(int value) {\n";
+ code += " if (value == null) value = 0;\n";
+
+ code += " if (!values.containsKey(value)) {\n";
+ code +=
+ " throw new StateError('Invalid value $value for bit flag enum ";
+ code += name + "');\n";
+ code += " }\n";
+
+ code += " return values[value];\n";
+ code += " }\n\n";
+
+ // this is meaningless for bit_flags
+ // however, note that unlike "regular" dart enums this enum can still have
+ // holes.
+ if (!is_bit_flags) {
+ code += " static const int minValue = " +
+ enum_def.ToString(*enum_def.MinValue()) + ";\n";
+ code += " static const int maxValue = " +
+ enum_def.ToString(*enum_def.MaxValue()) + ";\n";
+ }
+
+ code +=
+ " static bool containsValue(int value) =>"
+ " values.containsKey(value);\n\n";
+
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+
+ if (!ev.doc_comment.empty()) {
+ if (it != enum_def.Vals().begin()) { code += '\n'; }
+ GenDocComment(ev.doc_comment, &code, "", " ");
+ }
+ code += " static const " + name + " " + ev.name + " = ";
+ code += "const " + name + "._(" + enum_def.ToString(ev) + ");\n";
+ }
+
+ code += " static const Map<int," + name + "> values = {";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ code += enum_def.ToString(ev) + ": " + ev.name + ",";
+ }
+ code += "};\n\n";
+
+ code += " static const " + _kFb + ".Reader<" + name +
+ "> reader = const _" + name + "Reader();\n\n";
+ code += " @override\n";
+ code += " String toString() {\n";
+ code += " return '" + name + "{value: $value}';\n";
+ code += " }\n";
+ code += "}\n\n";
+
+ GenEnumReader(enum_def, name, &code);
+ (*namespace_code)[ns] += code;
+ }
+
+ void GenEnumReader(EnumDef &enum_def, const std::string &name,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+
+ code += "class _" + name + "Reader extends " + _kFb + ".Reader<" + name +
+ "> {\n";
+ code += " const _" + name + "Reader();\n\n";
+ code += " @override\n";
+ code += " int get size => 1;\n\n";
+ code += " @override\n";
+ code +=
+ " " + name + " read(" + _kFb + ".BufferContext bc, int offset) =>\n";
+ code += " new " + name + ".fromValue(const " + _kFb + "." +
+ GenType(enum_def.underlying_type) + "Reader().read(bc, offset));\n";
+ code += "}\n\n";
+ }
+
+ static std::string GenType(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_BOOL: return "Bool";
+ case BASE_TYPE_CHAR: return "Int8";
+ case BASE_TYPE_UTYPE:
+ case BASE_TYPE_UCHAR: return "Uint8";
+ case BASE_TYPE_SHORT: return "Int16";
+ case BASE_TYPE_USHORT: return "Uint16";
+ case BASE_TYPE_INT: return "Int32";
+ case BASE_TYPE_UINT: return "Uint32";
+ case BASE_TYPE_LONG: return "Int64";
+ case BASE_TYPE_ULONG: return "Uint64";
+ case BASE_TYPE_FLOAT: return "Float32";
+ case BASE_TYPE_DOUBLE: return "Float64";
+ case BASE_TYPE_STRING: return "String";
+ case BASE_TYPE_VECTOR: return GenType(type.VectorType());
+ case BASE_TYPE_STRUCT: return type.struct_def->name;
+ case BASE_TYPE_UNION: return type.enum_def->name + "TypeId";
+ default: return "Table";
+ }
+ }
+
+ std::string GenReaderTypeName(const Type &type, Namespace *current_namespace,
+ const FieldDef &def,
+ bool parent_is_vector = false) {
+ if (type.base_type == BASE_TYPE_BOOL) {
+ return "const " + _kFb + ".BoolReader()";
+ } else if (IsVector(type)) {
+ return "const " + _kFb + ".ListReader<" +
+ GenDartTypeName(type.VectorType(), current_namespace, def) + ">(" +
+ GenReaderTypeName(type.VectorType(), current_namespace, def,
+ true) +
+ ")";
+ } else if (IsString(type)) {
+ return "const " + _kFb + ".StringReader()";
+ }
+ if (IsScalar(type.base_type)) {
+ if (type.enum_def && parent_is_vector) {
+ return GenDartTypeName(type, current_namespace, def) + ".reader";
+ }
+ return "const " + _kFb + "." + GenType(type) + "Reader()";
+ } else {
+ return GenDartTypeName(type, current_namespace, def) + ".reader";
+ }
+ }
+
+ std::string GenDartTypeName(const Type &type, Namespace *current_namespace,
+ const FieldDef &def, bool addBuilder = false) {
+ if (type.enum_def) {
+ if (type.enum_def->is_union && type.base_type != BASE_TYPE_UNION) {
+ return type.enum_def->name + "TypeId";
+ } else if (type.enum_def->is_union) {
+ return "dynamic";
+ } else if (type.base_type != BASE_TYPE_VECTOR) {
+ return type.enum_def->name;
+ }
+ }
+
+ switch (type.base_type) {
+ case BASE_TYPE_BOOL: return "bool";
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG:
+ case BASE_TYPE_INT:
+ case BASE_TYPE_UINT:
+ case BASE_TYPE_SHORT:
+ case BASE_TYPE_USHORT:
+ case BASE_TYPE_CHAR:
+ case BASE_TYPE_UCHAR: return "int";
+ case BASE_TYPE_FLOAT:
+ case BASE_TYPE_DOUBLE: return "double";
+ case BASE_TYPE_STRING: return "String";
+ case BASE_TYPE_STRUCT:
+ return MaybeWrapNamespace(
+ type.struct_def->name + (addBuilder ? "ObjectBuilder" : ""),
+ current_namespace, def);
+ case BASE_TYPE_VECTOR:
+ return "List<" +
+ GenDartTypeName(type.VectorType(), current_namespace, def,
+ addBuilder) +
+ ">";
+ default: assert(0); return "dynamic";
+ }
+ }
+
+ static const std::string MaybeWrapNamespace(const std::string &type_name,
+ Namespace *current_ns,
+ const FieldDef &field) {
+ auto curr_ns_str = BuildNamespaceName(*current_ns);
+ std::string field_ns_str = "";
+ if (field.value.type.struct_def) {
+ field_ns_str +=
+ BuildNamespaceName(*field.value.type.struct_def->defined_namespace);
+ } else if (field.value.type.enum_def) {
+ field_ns_str +=
+ BuildNamespaceName(*field.value.type.enum_def->defined_namespace);
+ }
+
+ if (field_ns_str != "" && field_ns_str != curr_ns_str) {
+ return ImportAliasName(field_ns_str) + "." + type_name;
+ } else {
+ return type_name;
+ }
+ }
+
+ // Generate an accessor struct with constructor for a flatbuffers struct.
+ void GenStruct(const StructDef &struct_def,
+ namespace_code_map *namespace_code) {
+ if (struct_def.generated) return;
+
+ auto object_namespace = BuildNamespaceName(*struct_def.defined_namespace);
+ std::string code;
+
+ const auto &object_name = struct_def.name;
+
+ // Emit constructor
+
+ GenDocComment(struct_def.doc_comment, &code, "");
+
+ auto reader_name = "_" + object_name + "Reader";
+ auto builder_name = object_name + "Builder";
+ auto object_builder_name = object_name + "ObjectBuilder";
+
+ std::string reader_code, builder_code;
+
+ code += "class " + object_name + " {\n";
+
+ code += " " + object_name + "._(this._bc, this._bcOffset);\n";
+ if (!struct_def.fixed) {
+ code += " factory " + object_name + "(List<int> bytes) {\n";
+ code += " " + _kFb + ".BufferContext rootRef = new " + _kFb +
+ ".BufferContext.fromBytes(bytes);\n";
+ code += " return reader.read(rootRef, 0);\n";
+ code += " }\n";
+ }
+
+ code += "\n";
+ code += " static const " + _kFb + ".Reader<" + object_name +
+ "> reader = const " + reader_name + "();\n\n";
+
+ code += " final " + _kFb + ".BufferContext _bc;\n";
+ code += " final int _bcOffset;\n\n";
+
+ std::vector<std::pair<int, FieldDef *>> non_deprecated_fields;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto offset = static_cast<int>(it - struct_def.fields.vec.begin());
+ non_deprecated_fields.push_back(std::make_pair(offset, &field));
+ }
+
+ GenImplementationGetters(struct_def, non_deprecated_fields, &code);
+
+ code += "}\n\n";
+
+ GenReader(struct_def, &reader_name, &reader_code);
+ GenBuilder(struct_def, non_deprecated_fields, &builder_name, &builder_code);
+ GenObjectBuilder(struct_def, non_deprecated_fields, &object_builder_name,
+ &builder_code);
+
+ code += reader_code;
+ code += builder_code;
+
+ (*namespace_code)[object_namespace] += code;
+ }
+
+ std::string NamespaceAliasFromUnionType(Namespace *root_namespace,
+ const Type &type) {
+ const std::vector<std::string> qualified_name_parts =
+ type.struct_def->defined_namespace->components;
+ if (std::equal(root_namespace->components.begin(),
+ root_namespace->components.end(),
+ qualified_name_parts.begin())) {
+ return type.struct_def->name;
+ }
+
+ std::string ns;
+
+ for (auto it = qualified_name_parts.begin();
+ it != qualified_name_parts.end(); ++it) {
+ auto &part = *it;
+
+ for (size_t i = 0; i < part.length(); i++) {
+ if (i && !isdigit(part[i]) && part[i] == CharToUpper(part[i])) {
+ ns += "_";
+ ns += CharToLower(part[i]);
+ } else {
+ ns += CharToLower(part[i]);
+ }
+ }
+ if (it != qualified_name_parts.end() - 1) { ns += "_"; }
+ }
+
+ return ns + "." + type.struct_def->name;
+ }
+
+ void GenImplementationGetters(
+ const StructDef &struct_def,
+ std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+
+ std::string field_name = MakeCamel(field.name, false);
+ std::string type_name = GenDartTypeName(
+ field.value.type, struct_def.defined_namespace, field, false);
+
+ GenDocComment(field.doc_comment, &code, "", " ");
+
+ code += " " + type_name + " get " + field_name;
+ if (field.value.type.base_type == BASE_TYPE_UNION) {
+ code += " {\n";
+ code += " switch (" + field_name + "Type?.value) {\n";
+ auto &enum_def = *field.value.type.enum_def;
+ for (auto en_it = enum_def.Vals().begin() + 1;
+ en_it != enum_def.Vals().end(); ++en_it) {
+ auto &ev = **en_it;
+
+ auto enum_name = NamespaceAliasFromUnionType(
+ enum_def.defined_namespace, ev.union_type);
+ code += " case " + enum_def.ToString(ev) + ": return " +
+ enum_name + ".reader.vTableGet(_bc, _bcOffset, " +
+ NumToString(field.value.offset) + ", null);\n";
+ }
+ code += " default: return null;\n";
+ code += " }\n";
+ code += " }\n";
+ } else {
+ code += " => ";
+ if (field.value.type.enum_def &&
+ field.value.type.base_type != BASE_TYPE_VECTOR) {
+ code += "new " +
+ GenDartTypeName(field.value.type,
+ struct_def.defined_namespace, field) +
+ ".fromValue(";
+ }
+
+ code += GenReaderTypeName(field.value.type,
+ struct_def.defined_namespace, field);
+ if (struct_def.fixed) {
+ code +=
+ ".read(_bc, _bcOffset + " + NumToString(field.value.offset) + ")";
+ } else {
+ code += ".vTableGet(_bc, _bcOffset, " +
+ NumToString(field.value.offset) + ", ";
+ if (!field.value.constant.empty() && field.value.constant != "0") {
+ if (IsBool(field.value.type.base_type)) {
+ code += "true";
+ } else if (field.value.constant == "nan" ||
+ field.value.constant == "+nan" ||
+ field.value.constant == "-nan") {
+ code += "double.nan";
+ } else if (field.value.constant == "inf" ||
+ field.value.constant == "+inf") {
+ code += "double.infinity";
+ } else if (field.value.constant == "-inf") {
+ code += "double.negativeInfinity";
+ } else {
+ code += field.value.constant;
+ }
+ } else {
+ if (IsBool(field.value.type.base_type)) {
+ code += "false";
+ } else if (IsScalar(field.value.type.base_type)) {
+ code += "0";
+ } else {
+ code += "null";
+ }
+ }
+ code += ")";
+ }
+ if (field.value.type.enum_def &&
+ field.value.type.base_type != BASE_TYPE_VECTOR) {
+ code += ")";
+ }
+ code += ";\n";
+ }
+ }
+
+ code += "\n";
+
+ code += " @override\n";
+ code += " String toString() {\n";
+ code += " return '" + struct_def.name + "{";
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+ code +=
+ MakeCamel(field.name, false) + ": $" + MakeCamel(field.name, false);
+ if (it != non_deprecated_fields.end() - 1) { code += ", "; }
+ }
+ code += "}';\n";
+ code += " }\n";
+ }
+
+ void GenReader(const StructDef &struct_def, std::string *reader_name_ptr,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto &reader_name = *reader_name_ptr;
+ auto &impl_name = struct_def.name;
+
+ code += "class " + reader_name + " extends " + _kFb;
+ if (struct_def.fixed) {
+ code += ".StructReader<";
+ } else {
+ code += ".TableReader<";
+ }
+ code += impl_name + "> {\n";
+ code += " const " + reader_name + "();\n\n";
+
+ if (struct_def.fixed) {
+ code += " @override\n";
+ code += " int get size => " + NumToString(struct_def.bytesize) + ";\n\n";
+ }
+ code += " @override\n";
+ code += " " + impl_name +
+ " createObject(fb.BufferContext bc, int offset) => \n new " +
+ impl_name + "._(bc, offset);\n";
+ code += "}\n\n";
+ }
+
+ void GenBuilder(const StructDef &struct_def,
+ std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
+ std::string *builder_name_ptr, std::string *code_ptr) {
+ if (non_deprecated_fields.size() == 0) { return; }
+ auto &code = *code_ptr;
+ auto &builder_name = *builder_name_ptr;
+
+ code += "class " + builder_name + " {\n";
+ code += " " + builder_name + "(this.fbBuilder) {\n";
+ code += " assert(fbBuilder != null);\n";
+ code += " }\n\n";
+ code += " final " + _kFb + ".Builder fbBuilder;\n\n";
+
+ if (struct_def.fixed) {
+ StructBuilderBody(struct_def, non_deprecated_fields, code_ptr);
+ } else {
+ TableBuilderBody(struct_def, non_deprecated_fields, code_ptr);
+ }
+
+ code += "}\n\n";
+ }
+
+ void StructBuilderBody(
+ const StructDef &struct_def,
+ std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+
+ code += " int finish(";
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+
+ if (IsStruct(field.value.type)) {
+ code += "fb.StructBuilder";
+ } else {
+ code += GenDartTypeName(field.value.type, struct_def.defined_namespace,
+ field);
+ }
+ code += " " + field.name;
+ if (it != non_deprecated_fields.end() - 1) { code += ", "; }
+ }
+ code += ") {\n";
+
+ for (auto it = non_deprecated_fields.rbegin();
+ it != non_deprecated_fields.rend(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+
+ if (field.padding) {
+ code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n";
+ }
+
+ if (IsStruct(field.value.type)) {
+ code += " " + field.name + "();\n";
+ } else {
+ code += " fbBuilder.put" + GenType(field.value.type) + "(";
+ code += field.name;
+ if (field.value.type.enum_def) { code += "?.value"; }
+ code += ");\n";
+ }
+ }
+ code += " return fbBuilder.offset;\n";
+ code += " }\n\n";
+ }
+
+ void TableBuilderBody(
+ const StructDef &struct_def,
+ std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+
+ code += " void begin() {\n";
+ code += " fbBuilder.startTable();\n";
+ code += " }\n\n";
+
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+ auto offset = pair.first;
+
+ if (IsScalar(field.value.type.base_type)) {
+ code += " int add" + MakeCamel(field.name) + "(";
+ code += GenDartTypeName(field.value.type, struct_def.defined_namespace,
+ field);
+ code += " " + MakeCamel(field.name, false) + ") {\n";
+ code += " fbBuilder.add" + GenType(field.value.type) + "(" +
+ NumToString(offset) + ", ";
+ code += MakeCamel(field.name, false);
+ if (field.value.type.enum_def) { code += "?.value"; }
+ code += ");\n";
+ } else if (IsStruct(field.value.type)) {
+ code += " int add" + MakeCamel(field.name) + "(int offset) {\n";
+ code +=
+ " fbBuilder.addStruct(" + NumToString(offset) + ", offset);\n";
+ } else {
+ code += " int add" + MakeCamel(field.name) + "Offset(int offset) {\n";
+ code +=
+ " fbBuilder.addOffset(" + NumToString(offset) + ", offset);\n";
+ }
+ code += " return fbBuilder.offset;\n";
+ code += " }\n";
+ }
+
+ code += "\n";
+ code += " int finish() {\n";
+ code += " return fbBuilder.endTable();\n";
+ code += " }\n";
+ }
+
+ void GenObjectBuilder(
+ const StructDef &struct_def,
+ std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
+ std::string *builder_name_ptr, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto &builder_name = *builder_name_ptr;
+
+ code += "class " + builder_name + " extends " + _kFb + ".ObjectBuilder {\n";
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+
+ code += " final " +
+ GenDartTypeName(field.value.type, struct_def.defined_namespace,
+ field, true) +
+ " _" + MakeCamel(field.name, false) + ";\n";
+ }
+ code += "\n";
+ code += " " + builder_name + "(";
+
+ if (non_deprecated_fields.size() != 0) {
+ code += "{\n";
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+
+ code += " " +
+ GenDartTypeName(field.value.type, struct_def.defined_namespace,
+ field, true) +
+ " " + MakeCamel(field.name, false) + ",\n";
+ }
+ code += " })\n";
+ code += " : ";
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+
+ code += "_" + MakeCamel(field.name, false) + " = " +
+ MakeCamel(field.name, false);
+ if (it == non_deprecated_fields.end() - 1) {
+ code += ";\n\n";
+ } else {
+ code += ",\n ";
+ }
+ }
+ } else {
+ code += ");\n\n";
+ }
+
+ code += " /// Finish building, and store into the [fbBuilder].\n";
+ code += " @override\n";
+ code += " int finish(\n";
+ code += " " + _kFb + ".Builder fbBuilder) {\n";
+ code += " assert(fbBuilder != null);\n";
+
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+
+ if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type))
+ continue;
+
+ code += " final int " + MakeCamel(field.name, false) + "Offset";
+ if (IsVector(field.value.type)) {
+ code +=
+ " = _" + MakeCamel(field.name, false) + "?.isNotEmpty == true\n";
+ code += " ? fbBuilder.writeList";
+ switch (field.value.type.VectorType().base_type) {
+ case BASE_TYPE_STRING:
+ code += "(_" + MakeCamel(field.name, false) +
+ ".map((b) => fbBuilder.writeString(b)).toList())";
+ break;
+ case BASE_TYPE_STRUCT:
+ if (field.value.type.struct_def->fixed) {
+ code += "OfStructs(_" + MakeCamel(field.name, false) + ")";
+ } else {
+ code += "(_" + MakeCamel(field.name, false) +
+ ".map((b) => b.getOrCreateOffset(fbBuilder)).toList())";
+ }
+ break;
+ default:
+ code += GenType(field.value.type.VectorType()) + "(_" +
+ MakeCamel(field.name, false);
+ if (field.value.type.enum_def) { code += ".map((f) => f.value)"; }
+ code += ")";
+ }
+ code += "\n : null;\n";
+ } else if (IsString(field.value.type)) {
+ code += " = fbBuilder.writeString(_" + MakeCamel(field.name, false) +
+ ");\n";
+ } else {
+ code += " = _" + MakeCamel(field.name, false) +
+ "?.getOrCreateOffset(fbBuilder);\n";
+ }
+ }
+
+ code += "\n";
+ if (struct_def.fixed) {
+ StructObjectBuilderBody(non_deprecated_fields, code_ptr);
+ } else {
+ TableObjectBuilderBody(non_deprecated_fields, code_ptr);
+ }
+ code += " }\n\n";
+
+ code += " /// Convenience method to serialize to byte list.\n";
+ code += " @override\n";
+ code += " Uint8List toBytes([String fileIdentifier]) {\n";
+ code += " " + _kFb + ".Builder fbBuilder = new ";
+ code += _kFb + ".Builder();\n";
+ code += " int offset = finish(fbBuilder);\n";
+ code += " return fbBuilder.finish(offset, fileIdentifier);\n";
+ code += " }\n";
+ code += "}\n";
+ }
+
+ void StructObjectBuilderBody(
+ std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
+ std::string *code_ptr, bool prependUnderscore = true) {
+ auto &code = *code_ptr;
+
+ for (auto it = non_deprecated_fields.rbegin();
+ it != non_deprecated_fields.rend(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+
+ if (field.padding) {
+ code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n";
+ }
+
+ if (IsStruct(field.value.type)) {
+ code += " ";
+ if (prependUnderscore) { code += "_"; }
+ code += field.name + ".finish(fbBuilder);\n";
+ } else {
+ code += " fbBuilder.put" + GenType(field.value.type) + "(";
+ if (prependUnderscore) { code += "_"; }
+ code += field.name;
+ if (field.value.type.enum_def) { code += "?.value"; }
+ code += ");\n";
+ }
+ }
+
+ code += " return fbBuilder.offset;\n";
+ }
+
+ void TableObjectBuilderBody(
+ std::vector<std::pair<int, FieldDef *>> non_deprecated_fields,
+ std::string *code_ptr, bool prependUnderscore = true) {
+ std::string &code = *code_ptr;
+ code += " fbBuilder.startTable();\n";
+
+ for (auto it = non_deprecated_fields.begin();
+ it != non_deprecated_fields.end(); ++it) {
+ auto pair = *it;
+ auto &field = *pair.second;
+ auto offset = pair.first;
+
+ if (IsScalar(field.value.type.base_type)) {
+ code += " fbBuilder.add" + GenType(field.value.type) + "(" +
+ NumToString(offset) + ", ";
+ if (prependUnderscore) { code += "_"; }
+ code += MakeCamel(field.name, false);
+ if (field.value.type.enum_def) { code += "?.value"; }
+ code += ");\n";
+ } else if (IsStruct(field.value.type)) {
+ code += " if (";
+ if (prependUnderscore) { code += "_"; }
+ code += MakeCamel(field.name, false) + " != null) {\n";
+ code += " fbBuilder.addStruct(" + NumToString(offset) + ", ";
+ code += "_" + MakeCamel(field.name, false) + ".finish(fbBuilder));\n";
+ code += " }\n";
+ } else {
+ code +=
+ " if (" + MakeCamel(field.name, false) + "Offset != null) {\n";
+ code += " fbBuilder.addOffset(" + NumToString(offset) + ", " +
+ MakeCamel(field.name, false) + "Offset);\n";
+ code += " }\n";
+ }
+ }
+ code += " return fbBuilder.endTable();\n";
+ }
+};
+} // namespace dart
+
+bool GenerateDart(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ dart::DartGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+
+std::string DartMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ assert(parser.opts.lang <= IDLOptions::kMAX);
+
+ auto filebase =
+ flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
+ dart::DartGenerator generator(parser, path, file_name);
+ auto make_rule =
+ generator.GeneratedFileName(path, file_name, parser.opts) + ": ";
+
+ auto included_files = parser.GetIncludedFilesRecursive(file_name);
+ for (auto it = included_files.begin(); it != included_files.end(); ++it) {
+ make_rule += " " + *it;
+ }
+ return make_rule;
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp b/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp
new file mode 100644
index 0000000000..35c1a7d4f5
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_fbs.cpp
@@ -0,0 +1,154 @@
+/*
+ * 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 "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+static std::string GenType(const Type &type, bool underlying = false) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRUCT:
+ return type.struct_def->defined_namespace->GetFullyQualifiedName(
+ type.struct_def->name);
+ case BASE_TYPE_VECTOR: return "[" + GenType(type.VectorType()) + "]";
+ default:
+ if (type.enum_def && !underlying) {
+ return type.enum_def->defined_namespace->GetFullyQualifiedName(
+ type.enum_def->name);
+ } else {
+ return kTypeNames[type.base_type];
+ }
+ }
+}
+
+static void GenNameSpace(const Namespace &name_space, std::string *_schema,
+ const Namespace **last_namespace) {
+ if (*last_namespace == &name_space) return;
+ *last_namespace = &name_space;
+ auto &schema = *_schema;
+ schema += "namespace ";
+ for (auto it = name_space.components.begin();
+ it != name_space.components.end(); ++it) {
+ if (it != name_space.components.begin()) schema += ".";
+ schema += *it;
+ }
+ schema += ";\n\n";
+}
+
+// Generate a flatbuffer schema from the Parser's internal representation.
+std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
+ // Proto namespaces may clash with table names, escape the ones that were
+ // generated from a table:
+ for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end();
+ ++it) {
+ auto &ns = **it;
+ for (size_t i = 0; i < ns.from_table; i++) {
+ ns.components[ns.components.size() - 1 - i] += "_";
+ }
+
+ if (parser.opts.proto_mode && !parser.opts.proto_namespace_suffix.empty()) {
+ // Since we know that all these namespaces come from a .proto, and all are
+ // being converted, we can simply apply this suffix to all of them.
+ ns.components.insert(ns.components.end() - ns.from_table,
+ parser.opts.proto_namespace_suffix);
+ }
+ }
+
+ std::string schema;
+ schema += "// Generated from " + file_name + ".proto\n\n";
+ if (parser.opts.include_dependence_headers) {
+ // clang-format off
+ int num_includes = 0;
+ for (auto it = parser.included_files_.begin();
+ it != parser.included_files_.end(); ++it) {
+ if (it->second.empty())
+ continue;
+ std::string basename;
+ if(parser.opts.keep_include_path) {
+ basename = flatbuffers::StripExtension(it->second);
+ } else {
+ basename = flatbuffers::StripPath(
+ flatbuffers::StripExtension(it->second));
+ }
+ schema += "include \"" + basename + ".fbs\";\n";
+ num_includes++;
+ }
+ if (num_includes) schema += "\n";
+ // clang-format on
+ }
+ // Generate code for all the enum declarations.
+ const Namespace *last_namespace = nullptr;
+ for (auto enum_def_it = parser.enums_.vec.begin();
+ enum_def_it != parser.enums_.vec.end(); ++enum_def_it) {
+ EnumDef &enum_def = **enum_def_it;
+ if (parser.opts.include_dependence_headers && enum_def.generated) {
+ continue;
+ }
+ GenNameSpace(*enum_def.defined_namespace, &schema, &last_namespace);
+ GenComment(enum_def.doc_comment, &schema, nullptr);
+ if (enum_def.is_union)
+ schema += "union " + enum_def.name;
+ else
+ schema += "enum " + enum_def.name + " : ";
+ schema += GenType(enum_def.underlying_type, true) + " {\n";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ GenComment(ev.doc_comment, &schema, nullptr, " ");
+ if (enum_def.is_union)
+ schema += " " + GenType(ev.union_type) + ",\n";
+ else
+ schema += " " + ev.name + " = " + enum_def.ToString(ev) + ",\n";
+ }
+ schema += "}\n\n";
+ }
+ // Generate code for all structs/tables.
+ for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
+ ++it) {
+ StructDef &struct_def = **it;
+ if (parser.opts.include_dependence_headers && struct_def.generated) {
+ continue;
+ }
+ GenNameSpace(*struct_def.defined_namespace, &schema, &last_namespace);
+ GenComment(struct_def.doc_comment, &schema, nullptr);
+ schema += "table " + struct_def.name + " {\n";
+ for (auto field_it = struct_def.fields.vec.begin();
+ field_it != struct_def.fields.vec.end(); ++field_it) {
+ auto &field = **field_it;
+ if (field.value.type.base_type != BASE_TYPE_UTYPE) {
+ GenComment(field.doc_comment, &schema, nullptr, " ");
+ schema += " " + field.name + ":" + GenType(field.value.type);
+ if (field.value.constant != "0") schema += " = " + field.value.constant;
+ if (field.IsRequired()) schema += " (required)";
+ schema += ";\n";
+ }
+ }
+ schema += "}\n\n";
+ }
+ return schema;
+}
+
+bool GenerateFBS(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ return SaveFile((path + file_name + ".fbs").c_str(),
+ GenerateFBS(parser, file_name), false);
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_go.cpp b/contrib/libs/flatbuffers/src/idl_gen_go.cpp
new file mode 100644
index 0000000000..867f402322
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_go.cpp
@@ -0,0 +1,1374 @@
+/*
+ * 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 <sstream>
+#include <string>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+#ifdef _WIN32
+# include <direct.h>
+# define PATH_SEPARATOR "\\"
+# define mkdir(n, m) _mkdir(n)
+#else
+# include <sys/stat.h>
+# define PATH_SEPARATOR "/"
+#endif
+
+namespace flatbuffers {
+
+namespace go {
+
+// see https://golang.org/ref/spec#Keywords
+static const char *const g_golang_keywords[] = {
+ "break", "default", "func", "interface", "select", "case", "defer",
+ "go", "map", "struct", "chan", "else", "goto", "package",
+ "switch", "const", "fallthrough", "if", "range", "type", "continue",
+ "for", "import", "return", "var",
+};
+
+static std::string GoIdentity(const std::string &name) {
+ for (size_t i = 0;
+ i < sizeof(g_golang_keywords) / sizeof(g_golang_keywords[0]); i++) {
+ if (name == g_golang_keywords[i]) { return MakeCamel(name + "_", false); }
+ }
+
+ return MakeCamel(name, false);
+}
+
+class GoGenerator : public BaseGenerator {
+ public:
+ GoGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name, const std::string &go_namespace)
+ : BaseGenerator(parser, path, file_name, "" /* not used*/,
+ "" /* not used */, "go"),
+ cur_name_space_(nullptr) {
+ std::istringstream iss(go_namespace);
+ std::string component;
+ while (std::getline(iss, component, '.')) {
+ go_namespace_.components.push_back(component);
+ }
+ }
+
+ bool generate() {
+ std::string one_file_code;
+ bool needs_imports = false;
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ tracked_imported_namespaces_.clear();
+ needs_imports = false;
+ 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);
+ needs_imports = true;
+ }
+ if (parser_.opts.one_file) {
+ one_file_code += enumcode;
+ } else {
+ if (!SaveType(**it, enumcode, needs_imports, true)) return false;
+ }
+ }
+
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ tracked_imported_namespaces_.clear();
+ std::string declcode;
+ GenStruct(**it, &declcode);
+ if (parser_.opts.one_file) {
+ one_file_code += declcode;
+ } else {
+ if (!SaveType(**it, 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_;
+
+ struct NamespacePtrLess {
+ bool operator()(const Namespace *a, const Namespace *b) const {
+ return *a < *b;
+ }
+ };
+ std::set<const Namespace *, NamespacePtrLess> tracked_imported_namespaces_;
+
+ // Most field accessors need to retrieve and test the field offset first,
+ // this is the prefix code for that.
+ std::string OffsetPrefix(const FieldDef &field) {
+ return "{\n\to := flatbuffers.UOffsetT(rcv._tab.Offset(" +
+ NumToString(field.value.offset) + "))\n\tif o != 0 {\n";
+ }
+
+ // Begin a class declaration.
+ void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "type " + struct_def.name + " struct {\n\t";
+
+ // _ 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";
+ }
+
+ // Construct the name of the type for this enum.
+ std::string GetEnumTypeName(const EnumDef &enum_def) {
+ return WrapInNameSpaceAndTrack(enum_def.defined_namespace,
+ GoIdentity(enum_def.name));
+ }
+
+ // Create a type for the enum values.
+ void GenEnumType(const EnumDef &enum_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "type " + GetEnumTypeName(enum_def) + " ";
+ code += GenTypeBasic(enum_def.underlying_type) + "\n\n";
+ }
+
+ // Begin enum code with a class declaration.
+ void BeginEnum(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "const (\n";
+ }
+
+ // A single enum member.
+ void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
+ size_t max_name_length, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "\t";
+ code += enum_def.name;
+ code += ev.name;
+ code += " ";
+ code += std::string(max_name_length - ev.name.length(), ' ');
+ code += GetEnumTypeName(enum_def);
+ code += " = ";
+ code += enum_def.ToString(ev) + "\n";
+ }
+
+ // End enum code.
+ void EndEnum(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += ")\n\n";
+ }
+
+ // Begin enum name map.
+ void BeginEnumNames(const EnumDef &enum_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "var EnumNames";
+ code += enum_def.name;
+ code += " = map[" + GetEnumTypeName(enum_def) + "]string{\n";
+ }
+
+ // A single enum name member.
+ void EnumNameMember(const EnumDef &enum_def, const EnumVal &ev,
+ size_t max_name_length, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "\t";
+ code += enum_def.name;
+ code += ev.name;
+ code += ": ";
+ code += std::string(max_name_length - ev.name.length(), ' ');
+ code += "\"";
+ code += ev.name;
+ code += "\",\n";
+ }
+
+ // End enum name map.
+ void EndEnumNames(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "}\n\n";
+ }
+
+ // Generate String() method on enum type.
+ void EnumStringer(const EnumDef &enum_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "func (v " + enum_def.name + ") String() string {\n";
+ code += "\tif s, ok := EnumNames" + enum_def.name + "[v]; ok {\n";
+ code += "\t\treturn s\n";
+ code += "\t}\n";
+ code += "\treturn \"" + enum_def.name;
+ code += "(\" + strconv.FormatInt(int64(v), 10) + \")\"\n";
+ code += "}\n\n";
+ }
+
+ // Begin enum value map.
+ void BeginEnumValues(const EnumDef &enum_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "var EnumValues";
+ code += enum_def.name;
+ code += " = map[string]" + GetEnumTypeName(enum_def) + "{\n";
+ }
+
+ // A single enum value member.
+ void EnumValueMember(const EnumDef &enum_def, const EnumVal &ev,
+ size_t max_name_length, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "\t\"";
+ code += ev.name;
+ code += "\": ";
+ code += std::string(max_name_length - ev.name.length(), ' ');
+ code += enum_def.name;
+ code += ev.name;
+ code += ",\n";
+ }
+
+ // End enum value map.
+ void EndEnumValues(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "}\n\n";
+ }
+
+ // Initialize a new struct or table from existing data.
+ void NewRootTypeFromBuffer(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ std::string size_prefix[] = { "", "SizePrefixed" };
+
+ for (int i = 0; i < 2; i++) {
+ code += "func Get" + size_prefix[i] + "RootAs";
+ code += struct_def.name;
+ code += "(buf []byte, offset flatbuffers.UOffsetT) ";
+ code += "*" + struct_def.name + "";
+ code += " {\n";
+ if (i == 0) {
+ code += "\tn := flatbuffers.GetUOffsetT(buf[offset:])\n";
+ } else {
+ code +=
+ "\tn := "
+ "flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])\n";
+ }
+ code += "\tx := &" + struct_def.name + "{}\n";
+ if (i == 0) {
+ code += "\tx.Init(buf, n+offset)\n";
+ } else {
+ code += "\tx.Init(buf, n+offset+flatbuffers.SizeUint32)\n";
+ }
+ code += "\treturn x\n";
+ code += "}\n\n";
+ }
+ }
+
+ // Initialize an existing object with other data, to avoid an allocation.
+ void InitializeExisting(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += " Init(buf []byte, i flatbuffers.UOffsetT) ";
+ code += "{\n";
+ code += "\trcv._tab.Bytes = buf\n";
+ code += "\trcv._tab.Pos = i\n";
+ code += "}\n\n";
+ }
+
+ // Implement the table accessor
+ void GenTableAccessor(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += " Table() flatbuffers.Table ";
+ code += "{\n";
+
+ if (struct_def.fixed) {
+ code += "\treturn rcv._tab.Table\n";
+ } else {
+ code += "\treturn rcv._tab\n";
+ }
+ code += "}\n\n";
+ }
+
+ // Get the length of a vector.
+ void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += " " + MakeCamel(field.name) + "Length(";
+ code += ") int " + OffsetPrefix(field);
+ code += "\t\treturn rcv._tab.VectorLen(o)\n\t}\n";
+ code += "\treturn 0\n}\n\n";
+ }
+
+ // Get a [ubyte] vector as a byte slice.
+ void GetUByteSlice(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += " " + MakeCamel(field.name) + "Bytes(";
+ code += ") []byte " + OffsetPrefix(field);
+ code += "\t\treturn rcv._tab.ByteVector(o + rcv._tab.Pos)\n\t}\n";
+ code += "\treturn nil\n}\n\n";
+ }
+
+ // Get the value of a struct's scalar.
+ void GetScalarFieldOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ std::string getter = GenGetter(field.value.type);
+ GenReceiver(struct_def, code_ptr);
+ code += " " + MakeCamel(field.name);
+ code += "() " + TypeName(field) + " {\n";
+ code += "\treturn " +
+ CastToEnum(field.value.type,
+ getter + "(rcv._tab.Pos + flatbuffers.UOffsetT(" +
+ NumToString(field.value.offset) + "))");
+ code += "\n}\n";
+ }
+
+ // Get the value of a table's scalar.
+ void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ std::string getter = GenGetter(field.value.type);
+ GenReceiver(struct_def, code_ptr);
+ code += " " + MakeCamel(field.name);
+ code += "() " + TypeName(field) + " ";
+ code += OffsetPrefix(field) + "\t\treturn ";
+ code += CastToEnum(field.value.type, getter + "(o + rcv._tab.Pos)");
+ code += "\n\t}\n";
+ code += "\treturn " + GenConstant(field) + "\n";
+ code += "}\n\n";
+ }
+
+ // Get a struct by initializing an existing struct.
+ // Specific to Struct.
+ void GetStructFieldOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += " " + MakeCamel(field.name);
+ code += "(obj *" + TypeName(field);
+ code += ") *" + TypeName(field);
+ code += " {\n";
+ code += "\tif obj == nil {\n";
+ code += "\t\tobj = new(" + TypeName(field) + ")\n";
+ code += "\t}\n";
+ code += "\tobj.Init(rcv._tab.Bytes, rcv._tab.Pos+";
+ code += NumToString(field.value.offset) + ")";
+ code += "\n\treturn obj\n";
+ code += "}\n";
+ }
+
+ // Get a struct by initializing an existing struct.
+ // Specific to Table.
+ void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += " " + MakeCamel(field.name);
+ code += "(obj *";
+ code += TypeName(field);
+ code += ") *" + TypeName(field) + " " + OffsetPrefix(field);
+ if (field.value.type.struct_def->fixed) {
+ code += "\t\tx := o + rcv._tab.Pos\n";
+ } else {
+ code += "\t\tx := rcv._tab.Indirect(o + rcv._tab.Pos)\n";
+ }
+ code += "\t\tif obj == nil {\n";
+ code += "\t\t\tobj = new(" + TypeName(field) + ")\n";
+ code += "\t\t}\n";
+ code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
+ code += "\t\treturn obj\n\t}\n\treturn nil\n";
+ code += "}\n\n";
+ }
+
+ // Get the value of a string.
+ void GetStringField(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += " " + MakeCamel(field.name);
+ code += "() " + TypeName(field) + " ";
+ code += OffsetPrefix(field) + "\t\treturn " + GenGetter(field.value.type);
+ code += "(o + rcv._tab.Pos)\n\t}\n\treturn nil\n";
+ code += "}\n\n";
+ }
+
+ // Get the value of a union from an object.
+ void GetUnionField(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += " " + MakeCamel(field.name) + "(";
+ code += "obj " + GenTypePointer(field.value.type) + ") bool ";
+ code += OffsetPrefix(field);
+ code += "\t\t" + GenGetter(field.value.type);
+ code += "(obj, o)\n\t\treturn true\n\t}\n";
+ code += "\treturn false\n";
+ code += "}\n\n";
+ }
+
+ // Get the value of a vector's struct member.
+ void GetMemberOfVectorOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ GenReceiver(struct_def, code_ptr);
+ code += " " + MakeCamel(field.name);
+ code += "(obj *" + TypeName(field);
+ code += ", j int) bool " + OffsetPrefix(field);
+ code += "\t\tx := rcv._tab.Vector(o)\n";
+ code += "\t\tx += flatbuffers.UOffsetT(j) * ";
+ code += NumToString(InlineSize(vectortype)) + "\n";
+ if (!(vectortype.struct_def->fixed)) {
+ code += "\t\tx = rcv._tab.Indirect(x)\n";
+ }
+ code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
+ code += "\t\treturn true\n\t}\n";
+ code += "\treturn false\n";
+ code += "}\n\n";
+ }
+
+ // Get the value of a vector's non-struct member.
+ void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ GenReceiver(struct_def, code_ptr);
+ code += " " + MakeCamel(field.name);
+ code += "(j int) " + TypeName(field) + " ";
+ code += OffsetPrefix(field);
+ code += "\t\ta := rcv._tab.Vector(o)\n";
+ code += "\t\treturn " +
+ CastToEnum(field.value.type,
+ GenGetter(field.value.type) +
+ "(a + flatbuffers.UOffsetT(j*" +
+ NumToString(InlineSize(vectortype)) + "))");
+ code += "\n\t}\n";
+ if (IsString(vectortype)) {
+ code += "\treturn nil\n";
+ } else if (vectortype.base_type == BASE_TYPE_BOOL) {
+ code += "\treturn false\n";
+ } else {
+ code += "\treturn 0\n";
+ }
+ code += "}\n\n";
+ }
+
+ // Begin the creator function signature.
+ void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ if (code.substr(code.length() - 2) != "\n\n") {
+ // a previous mutate has not put an extra new line
+ code += "\n";
+ }
+ code += "func Create" + struct_def.name;
+ code += "(builder *flatbuffers.Builder";
+ }
+
+ // Recursively generate arguments for a constructor, to deal with nested
+ // structs.
+ void StructBuilderArgs(const StructDef &struct_def, const char *nameprefix,
+ std::string *code_ptr) {
+ 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.
+ StructBuilderArgs(*field.value.type.struct_def,
+ (nameprefix + (field.name + "_")).c_str(), code_ptr);
+ } else {
+ std::string &code = *code_ptr;
+ code += std::string(", ") + nameprefix;
+ code += GoIdentity(field.name);
+ code += " " + TypeName(field);
+ }
+ }
+ }
+
+ // End the creator function signature.
+ void EndBuilderArgs(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += ") flatbuffers.UOffsetT {\n";
+ }
+
+ // Recursively generate struct construction statements and instert manual
+ // padding.
+ void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "\tbuilder.Prep(" + NumToString(struct_def.minalign) + ", ";
+ code += NumToString(struct_def.bytesize) + ")\n";
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ auto &field = **it;
+ if (field.padding)
+ code += "\tbuilder.Pad(" + NumToString(field.padding) + ")\n";
+ if (IsStruct(field.value.type)) {
+ StructBuilderBody(*field.value.type.struct_def,
+ (nameprefix + (field.name + "_")).c_str(), code_ptr);
+ } else {
+ code += "\tbuilder.Prepend" + GenMethod(field) + "(";
+ code += CastToBaseType(field.value.type,
+ nameprefix + GoIdentity(field.name)) +
+ ")\n";
+ }
+ }
+ }
+
+ void EndBuilderBody(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "\treturn builder.Offset()\n";
+ code += "}\n";
+ }
+
+ // Get the value of a table's starting offset.
+ void GetStartOfTable(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "func " + struct_def.name + "Start";
+ code += "(builder *flatbuffers.Builder) {\n";
+ code += "\tbuilder.StartObject(";
+ code += NumToString(struct_def.fields.vec.size());
+ code += ")\n}\n";
+ }
+
+ // Set the value of a table's field.
+ void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
+ const size_t offset, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "func " + struct_def.name + "Add" + MakeCamel(field.name);
+ code += "(builder *flatbuffers.Builder, ";
+ code += GoIdentity(field.name) + " ";
+ if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
+ code += "flatbuffers.UOffsetT";
+ } else {
+ code += TypeName(field);
+ }
+ code += ") {\n";
+ code += "\tbuilder.Prepend";
+ code += GenMethod(field) + "Slot(";
+ code += NumToString(offset) + ", ";
+ if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
+ code += "flatbuffers.UOffsetT";
+ code += "(";
+ code += GoIdentity(field.name) + ")";
+ } else {
+ code += CastToBaseType(field.value.type, GoIdentity(field.name));
+ }
+ code += ", " + GenConstant(field);
+ code += ")\n}\n";
+ }
+
+ // Set the value of one of the members of a table's vector.
+ void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "func " + struct_def.name + "Start";
+ code += MakeCamel(field.name);
+ code += "Vector(builder *flatbuffers.Builder, numElems int) ";
+ code += "flatbuffers.UOffsetT {\n\treturn builder.StartVector(";
+ auto vector_type = field.value.type.VectorType();
+ auto alignment = InlineAlignment(vector_type);
+ auto elem_size = InlineSize(vector_type);
+ code += NumToString(elem_size);
+ code += ", numElems, " + NumToString(alignment);
+ code += ")\n}\n";
+ }
+
+ // Get the offset of the end of a table.
+ void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "func " + struct_def.name + "End";
+ code += "(builder *flatbuffers.Builder) flatbuffers.UOffsetT ";
+ code += "{\n\treturn builder.EndObject()\n}\n";
+ }
+
+ // Generate the receiver for function signatures.
+ void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "func (rcv *" + struct_def.name + ")";
+ }
+
+ // Generate a struct field getter, conditioned on its child type(s).
+ void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ GenComment(field.doc_comment, code_ptr, nullptr, "");
+ if (IsScalar(field.value.type.base_type)) {
+ if (struct_def.fixed) {
+ GetScalarFieldOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetScalarFieldOfTable(struct_def, field, code_ptr);
+ }
+ } else {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT:
+ if (struct_def.fixed) {
+ GetStructFieldOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetStructFieldOfTable(struct_def, field, code_ptr);
+ }
+ break;
+ case BASE_TYPE_STRING:
+ GetStringField(struct_def, field, code_ptr);
+ break;
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+ if (IsVector(field.value.type)) {
+ GetVectorLen(struct_def, field, code_ptr);
+ if (field.value.type.element == BASE_TYPE_UCHAR) {
+ GetUByteSlice(struct_def, field, code_ptr);
+ }
+ }
+ }
+
+ // Mutate the value of a struct's scalar.
+ void MutateScalarFieldOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ std::string type = MakeCamel(GenTypeBasic(field.value.type));
+ std::string setter = "rcv._tab.Mutate" + type;
+ GenReceiver(struct_def, code_ptr);
+ code += " Mutate" + MakeCamel(field.name);
+ code += "(n " + TypeName(field) + ") bool {\n\treturn " + setter;
+ code += "(rcv._tab.Pos+flatbuffers.UOffsetT(";
+ code += NumToString(field.value.offset) + "), ";
+ code += CastToBaseType(field.value.type, "n") + ")\n}\n\n";
+ }
+
+ // Mutate the value of a table's scalar.
+ void MutateScalarFieldOfTable(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ std::string type = MakeCamel(GenTypeBasic(field.value.type));
+ std::string setter = "rcv._tab.Mutate" + type + "Slot";
+ GenReceiver(struct_def, code_ptr);
+ code += " Mutate" + MakeCamel(field.name);
+ code += "(n " + TypeName(field) + ") bool {\n\treturn ";
+ code += setter + "(" + NumToString(field.value.offset) + ", ";
+ code += CastToBaseType(field.value.type, "n") + ")\n";
+ code += "}\n\n";
+ }
+
+ // Mutate an element of a vector of scalars.
+ void MutateElementOfVectorOfNonStruct(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+ std::string type = MakeCamel(GenTypeBasic(vectortype));
+ std::string setter = "rcv._tab.Mutate" + type;
+ GenReceiver(struct_def, code_ptr);
+ code += " Mutate" + MakeCamel(field.name);
+ code += "(j int, n " + TypeName(field) + ") bool ";
+ code += OffsetPrefix(field);
+ code += "\t\ta := rcv._tab.Vector(o)\n";
+ code += "\t\treturn " + setter + "(";
+ code += "a+flatbuffers.UOffsetT(j*";
+ code += NumToString(InlineSize(vectortype)) + "), ";
+ code += CastToBaseType(vectortype, "n") + ")\n";
+ code += "\t}\n";
+ code += "\treturn false\n";
+ code += "}\n\n";
+ }
+
+ // Generate a struct field setter, conditioned on its child type(s).
+ void GenStructMutator(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ GenComment(field.doc_comment, code_ptr, nullptr, "");
+ if (IsScalar(field.value.type.base_type)) {
+ if (struct_def.fixed) {
+ MutateScalarFieldOfStruct(struct_def, field, code_ptr);
+ } else {
+ MutateScalarFieldOfTable(struct_def, field, code_ptr);
+ }
+ } else if (IsVector(field.value.type)) {
+ if (IsScalar(field.value.type.element)) {
+ MutateElementOfVectorOfNonStruct(struct_def, field, code_ptr);
+ }
+ }
+ }
+
+ // Generate table constructors, conditioned on its members' types.
+ void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) {
+ GetStartOfTable(struct_def, code_ptr);
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ auto offset = it - struct_def.fields.vec.begin();
+ BuildFieldOfTable(struct_def, field, offset, code_ptr);
+ if (IsVector(field.value.type)) {
+ BuildVectorOfTable(struct_def, field, code_ptr);
+ }
+ }
+
+ GetEndOffsetOnTable(struct_def, code_ptr);
+ }
+
+ // Generate struct or table methods.
+ void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
+ if (struct_def.generated) return;
+
+ cur_name_space_ = struct_def.defined_namespace;
+
+ GenComment(struct_def.doc_comment, code_ptr, nullptr);
+ if (parser_.opts.generate_object_based_api) {
+ GenNativeStruct(struct_def, code_ptr);
+ }
+ BeginClass(struct_def, code_ptr);
+ if (!struct_def.fixed) {
+ // Generate a special accessor for the table that has been declared as
+ // the root type.
+ NewRootTypeFromBuffer(struct_def, code_ptr);
+ }
+ // Generate the Init method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ InitializeExisting(struct_def, code_ptr);
+ // Generate _tab accessor
+ GenTableAccessor(struct_def, code_ptr);
+
+ // Generate struct fields accessors
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ GenStructAccessor(struct_def, field, code_ptr);
+ GenStructMutator(struct_def, field, code_ptr);
+ }
+
+ // Generate builders
+ if (struct_def.fixed) {
+ // create a struct constructor function
+ GenStructBuilder(struct_def, code_ptr);
+ } else {
+ // Create a set of functions that allow table construction.
+ GenTableBuilders(struct_def, code_ptr);
+ }
+ }
+
+ void GenNativeStruct(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "type " + NativeName(struct_def) + " struct {\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const FieldDef &field = **it;
+ if (field.deprecated) continue;
+ if (IsScalar(field.value.type.base_type) &&
+ field.value.type.enum_def != nullptr &&
+ field.value.type.enum_def->is_union)
+ continue;
+ code += "\t" + MakeCamel(field.name) + " " +
+ NativeType(field.value.type) + "\n";
+ }
+ code += "}\n\n";
+
+ if (!struct_def.fixed) {
+ GenNativeTablePack(struct_def, code_ptr);
+ GenNativeTableUnPack(struct_def, code_ptr);
+ } else {
+ GenNativeStructPack(struct_def, code_ptr);
+ GenNativeStructUnPack(struct_def, code_ptr);
+ }
+ }
+
+ void GenNativeUnion(const EnumDef &enum_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "type " + NativeName(enum_def) + " struct {\n";
+ code += "\tType " + enum_def.name + "\n";
+ code += "\tValue interface{}\n";
+ code += "}\n\n";
+ }
+
+ void GenNativeUnionPack(const EnumDef &enum_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "func (t *" + NativeName(enum_def) +
+ ") Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {\n";
+ code += "\tif t == nil {\n\t\treturn 0\n\t}\n";
+
+ code += "\tswitch t.Type {\n";
+ for (auto it2 = enum_def.Vals().begin(); it2 != enum_def.Vals().end();
+ ++it2) {
+ const EnumVal &ev = **it2;
+ if (ev.IsZero()) continue;
+ code += "\tcase " + enum_def.name + ev.name + ":\n";
+ code += "\t\treturn t.Value.(" + NativeType(ev.union_type) +
+ ").Pack(builder)\n";
+ }
+ code += "\t}\n";
+ code += "\treturn 0\n";
+ code += "}\n\n";
+ }
+
+ void GenNativeUnionUnPack(const EnumDef &enum_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "func (rcv " + enum_def.name +
+ ") UnPack(table flatbuffers.Table) *" + NativeName(enum_def) +
+ " {\n";
+ code += "\tswitch rcv {\n";
+
+ for (auto it2 = enum_def.Vals().begin(); it2 != enum_def.Vals().end();
+ ++it2) {
+ const EnumVal &ev = **it2;
+ if (ev.IsZero()) continue;
+ code += "\tcase " + enum_def.name + ev.name + ":\n";
+ code += "\t\tx := " + ev.union_type.struct_def->name + "{_tab: table}\n";
+
+ code += "\t\treturn &" +
+ WrapInNameSpaceAndTrack(enum_def.defined_namespace,
+ NativeName(enum_def)) +
+ "{ Type: " + enum_def.name + ev.name + ", Value: x.UnPack() }\n";
+ }
+ code += "\t}\n";
+ code += "\treturn nil\n";
+ code += "}\n\n";
+ }
+
+ void GenNativeTablePack(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "func (t *" + NativeName(struct_def) +
+ ") Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {\n";
+ code += "\tif t == nil { return 0 }\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const FieldDef &field = **it;
+ if (field.deprecated) continue;
+ if (IsScalar(field.value.type.base_type)) continue;
+
+ std::string offset = MakeCamel(field.name, false) + "Offset";
+
+ if (IsString(field.value.type)) {
+ code += "\t" + offset + " := builder.CreateString(t." +
+ MakeCamel(field.name) + ")\n";
+ } else if (IsVector(field.value.type) &&
+ field.value.type.element == BASE_TYPE_UCHAR &&
+ field.value.type.enum_def == nullptr) {
+ code += "\t" + offset + " := flatbuffers.UOffsetT(0)\n";
+ code += "\tif t." + MakeCamel(field.name) + " != nil {\n";
+ code += "\t\t" + offset + " = builder.CreateByteString(t." +
+ MakeCamel(field.name) + ")\n";
+ code += "\t}\n";
+ } else if (IsVector(field.value.type)) {
+ code += "\t" + offset + " := flatbuffers.UOffsetT(0)\n";
+ code += "\tif t." + MakeCamel(field.name) + " != nil {\n";
+ std::string length = MakeCamel(field.name, false) + "Length";
+ std::string offsets = MakeCamel(field.name, false) + "Offsets";
+ code += "\t\t" + length + " := len(t." + MakeCamel(field.name) + ")\n";
+ if (field.value.type.element == BASE_TYPE_STRING) {
+ code += "\t\t" + offsets + " := make([]flatbuffers.UOffsetT, " +
+ length + ")\n";
+ code += "\t\tfor j := 0; j < " + length + "; j++ {\n";
+ code += "\t\t\t" + offsets + "[j] = builder.CreateString(t." +
+ MakeCamel(field.name) + "[j])\n";
+ code += "\t\t}\n";
+ } else if (field.value.type.element == BASE_TYPE_STRUCT &&
+ !field.value.type.struct_def->fixed) {
+ code += "\t\t" + offsets + " := make([]flatbuffers.UOffsetT, " +
+ length + ")\n";
+ code += "\t\tfor j := 0; j < " + length + "; j++ {\n";
+ code += "\t\t\t" + offsets + "[j] = t." + MakeCamel(field.name) +
+ "[j].Pack(builder)\n";
+ code += "\t\t}\n";
+ }
+ code += "\t\t" + struct_def.name + "Start" + MakeCamel(field.name) +
+ "Vector(builder, " + length + ")\n";
+ code += "\t\tfor j := " + length + " - 1; j >= 0; j-- {\n";
+ if (IsScalar(field.value.type.element)) {
+ code += "\t\t\tbuilder.Prepend" +
+ MakeCamel(GenTypeBasic(field.value.type.VectorType())) + "(" +
+ CastToBaseType(field.value.type.VectorType(),
+ "t." + MakeCamel(field.name) + "[j]") +
+ ")\n";
+ } else if (field.value.type.element == BASE_TYPE_STRUCT &&
+ field.value.type.struct_def->fixed) {
+ code += "\t\t\tt." + MakeCamel(field.name) + "[j].Pack(builder)\n";
+ } else {
+ code += "\t\t\tbuilder.PrependUOffsetT(" + offsets + "[j])\n";
+ }
+ code += "\t\t}\n";
+ code += "\t\t" + offset + " = builder.EndVector(" + length + ")\n";
+ code += "\t}\n";
+ } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
+ if (field.value.type.struct_def->fixed) continue;
+ code += "\t" + offset + " := t." + MakeCamel(field.name) +
+ ".Pack(builder)\n";
+ } else if (field.value.type.base_type == BASE_TYPE_UNION) {
+ code += "\t" + offset + " := t." + MakeCamel(field.name) +
+ ".Pack(builder)\n";
+ code += "\t\n";
+ } else {
+ FLATBUFFERS_ASSERT(0);
+ }
+ }
+ code += "\t" + struct_def.name + "Start(builder)\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const FieldDef &field = **it;
+ if (field.deprecated) continue;
+
+ std::string offset = MakeCamel(field.name, false) + "Offset";
+ if (IsScalar(field.value.type.base_type)) {
+ if (field.value.type.enum_def == nullptr ||
+ !field.value.type.enum_def->is_union) {
+ code += "\t" + struct_def.name + "Add" + MakeCamel(field.name) +
+ "(builder, t." + MakeCamel(field.name) + ")\n";
+ }
+ } else {
+ if (field.value.type.base_type == BASE_TYPE_STRUCT &&
+ field.value.type.struct_def->fixed) {
+ code += "\t" + offset + " := t." + MakeCamel(field.name) +
+ ".Pack(builder)\n";
+ } else if (field.value.type.enum_def != nullptr &&
+ field.value.type.enum_def->is_union) {
+ code += "\tif t." + MakeCamel(field.name) + " != nil {\n";
+ code += "\t\t" + struct_def.name + "Add" +
+ MakeCamel(field.name + UnionTypeFieldSuffix()) +
+ "(builder, t." + MakeCamel(field.name) + ".Type)\n";
+ code += "\t}\n";
+ }
+ code += "\t" + struct_def.name + "Add" + MakeCamel(field.name) +
+ "(builder, " + offset + ")\n";
+ }
+ }
+ code += "\treturn " + struct_def.name + "End(builder)\n";
+ code += "}\n\n";
+ }
+
+ void GenNativeTableUnPack(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" +
+ NativeName(struct_def) + ") {\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const FieldDef &field = **it;
+ if (field.deprecated) continue;
+ std::string field_name_camel = MakeCamel(field.name);
+ std::string length = MakeCamel(field.name, false) + "Length";
+ if (IsScalar(field.value.type.base_type)) {
+ if (field.value.type.enum_def != nullptr &&
+ field.value.type.enum_def->is_union)
+ continue;
+ code +=
+ "\tt." + field_name_camel + " = rcv." + field_name_camel + "()\n";
+ } else if (IsString(field.value.type)) {
+ code += "\tt." + field_name_camel + " = string(rcv." +
+ field_name_camel + "())\n";
+ } else if (IsVector(field.value.type) &&
+ field.value.type.element == BASE_TYPE_UCHAR &&
+ field.value.type.enum_def == nullptr) {
+ code += "\tt." + field_name_camel + " = rcv." + field_name_camel +
+ "Bytes()\n";
+ } else if (IsVector(field.value.type)) {
+ code += "\t" + length + " := rcv." + field_name_camel + "Length()\n";
+ code += "\tt." + field_name_camel + " = make(" +
+ NativeType(field.value.type) + ", " + length + ")\n";
+ code += "\tfor j := 0; j < " + length + "; j++ {\n";
+ if (field.value.type.element == BASE_TYPE_STRUCT) {
+ code += "\t\tx := " +
+ WrapInNameSpaceAndTrack(*field.value.type.struct_def) +
+ "{}\n";
+ code += "\t\trcv." + field_name_camel + "(&x, j)\n";
+ }
+ code += "\t\tt." + field_name_camel + "[j] = ";
+ if (IsScalar(field.value.type.element)) {
+ code += "rcv." + field_name_camel + "(j)";
+ } else if (field.value.type.element == BASE_TYPE_STRING) {
+ code += "string(rcv." + field_name_camel + "(j))";
+ } else if (field.value.type.element == BASE_TYPE_STRUCT) {
+ code += "x.UnPack()";
+ } else {
+ // TODO(iceboy): Support vector of unions.
+ FLATBUFFERS_ASSERT(0);
+ }
+ code += "\n";
+ code += "\t}\n";
+ } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
+ code += "\tt." + field_name_camel + " = rcv." + field_name_camel +
+ "(nil).UnPack()\n";
+ } else if (field.value.type.base_type == BASE_TYPE_UNION) {
+ std::string field_table = MakeCamel(field.name, false) + "Table";
+ code += "\t" + field_table + " := flatbuffers.Table{}\n";
+ code +=
+ "\tif rcv." + MakeCamel(field.name) + "(&" + field_table + ") {\n";
+ code += "\t\tt." + field_name_camel + " = rcv." +
+ MakeCamel(field.name + UnionTypeFieldSuffix()) + "().UnPack(" +
+ field_table + ")\n";
+ code += "\t}\n";
+ } else {
+ FLATBUFFERS_ASSERT(0);
+ }
+ }
+ code += "}\n\n";
+
+ code += "func (rcv *" + struct_def.name + ") UnPack() *" +
+ NativeName(struct_def) + " {\n";
+ code += "\tif rcv == nil { return nil }\n";
+ code += "\tt := &" + NativeName(struct_def) + "{}\n";
+ code += "\trcv.UnPackTo(t)\n";
+ code += "\treturn t\n";
+ code += "}\n\n";
+ }
+
+ void GenNativeStructPack(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "func (t *" + NativeName(struct_def) +
+ ") Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {\n";
+ code += "\tif t == nil { return 0 }\n";
+ code += "\treturn Create" + struct_def.name + "(builder";
+ StructPackArgs(struct_def, "", code_ptr);
+ code += ")\n";
+ code += "}\n";
+ }
+
+ void StructPackArgs(const StructDef &struct_def, const char *nameprefix,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const FieldDef &field = **it;
+ if (field.value.type.base_type == BASE_TYPE_STRUCT) {
+ StructPackArgs(*field.value.type.struct_def,
+ (nameprefix + MakeCamel(field.name) + ".").c_str(),
+ code_ptr);
+ } else {
+ code += std::string(", t.") + nameprefix + MakeCamel(field.name);
+ }
+ }
+ }
+
+ void GenNativeStructUnPack(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" +
+ NativeName(struct_def) + ") {\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const FieldDef &field = **it;
+ if (field.value.type.base_type == BASE_TYPE_STRUCT) {
+ code += "\tt." + MakeCamel(field.name) + " = rcv." +
+ MakeCamel(field.name) + "(nil).UnPack()\n";
+ } else {
+ code += "\tt." + MakeCamel(field.name) + " = rcv." +
+ MakeCamel(field.name) + "()\n";
+ }
+ }
+ code += "}\n\n";
+
+ code += "func (rcv *" + struct_def.name + ") UnPack() *" +
+ NativeName(struct_def) + " {\n";
+ code += "\tif rcv == nil { return nil }\n";
+ code += "\tt := &" + NativeName(struct_def) + "{}\n";
+ code += "\trcv.UnPackTo(t)\n";
+ code += "\treturn t\n";
+ code += "}\n\n";
+ }
+
+ // Generate enum declarations.
+ void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
+ if (enum_def.generated) return;
+
+ auto max_name_length = MaxNameLength(enum_def);
+ cur_name_space_ = enum_def.defined_namespace;
+
+ GenComment(enum_def.doc_comment, code_ptr, nullptr);
+ GenEnumType(enum_def, code_ptr);
+ BeginEnum(code_ptr);
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ const EnumVal &ev = **it;
+ GenComment(ev.doc_comment, code_ptr, nullptr, "\t");
+ EnumMember(enum_def, ev, max_name_length, code_ptr);
+ }
+ EndEnum(code_ptr);
+
+ BeginEnumNames(enum_def, code_ptr);
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ const EnumVal &ev = **it;
+ EnumNameMember(enum_def, ev, max_name_length, code_ptr);
+ }
+ EndEnumNames(code_ptr);
+
+ BeginEnumValues(enum_def, code_ptr);
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ EnumValueMember(enum_def, ev, max_name_length, code_ptr);
+ }
+ EndEnumValues(code_ptr);
+
+ EnumStringer(enum_def, code_ptr);
+ }
+
+ // Returns the function name that is able to read a value of the given type.
+ std::string GenGetter(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return "rcv._tab.ByteVector";
+ case BASE_TYPE_UNION: return "rcv._tab.Union";
+ case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
+ default: return "rcv._tab.Get" + MakeCamel(GenTypeBasic(type));
+ }
+ }
+
+ // Returns the method name for use with add/put calls.
+ std::string GenMethod(const FieldDef &field) {
+ return IsScalar(field.value.type.base_type)
+ ? MakeCamel(GenTypeBasic(field.value.type))
+ : (IsStruct(field.value.type) ? "Struct" : "UOffsetT");
+ }
+
+ std::string GenTypeBasic(const Type &type) {
+ // clang-format off
+ static const char *ctypename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, ...) \
+ #GTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+ return ctypename[type.base_type];
+ }
+
+ std::string GenTypePointer(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return "[]byte";
+ case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
+ case BASE_TYPE_STRUCT: return WrapInNameSpaceAndTrack(*type.struct_def);
+ case BASE_TYPE_UNION:
+ // fall through
+ default: return "*flatbuffers.Table";
+ }
+ }
+
+ std::string GenTypeGet(const Type &type) {
+ if (type.enum_def != nullptr) { return GetEnumTypeName(*type.enum_def); }
+ return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
+ }
+
+ std::string TypeName(const FieldDef &field) {
+ return GenTypeGet(field.value.type);
+ }
+
+ // If type is an enum, returns value with a cast to the enum type, otherwise
+ // returns value as-is.
+ std::string CastToEnum(const Type &type, std::string value) {
+ if (type.enum_def == nullptr) {
+ return value;
+ } else {
+ return GenTypeGet(type) + "(" + value + ")";
+ }
+ }
+
+ // If type is an enum, returns value with a cast to the enum base type,
+ // otherwise returns value as-is.
+ std::string CastToBaseType(const Type &type, std::string value) {
+ if (type.enum_def == nullptr) {
+ return value;
+ } else {
+ return GenTypeBasic(type) + "(" + value + ")";
+ }
+ }
+
+ std::string GenConstant(const FieldDef &field) {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_BOOL:
+ return field.value.constant == "0" ? "false" : "true";
+ default: return field.value.constant;
+ }
+ }
+
+ std::string NativeName(const StructDef &struct_def) {
+ return parser_.opts.object_prefix + struct_def.name +
+ parser_.opts.object_suffix;
+ }
+
+ std::string NativeName(const EnumDef &enum_def) {
+ return parser_.opts.object_prefix + enum_def.name +
+ parser_.opts.object_suffix;
+ }
+
+ std::string NativeType(const Type &type) {
+ if (IsScalar(type.base_type)) {
+ if (type.enum_def == nullptr) {
+ return GenTypeBasic(type);
+ } else {
+ return GetEnumTypeName(*type.enum_def);
+ }
+ } else if (IsString(type)) {
+ return "string";
+ } else if (IsVector(type)) {
+ return "[]" + NativeType(type.VectorType());
+ } else if (type.base_type == BASE_TYPE_STRUCT) {
+ return "*" + WrapInNameSpaceAndTrack(type.struct_def->defined_namespace,
+ NativeName(*type.struct_def));
+ } else if (type.base_type == BASE_TYPE_UNION) {
+ return "*" + WrapInNameSpaceAndTrack(type.enum_def->defined_namespace,
+ NativeName(*type.enum_def));
+ }
+ FLATBUFFERS_ASSERT(0);
+ return std::string();
+ }
+
+ // Create a struct with a builder and the struct's arguments.
+ void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) {
+ BeginBuilderArgs(struct_def, code_ptr);
+ StructBuilderArgs(struct_def, "", code_ptr);
+ EndBuilderArgs(code_ptr);
+
+ StructBuilderBody(struct_def, "", code_ptr);
+ EndBuilderBody(code_ptr);
+ }
+ // Begin by declaring namespace and imports.
+ void BeginFile(const std::string &name_space_name, const bool needs_imports,
+ const bool is_enum, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code = code +
+ "// Code generated by the FlatBuffers compiler. DO NOT EDIT.\n\n";
+ code += "package " + name_space_name + "\n\n";
+ if (needs_imports) {
+ code += "import (\n";
+ if (is_enum) { code += "\t\"strconv\"\n\n"; }
+ if (!parser_.opts.go_import.empty()) {
+ code += "\tflatbuffers \"" + parser_.opts.go_import + "\"\n";
+ } else {
+ code += "\tflatbuffers \"github.com/google/flatbuffers/go\"\n";
+ }
+ if (tracked_imported_namespaces_.size() > 0) {
+ code += "\n";
+ for (auto it = tracked_imported_namespaces_.begin();
+ it != tracked_imported_namespaces_.end(); ++it) {
+ code += "\t" + NamespaceImportName(*it) + " \"" +
+ NamespaceImportPath(*it) + "\"\n";
+ }
+ }
+ code += ")\n\n";
+ } else {
+ if (is_enum) { code += "import \"strconv\"\n\n"; }
+ }
+ }
+
+ // Save out the generated code for a Go Table type.
+ bool SaveType(const Definition &def, const std::string &classcode,
+ const bool needs_imports, const bool is_enum) {
+ if (!classcode.length()) return true;
+
+ Namespace &ns = go_namespace_.components.empty() ? *def.defined_namespace
+ : go_namespace_;
+ std::string code = "";
+ BeginFile(LastNamespacePart(ns), needs_imports, is_enum, &code);
+ code += classcode;
+ // Strip extra newlines at end of file to make it gofmt-clean.
+ while (code.length() > 2 && code.substr(code.length() - 2) == "\n\n") {
+ code.pop_back();
+ }
+ std::string filename = NamespaceDir(ns) + def.name + ".go";
+ return SaveFile(filename.c_str(), code, false);
+ }
+
+ // Create the full name of the imported namespace (format: A__B__C).
+ std::string NamespaceImportName(const Namespace *ns) {
+ std::string s = "";
+ for (auto it = ns->components.begin(); it != ns->components.end(); ++it) {
+ if (s.size() == 0) {
+ s += *it;
+ } else {
+ s += "__" + *it;
+ }
+ }
+ return s;
+ }
+
+ // Create the full path for the imported namespace (format: A/B/C).
+ std::string NamespaceImportPath(const Namespace *ns) {
+ std::string s = "";
+ for (auto it = ns->components.begin(); it != ns->components.end(); ++it) {
+ if (s.size() == 0) {
+ s += *it;
+ } else {
+ s += "/" + *it;
+ }
+ }
+ return s;
+ }
+
+ // Ensure that a type is prefixed with its go package import name if it is
+ // used outside of its namespace.
+ std::string WrapInNameSpaceAndTrack(const Namespace *ns,
+ const std::string &name) {
+ if (CurrentNameSpace() == ns) return name;
+
+ tracked_imported_namespaces_.insert(ns);
+
+ std::string import_name = NamespaceImportName(ns);
+ return import_name + "." + name;
+ }
+
+ std::string WrapInNameSpaceAndTrack(const Definition &def) {
+ return WrapInNameSpaceAndTrack(def.defined_namespace, def.name);
+ }
+
+ const Namespace *CurrentNameSpace() const { return cur_name_space_; }
+
+ static size_t MaxNameLength(const EnumDef &enum_def) {
+ size_t max = 0;
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ max = std::max((*it)->name.length(), max);
+ }
+ return max;
+ }
+};
+} // namespace go
+
+bool GenerateGo(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ go::GoGenerator generator(parser, path, file_name, parser.opts.go_namespace);
+ return generator.generate();
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp b/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp
new file mode 100644
index 0000000000..9aea745d4e
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_grpc.cpp
@@ -0,0 +1,557 @@
+/*
+ * 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 "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+#include "src/compiler/cpp_generator.h"
+#include "src/compiler/go_generator.h"
+#include "src/compiler/java_generator.h"
+#include "src/compiler/python_generator.h"
+#include "src/compiler/swift_generator.h"
+#include "src/compiler/ts_generator.h"
+
+#if defined(_MSC_VER)
+# pragma warning(push)
+# pragma warning(disable : 4512) // C4512: 'class' : assignment operator could
+// not be generated
+#endif
+
+namespace flatbuffers {
+
+class FlatBufMethod : public grpc_generator::Method {
+ public:
+ enum Streaming { kNone, kClient, kServer, kBiDi };
+
+ FlatBufMethod(const RPCCall *method) : method_(method) {
+ streaming_ = kNone;
+ auto val = method_->attributes.Lookup("streaming");
+ if (val) {
+ if (val->constant == "client") streaming_ = kClient;
+ if (val->constant == "server") streaming_ = kServer;
+ if (val->constant == "bidi") streaming_ = kBiDi;
+ }
+ }
+
+ grpc::string GetLeadingComments(const grpc::string) const { return ""; }
+
+ grpc::string GetTrailingComments(const grpc::string) const { return ""; }
+
+ std::vector<grpc::string> GetAllComments() const {
+ return method_->doc_comment;
+ }
+
+ std::string name() const { return method_->name; }
+
+ // TODO: This method need to incorporate namespace for C++ side. Other
+ // language bindings simply don't use this method.
+ std::string GRPCType(const StructDef &sd) const {
+ return "flatbuffers::grpc::Message<" + sd.name + ">";
+ }
+
+ std::vector<std::string> get_input_namespace_parts() const {
+ return (*method_->request).defined_namespace->components;
+ }
+
+ std::string get_input_type_name() const { return (*method_->request).name; }
+
+ std::vector<std::string> get_output_namespace_parts() const {
+ return (*method_->response).defined_namespace->components;
+ }
+
+ std::string get_output_type_name() const { return (*method_->response).name; }
+
+ bool get_module_and_message_path_input(grpc::string * /*str*/,
+ grpc::string /*generator_file_name*/,
+ bool /*generate_in_pb2_grpc*/,
+ grpc::string /*import_prefix*/) const {
+ return true;
+ }
+
+ bool get_module_and_message_path_output(
+ grpc::string * /*str*/, grpc::string /*generator_file_name*/,
+ bool /*generate_in_pb2_grpc*/, grpc::string /*import_prefix*/) const {
+ return true;
+ }
+
+ std::string get_fb_builder() const { return "builder"; }
+
+ std::string input_type_name() const { return GRPCType(*method_->request); }
+
+ std::string output_type_name() const { return GRPCType(*method_->response); }
+
+ bool NoStreaming() const { return streaming_ == kNone; }
+
+ bool ClientStreaming() const { return streaming_ == kClient; }
+
+ bool ServerStreaming() const { return streaming_ == kServer; }
+
+ bool BidiStreaming() const { return streaming_ == kBiDi; }
+
+ private:
+ const RPCCall *method_;
+ Streaming streaming_;
+};
+
+class FlatBufService : public grpc_generator::Service {
+ public:
+ FlatBufService(const ServiceDef *service) : service_(service) {}
+
+ grpc::string GetLeadingComments(const grpc::string) const { return ""; }
+
+ grpc::string GetTrailingComments(const grpc::string) const { return ""; }
+
+ std::vector<grpc::string> GetAllComments() const {
+ return service_->doc_comment;
+ }
+
+ std::vector<grpc::string> namespace_parts() const {
+ return service_->defined_namespace->components;
+ }
+
+ std::string name() const { return service_->name; }
+ bool is_internal() const {
+ return service_->Definition::attributes.Lookup("private") ? true : false;
+ }
+
+ int method_count() const {
+ return static_cast<int>(service_->calls.vec.size());
+ }
+
+ std::unique_ptr<const grpc_generator::Method> method(int i) const {
+ return std::unique_ptr<const grpc_generator::Method>(
+ new FlatBufMethod(service_->calls.vec[i]));
+ }
+
+ private:
+ const ServiceDef *service_;
+};
+
+class FlatBufPrinter : public grpc_generator::Printer {
+ public:
+ FlatBufPrinter(std::string *str, const char indentation_type)
+ : str_(str),
+ escape_char_('$'),
+ indent_(0),
+ indentation_size_(2),
+ indentation_type_(indentation_type) {}
+
+ void Print(const std::map<std::string, std::string> &vars,
+ const char *string_template) {
+ std::string s = string_template;
+ // Replace any occurrences of strings in "vars" that are surrounded
+ // by the escape character by what they're mapped to.
+ size_t pos;
+ while ((pos = s.find(escape_char_)) != std::string::npos) {
+ // Found an escape char, must also find the closing one.
+ size_t pos2 = s.find(escape_char_, pos + 1);
+ // If placeholder not closed, ignore.
+ if (pos2 == std::string::npos) break;
+ auto it = vars.find(s.substr(pos + 1, pos2 - pos - 1));
+ // If unknown placeholder, ignore.
+ if (it == vars.end()) break;
+ // Subtitute placeholder.
+ s.replace(pos, pos2 - pos + 1, it->second);
+ }
+ Print(s.c_str());
+ }
+
+ void Print(const char *s) {
+ if (s == nullptr || *s == '\0') { return; }
+ // Add this string, but for each part separated by \n, add indentation.
+ for (;;) {
+ // Current indentation.
+ str_->insert(str_->end(), indent_ * indentation_size_, indentation_type_);
+ // See if this contains more than one line.
+ const char *lf = strchr(s, '\n');
+ if (lf) {
+ (*str_) += std::string(s, lf + 1);
+ s = lf + 1;
+ if (!*s) break; // Only continue if there's more lines.
+ } else {
+ (*str_) += s;
+ break;
+ }
+ }
+ }
+
+ void SetIndentationSize(const int size) {
+ FLATBUFFERS_ASSERT(str_->empty());
+ indentation_size_ = size;
+ }
+
+ void Indent() { indent_++; }
+
+ void Outdent() {
+ indent_--;
+ FLATBUFFERS_ASSERT(indent_ >= 0);
+ }
+
+ private:
+ std::string *str_;
+ char escape_char_;
+ int indent_;
+ int indentation_size_;
+ char indentation_type_;
+};
+
+class FlatBufFile : public grpc_generator::File {
+ public:
+ enum Language {
+ kLanguageGo,
+ kLanguageCpp,
+ kLanguageJava,
+ kLanguagePython,
+ kLanguageSwift,
+ kLanguageTS
+ };
+
+ FlatBufFile(const Parser &parser, const std::string &file_name,
+ Language language)
+ : parser_(parser), file_name_(file_name), language_(language) {}
+
+ FlatBufFile &operator=(const FlatBufFile &);
+
+ grpc::string GetLeadingComments(const grpc::string) const { return ""; }
+
+ grpc::string GetTrailingComments(const grpc::string) const { return ""; }
+
+ std::vector<grpc::string> GetAllComments() const {
+ return std::vector<grpc::string>();
+ }
+
+ std::string filename() const { return file_name_; }
+
+ std::string filename_without_ext() const {
+ return StripExtension(file_name_);
+ }
+
+ std::string message_header_ext() const { return "_generated.h"; }
+
+ std::string service_header_ext() const { return ".grpc.fb.h"; }
+
+ std::string package() const {
+ return parser_.current_namespace_->GetFullyQualifiedName("");
+ }
+
+ std::vector<std::string> package_parts() const {
+ return parser_.current_namespace_->components;
+ }
+
+ std::string additional_headers() const {
+ switch (language_) {
+ case kLanguageCpp: {
+ return "#include \"flatbuffers/grpc.h\"\n";
+ }
+ case kLanguageGo: {
+ return "import \"github.com/google/flatbuffers/go\"";
+ }
+ case kLanguageJava: {
+ return "import com.google.flatbuffers.grpc.FlatbuffersUtils;";
+ }
+ case kLanguagePython: {
+ return "";
+ }
+ case kLanguageSwift: {
+ return "";
+ }
+ case kLanguageTS: {
+ return "";
+ }
+ }
+ return "";
+ }
+
+ int service_count() const {
+ return static_cast<int>(parser_.services_.vec.size());
+ }
+
+ std::unique_ptr<const grpc_generator::Service> service(int i) const {
+ return std::unique_ptr<const grpc_generator::Service>(
+ new FlatBufService(parser_.services_.vec[i]));
+ }
+
+ std::unique_ptr<grpc_generator::Printer> CreatePrinter(
+ std::string *str, const char indentation_type = ' ') const {
+ return std::unique_ptr<grpc_generator::Printer>(
+ new FlatBufPrinter(str, indentation_type));
+ }
+
+ private:
+ const Parser &parser_;
+ const std::string &file_name_;
+ const Language language_;
+};
+
+class GoGRPCGenerator : public flatbuffers::BaseGenerator {
+ public:
+ GoGRPCGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", "" /*Unused*/, "go"),
+ parser_(parser),
+ path_(path),
+ file_name_(file_name) {}
+
+ bool generate() {
+ FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageGo);
+ grpc_go_generator::Parameters p;
+ p.custom_method_io_type = "flatbuffers.Builder";
+ for (int i = 0; i < file.service_count(); i++) {
+ auto service = file.service(i);
+ const Definition *def = parser_.services_.vec[i];
+ p.package_name = LastNamespacePart(*(def->defined_namespace));
+ p.service_prefix =
+ def->defined_namespace->GetFullyQualifiedName(""); // file.package();
+ std::string output =
+ grpc_go_generator::GenerateServiceSource(&file, service.get(), &p);
+ std::string filename =
+ NamespaceDir(*def->defined_namespace) + def->name + "_grpc.go";
+ if (!flatbuffers::SaveFile(filename.c_str(), output, false)) return false;
+ }
+ return true;
+ }
+
+ protected:
+ const Parser &parser_;
+ const std::string &path_, &file_name_;
+};
+
+bool GenerateGoGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ int nservices = 0;
+ for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
+ ++it) {
+ if (!(*it)->generated) nservices++;
+ }
+ if (!nservices) return true;
+ return GoGRPCGenerator(parser, path, file_name).generate();
+}
+
+bool GenerateCppGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ int nservices = 0;
+ for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
+ ++it) {
+ if (!(*it)->generated) nservices++;
+ }
+ if (!nservices) return true;
+
+ grpc_cpp_generator::Parameters generator_parameters;
+ // TODO(wvo): make the other parameters in this struct configurable.
+ generator_parameters.use_system_headers = true;
+
+ FlatBufFile fbfile(parser, file_name, FlatBufFile::kLanguageCpp);
+
+ std::string header_code =
+ grpc_cpp_generator::GetHeaderPrologue(&fbfile, generator_parameters) +
+ grpc_cpp_generator::GetHeaderIncludes(&fbfile, generator_parameters) +
+ grpc_cpp_generator::GetHeaderServices(&fbfile, generator_parameters) +
+ grpc_cpp_generator::GetHeaderEpilogue(&fbfile, generator_parameters);
+
+ std::string source_code =
+ grpc_cpp_generator::GetSourcePrologue(&fbfile, generator_parameters) +
+ grpc_cpp_generator::GetSourceIncludes(&fbfile, generator_parameters) +
+ grpc_cpp_generator::GetSourceServices(&fbfile, generator_parameters) +
+ grpc_cpp_generator::GetSourceEpilogue(&fbfile, generator_parameters);
+
+ return flatbuffers::SaveFile((path + file_name + ".grpc.fb.h").c_str(),
+ header_code, false) &&
+ flatbuffers::SaveFile((path + file_name + ".grpc.fb.cc").c_str(),
+ source_code, false);
+}
+
+class JavaGRPCGenerator : public flatbuffers::BaseGenerator {
+ public:
+ JavaGRPCGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", "." /*separator*/, "java") {}
+
+ bool generate() {
+ FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageJava);
+ grpc_java_generator::Parameters p;
+ for (int i = 0; i < file.service_count(); i++) {
+ auto service = file.service(i);
+ const Definition *def = parser_.services_.vec[i];
+ p.package_name =
+ def->defined_namespace->GetFullyQualifiedName(""); // file.package();
+ std::string output =
+ grpc_java_generator::GenerateServiceSource(&file, service.get(), &p);
+ std::string filename =
+ NamespaceDir(*def->defined_namespace) + def->name + "Grpc.java";
+ if (!flatbuffers::SaveFile(filename.c_str(), output, false)) return false;
+ }
+ return true;
+ }
+};
+
+bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ int nservices = 0;
+ for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
+ ++it) {
+ if (!(*it)->generated) nservices++;
+ }
+ if (!nservices) return true;
+ return JavaGRPCGenerator(parser, path, file_name).generate();
+}
+
+class PythonGRPCGenerator : public flatbuffers::BaseGenerator {
+ private:
+ CodeWriter code_;
+
+ public:
+ PythonGRPCGenerator(const Parser &parser, const std::string &filename)
+ : BaseGenerator(parser, "", filename, "", "" /*Unused*/, "swift") {}
+
+ bool generate() {
+ code_.Clear();
+ code_ +=
+ "# Generated by the gRPC Python protocol compiler plugin. "
+ "DO NOT EDIT!\n";
+ code_ += "import grpc\n";
+
+ FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguagePython);
+
+ for (int i = 0; i < file.service_count(); i++) {
+ auto service = file.service(i);
+ code_ += grpc_python_generator::Generate(&file, service.get());
+ }
+ const auto final_code = code_.ToString();
+ const auto filename = GenerateFileName();
+ return SaveFile(filename.c_str(), final_code, false);
+ }
+
+ std::string GenerateFileName() {
+ std::string namespace_dir;
+ auto &namespaces = parser_.namespaces_.back()->components;
+ for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
+ if (it != namespaces.begin()) namespace_dir += kPathSeparator;
+ namespace_dir += *it;
+ }
+ std::string grpc_py_filename = namespace_dir;
+ if (!namespace_dir.empty()) grpc_py_filename += kPathSeparator;
+ return grpc_py_filename + file_name_ + "_grpc_fb.py";
+ }
+};
+
+bool GeneratePythonGRPC(const Parser &parser, const std::string & /*path*/,
+ const std::string &file_name) {
+ int nservices = 0;
+ for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
+ ++it) {
+ if (!(*it)->generated) nservices++;
+ }
+ if (!nservices) return true;
+
+ return PythonGRPCGenerator(parser, file_name).generate();
+}
+
+class SwiftGRPCGenerator : public flatbuffers::BaseGenerator {
+ private:
+ CodeWriter code_;
+
+ public:
+ SwiftGRPCGenerator(const Parser &parser, const std::string &path,
+ const std::string &filename)
+ : BaseGenerator(parser, path, filename, "", "" /*Unused*/, "swift") {}
+
+ bool generate() {
+ code_.Clear();
+ code_ += "// Generated GRPC code for FlatBuffers swift!";
+ code_ += grpc_swift_generator::GenerateHeader();
+ FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageSwift);
+ for (int i = 0; i < file.service_count(); i++) {
+ auto service = file.service(i);
+ code_ += grpc_swift_generator::Generate(&file, service.get());
+ }
+ const auto final_code = code_.ToString();
+ const auto filename = GeneratedFileName(path_, file_name_);
+ return SaveFile(filename.c_str(), final_code, false);
+ }
+
+ static std::string GeneratedFileName(const std::string &path,
+ const std::string &file_name) {
+ return path + file_name + ".grpc.swift";
+ }
+};
+
+bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ int nservices = 0;
+ for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
+ ++it) {
+ if (!(*it)->generated) nservices++;
+ }
+ if (!nservices) return true;
+ return SwiftGRPCGenerator(parser, path, file_name).generate();
+}
+
+class TSGRPCGenerator : public flatbuffers::BaseGenerator {
+ private:
+ CodeWriter code_;
+
+ public:
+ TSGRPCGenerator(const Parser &parser, const std::string &path,
+ const std::string &filename)
+ : BaseGenerator(parser, path, filename, "", "" /*Unused*/, "ts") {}
+
+ bool generate() {
+ code_.Clear();
+ FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageTS);
+
+ for (int i = 0; i < file.service_count(); i++) {
+ auto service = file.service(i);
+ code_ += grpc_ts_generator::Generate(&file, service.get(), file_name_);
+ const auto ts_name = GeneratedFileName(path_, file_name_);
+ if (!SaveFile(ts_name.c_str(), code_.ToString(), false)) return false;
+
+ code_.Clear();
+ code_ += grpc_ts_generator::GenerateInterface(&file, service.get(),
+ file_name_);
+ const auto ts_interface_name = GeneratedFileName(path_, file_name_, true);
+ if (!SaveFile(ts_interface_name.c_str(), code_.ToString(), false))
+ return false;
+ }
+ return true;
+ }
+
+ static std::string GeneratedFileName(const std::string &path,
+ const std::string &file_name,
+ const bool is_interface = false) {
+ if (is_interface) return path + file_name + "_grpc.d.ts";
+ return path + file_name + "_grpc.js";
+ }
+};
+
+bool GenerateTSGRPC(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ int nservices = 0;
+ for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end();
+ ++it) {
+ if (!(*it)->generated) nservices++;
+ }
+ if (!nservices) return true;
+ return TSGRPCGenerator(parser, path, file_name).generate();
+}
+
+} // namespace flatbuffers
+
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#endif
diff --git a/contrib/libs/flatbuffers/src/idl_gen_java.cpp b/contrib/libs/flatbuffers/src/idl_gen_java.cpp
new file mode 100644
index 0000000000..cfd3a55cdb
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_java.cpp
@@ -0,0 +1,1244 @@
+/*
+ * 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 "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+#if defined(FLATBUFFERS_CPP98_STL)
+# include <cctype>
+#endif // defined(FLATBUFFERS_CPP98_STL)
+
+namespace flatbuffers {
+namespace java {
+
+static TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN",
+ "POSITIVE_INFINITY",
+ "NEGATIVE_INFINITY");
+
+static CommentConfig comment_config = {
+ "/**",
+ " *",
+ " */",
+};
+
+class JavaGenerator : public BaseGenerator {
+ public:
+ JavaGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", ".", "java"),
+ cur_name_space_(nullptr) {}
+
+ JavaGenerator &operator=(const JavaGenerator &);
+ bool generate() {
+ std::string one_file_code;
+ cur_name_space_ = parser_.current_namespace_;
+
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ std::string enumcode;
+ auto &enum_def = **it;
+ if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace;
+ GenEnum(enum_def, &enumcode);
+ if (parser_.opts.one_file) {
+ one_file_code += enumcode;
+ } else {
+ if (!SaveType(enum_def.name, *enum_def.defined_namespace, enumcode,
+ /* needs_includes= */ false))
+ return false;
+ }
+ }
+
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ std::string declcode;
+ auto &struct_def = **it;
+ if (!parser_.opts.one_file)
+ cur_name_space_ = struct_def.defined_namespace;
+ GenStruct(struct_def, &declcode);
+ if (parser_.opts.one_file) {
+ one_file_code += declcode;
+ } else {
+ if (!SaveType(struct_def.name, *struct_def.defined_namespace, declcode,
+ /* needs_includes= */ true))
+ return false;
+ }
+ }
+
+ if (parser_.opts.one_file) {
+ return SaveType(file_name_, *parser_.current_namespace_, one_file_code,
+ /* needs_includes= */ true);
+ }
+ return true;
+ }
+
+ // 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;
+ code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
+
+ std::string namespace_name = FullNamespace(".", ns);
+ if (!namespace_name.empty()) {
+ code += "package " + namespace_name + ";";
+ code += "\n\n";
+ }
+ if (needs_includes) {
+ code +=
+ "import java.nio.*;\nimport java.lang.*;\nimport "
+ "java.util.*;\nimport com.google.flatbuffers.*;\n";
+ if (parser_.opts.gen_nullable) {
+ code += "\nimport javax.annotation.Nullable;\n";
+ }
+ if (parser_.opts.java_checkerframework) {
+ code += "\nimport org.checkerframework.dataflow.qual.Pure;\n";
+ }
+ code += "\n";
+ }
+
+ code += classcode;
+ if (!namespace_name.empty()) code += "";
+ auto filename = NamespaceDir(ns) + defname + ".java";
+ return SaveFile(filename.c_str(), code, false);
+ }
+
+ const Namespace *CurrentNameSpace() const { return cur_name_space_; }
+
+ std::string GenNullableAnnotation(const Type &t) const {
+ return parser_.opts.gen_nullable &&
+ !IsScalar(DestinationType(t, true).base_type) &&
+ t.base_type != BASE_TYPE_VECTOR
+ ? " @Nullable "
+ : "";
+ }
+
+ std::string GenPureAnnotation(const Type &t) const {
+ return parser_.opts.java_checkerframework &&
+ !IsScalar(DestinationType(t, true).base_type)
+ ? " @Pure "
+ : "";
+ }
+
+ std::string GenTypeBasic(const Type &type) const {
+ // clang-format off
+ static const char * const java_typename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, ...) \
+ #JTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+ return java_typename[type.base_type];
+ }
+
+ 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 WrapInNameSpace(*type.struct_def);
+ case BASE_TYPE_UNION: FLATBUFFERS_FALLTHROUGH(); // else fall thru
+ default: return "Table";
+ }
+ }
+
+ std::string GenTypeGet(const Type &type) const {
+ return IsScalar(type.base_type)
+ ? GenTypeBasic(type)
+ : (IsArray(type) ? GenTypeGet(type.VectorType())
+ : GenTypePointer(type));
+ }
+
+ // Find the destination type the user wants to receive the value in (e.g.
+ // one size higher signed types for unsigned serialized values in Java).
+ Type DestinationType(const Type &type, bool vectorelem) const {
+ switch (type.base_type) {
+ // We use int for both uchar/ushort, since that generally means less
+ // casting than using short for uchar.
+ case BASE_TYPE_UCHAR: return Type(BASE_TYPE_INT);
+ case BASE_TYPE_USHORT: return Type(BASE_TYPE_INT);
+ case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG);
+ case BASE_TYPE_ARRAY:
+ case BASE_TYPE_VECTOR:
+ if (vectorelem) return DestinationType(type.VectorType(), vectorelem);
+ FLATBUFFERS_FALLTHROUGH(); // else fall thru
+ default: return type;
+ }
+ }
+
+ std::string GenOffsetType() const { return "int"; }
+
+ std::string GenOffsetConstruct(const std::string &variable_name) const {
+ return variable_name;
+ }
+
+ std::string GenVectorOffsetType() const { return "int"; }
+
+ // Generate destination type name
+ std::string GenTypeNameDest(const Type &type) const {
+ return GenTypeGet(DestinationType(type, true));
+ }
+
+ // Mask to turn serialized value into destination type value.
+ std::string DestinationMask(const Type &type, bool vectorelem) const {
+ switch (type.base_type) {
+ case BASE_TYPE_UCHAR: return " & 0xFF";
+ case BASE_TYPE_USHORT: return " & 0xFFFF";
+ case BASE_TYPE_UINT: return " & 0xFFFFFFFFL";
+ case BASE_TYPE_VECTOR:
+ if (vectorelem) return DestinationMask(type.VectorType(), vectorelem);
+ FLATBUFFERS_FALLTHROUGH(); // else fall thru
+ default: return "";
+ }
+ }
+
+ // Casts necessary to correctly read serialized data
+ std::string DestinationCast(const Type &type) const {
+ if (IsSeries(type)) {
+ return DestinationCast(type.VectorType());
+ } else {
+ // Cast necessary to correctly read serialized unsigned values.
+ if (type.base_type == BASE_TYPE_UINT) return "(long)";
+ }
+ return "";
+ }
+
+ // Cast statements for mutator method parameters.
+ // In Java, parameters representing unsigned numbers need to be cast down to
+ // their respective type. For example, a long holding an unsigned int value
+ // would be cast down to int before being put onto the buffer.
+ std::string SourceCast(const Type &type, bool castFromDest) const {
+ if (IsSeries(type)) {
+ return SourceCast(type.VectorType(), castFromDest);
+ } else {
+ if (castFromDest) {
+ if (type.base_type == BASE_TYPE_UINT)
+ return "(int)";
+ else if (type.base_type == BASE_TYPE_USHORT)
+ return "(short)";
+ else if (type.base_type == BASE_TYPE_UCHAR)
+ return "(byte)";
+ }
+ }
+ return "";
+ }
+
+ std::string SourceCast(const Type &type) const {
+ return SourceCast(type, true);
+ }
+
+ std::string SourceCastBasic(const Type &type, bool castFromDest) const {
+ return IsScalar(type.base_type) ? SourceCast(type, castFromDest) : "";
+ }
+
+ std::string SourceCastBasic(const Type &type) const {
+ return SourceCastBasic(type, true);
+ }
+
+ 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 ? (WrapInNameSpace(enum_def) + "." + enum_val->name)
+ : value.constant;
+ }
+
+ std::string GenDefaultValue(const FieldDef &field) const {
+ auto &value = field.value;
+ auto constant = field.IsScalarOptional() ? "0" : value.constant;
+ auto longSuffix = "L";
+ switch (value.type.base_type) {
+ case BASE_TYPE_BOOL: return constant == "0" ? "false" : "true";
+ case BASE_TYPE_ULONG: {
+ // Converts the ulong into its bits signed equivalent
+ uint64_t defaultValue = StringToUInt(constant.c_str());
+ return NumToString(static_cast<int64_t>(defaultValue)) + longSuffix;
+ }
+ case BASE_TYPE_UINT:
+ case BASE_TYPE_LONG: return constant + longSuffix;
+ default:
+ if (IsFloat(value.type.base_type)) {
+ if (field.IsScalarOptional()) {
+ return value.type.base_type == BASE_TYPE_DOUBLE ? "0.0" : "0f";
+ }
+ return JavaFloatGen.GenFloatConstant(field);
+ } else {
+ return constant;
+ }
+ }
+ }
+
+ std::string GenDefaultValueBasic(const FieldDef &field) const {
+ auto &value = field.value;
+ if (!IsScalar(value.type.base_type)) { return "0"; }
+ return GenDefaultValue(field);
+ }
+
+ void GenEnum(EnumDef &enum_def, std::string *code_ptr) const {
+ std::string &code = *code_ptr;
+ if (enum_def.generated) return;
+
+ // Generate enum definitions of the form:
+ // public static (final) int name = value;
+ // In Java, we use ints rather than the Enum feature, because we want them
+ // to map directly to how they're used in C/C++ and file formats.
+ // That, and Java Enums are expensive, and not universally liked.
+ GenComment(enum_def.doc_comment, code_ptr, &comment_config);
+
+ if (enum_def.attributes.Lookup("private")) {
+ // For Java, we leave the enum unmarked to indicate package-private
+ } else {
+ code += "public ";
+ }
+ code += "final class " + enum_def.name;
+ code += " {\n";
+ code += " private " + enum_def.name + "() { }\n";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ GenComment(ev.doc_comment, code_ptr, &comment_config, " ");
+ code += " public static final ";
+ code += GenTypeBasic(DestinationType(enum_def.underlying_type, false));
+ code += " ";
+ code += ev.name + " = ";
+ code += enum_def.ToString(ev);
+ code += ";\n";
+ }
+
+ // 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) {
+ code += "\n public static final String";
+ code += "[] names = { ";
+ auto val = enum_def.Vals().front();
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ auto ev = *it;
+ for (auto k = enum_def.Distance(val, ev); k > 1; --k) code += "\"\", ";
+ val = ev;
+ code += "\"" + (*it)->name + "\", ";
+ }
+ code += "};\n\n";
+ code += " public static ";
+ code += "String";
+ code += " " + MakeCamel("name", false);
+ code += "(int e) { return names[e";
+ if (enum_def.MinValue()->IsNonZero())
+ code += " - " + enum_def.MinValue()->name;
+ code += "]; }\n";
+ }
+
+ // Close the class
+ code += "}\n\n";
+ }
+
+ // Returns the function name that is able to read a value of the given type.
+ std::string GenGetter(const Type &type) 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 GenGetter(type.VectorType());
+ case BASE_TYPE_ARRAY: return GenGetter(type.VectorType());
+ default: {
+ std::string getter = "bb.get";
+ if (type.base_type == BASE_TYPE_BOOL) {
+ getter = "0!=" + getter;
+ } else if (GenTypeBasic(type) != "byte") {
+ getter += MakeCamel(GenTypeBasic(type));
+ }
+ return getter;
+ }
+ }
+ }
+
+ // Returns the function name that is able to read a value of the given type.
+ std::string GenGetterForLookupByKey(flatbuffers::FieldDef *key_field,
+ const std::string &data_buffer,
+ const char *num = nullptr) const {
+ auto type = key_field->value.type;
+ auto dest_mask = DestinationMask(type, true);
+ auto dest_cast = DestinationCast(type);
+ auto getter = data_buffer + ".get";
+ if (GenTypeBasic(type) != "byte") {
+ getter += MakeCamel(GenTypeBasic(type));
+ }
+ getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")" +
+ dest_mask;
+ return getter;
+ }
+
+ // Direct mutation is only allowed for scalar fields.
+ // Hence a setter method will only be generated for such fields.
+ std::string GenSetter(const Type &type) const {
+ if (IsScalar(type.base_type)) {
+ std::string setter = "bb.put";
+ if (GenTypeBasic(type) != "byte" && type.base_type != BASE_TYPE_BOOL) {
+ setter += MakeCamel(GenTypeBasic(type));
+ }
+ return setter;
+ } else {
+ return "";
+ }
+ }
+
+ // Returns the method name for use with add/put calls.
+ std::string GenMethod(const Type &type) const {
+ return IsScalar(type.base_type) ? MakeCamel(GenTypeBasic(type))
+ : (IsStruct(type) ? "Struct" : "Offset");
+ }
+
+ // Recursively generate arguments for a constructor, to deal with nested
+ // structs.
+ void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
+ const char *nameprefix, size_t array_count = 0) const {
+ std::string &code = *code_ptr;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ const auto &field_type = field.value.type;
+ const auto array_field = IsArray(field_type);
+ const auto &type = array_field ? field_type.VectorType()
+ : DestinationType(field_type, false);
+ const auto array_cnt = array_field ? (array_count + 1) : array_count;
+ if (IsStruct(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_type.struct_def, code_ptr,
+ (nameprefix + (field.name + "_")).c_str(), array_cnt);
+ } else {
+ code += ", ";
+ code += GenTypeBasic(type);
+ for (size_t i = 0; i < array_cnt; i++) code += "[]";
+ code += " ";
+ code += nameprefix;
+ code += MakeCamel(field.name, false);
+ }
+ }
+ }
+
+ // Recusively generate struct construction statements of the form:
+ // builder.putType(name);
+ // and insert manual padding.
+ void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
+ const char *nameprefix, size_t index = 0,
+ bool in_array = false) const {
+ std::string &code = *code_ptr;
+ std::string indent((index + 1) * 2, ' ');
+ code += indent + " builder.prep(";
+ code += NumToString(struct_def.minalign) + ", ";
+ code += NumToString(struct_def.bytesize) + ");\n";
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ auto &field = **it;
+ const auto &field_type = field.value.type;
+ if (field.padding) {
+ code += indent + " builder.pad(";
+ code += NumToString(field.padding) + ");\n";
+ }
+ if (IsStruct(field_type)) {
+ GenStructBody(*field_type.struct_def, code_ptr,
+ (nameprefix + (field.name + "_")).c_str(), index,
+ in_array);
+ } else {
+ const auto &type =
+ IsArray(field_type) ? field_type.VectorType() : field_type;
+ const auto index_var = "_idx" + NumToString(index);
+ if (IsArray(field_type)) {
+ code += indent + " for (int " + index_var + " = ";
+ code += NumToString(field_type.fixed_length);
+ code += "; " + index_var + " > 0; " + index_var + "--) {\n";
+ in_array = true;
+ }
+ if (IsStruct(type)) {
+ GenStructBody(*field_type.struct_def, code_ptr,
+ (nameprefix + (field.name + "_")).c_str(), index + 1,
+ in_array);
+ } else {
+ code += IsArray(field_type) ? " " : "";
+ code += indent + " builder.put";
+ code += GenMethod(type) + "(";
+ code += SourceCast(type);
+ auto argname = nameprefix + MakeCamel(field.name, false);
+ code += argname;
+ size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
+ for (size_t i = 0; in_array && i < array_cnt; i++) {
+ code += "[_idx" + NumToString(i) + "-1]";
+ }
+ code += ");\n";
+ }
+ if (IsArray(field_type)) { code += indent + " }\n"; }
+ }
+ }
+ }
+
+ std::string GenByteBufferLength(const char *bb_name) const {
+ std::string bb_len = bb_name;
+ bb_len += ".capacity()";
+ return bb_len;
+ }
+
+ std::string GenOffsetGetter(flatbuffers::FieldDef *key_field,
+ const char *num = nullptr) const {
+ std::string key_offset = "";
+ key_offset += "__offset(" + NumToString(key_field->value.offset) + ", ";
+ if (num) {
+ key_offset += num;
+ key_offset += ", _bb)";
+ } else {
+ key_offset += GenByteBufferLength("bb");
+ key_offset += " - tableOffset, bb)";
+ }
+ return key_offset;
+ }
+
+ std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) const {
+ std::string key_getter = " ";
+ key_getter += "int tableOffset = ";
+ key_getter += "__indirect(vectorLocation + 4 * (start + middle)";
+ key_getter += ", bb);\n ";
+ if (IsString(key_field->value.type)) {
+ key_getter += "int comp = ";
+ key_getter += "compareStrings(";
+ key_getter += GenOffsetGetter(key_field);
+ key_getter += ", byteKey, bb);\n";
+ } else {
+ auto get_val = GenGetterForLookupByKey(key_field, "bb");
+ key_getter += GenTypeNameDest(key_field->value.type) + " val = ";
+ key_getter += get_val + ";\n";
+ key_getter += " int comp = val > key ? 1 : val < key ? -1 : 0;\n";
+ }
+ return key_getter;
+ }
+
+ std::string GenKeyGetter(flatbuffers::FieldDef *key_field) const {
+ std::string key_getter = "";
+ auto data_buffer = "_bb";
+ if (IsString(key_field->value.type)) {
+ key_getter += " return ";
+ key_getter += "";
+ key_getter += "compareStrings(";
+ key_getter += GenOffsetGetter(key_field, "o1") + ", ";
+ key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")";
+ key_getter += ";";
+ } else {
+ auto field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o1");
+ key_getter +=
+ "\n " + GenTypeNameDest(key_field->value.type) + " val_1 = ";
+ key_getter +=
+ field_getter + ";\n " + GenTypeNameDest(key_field->value.type);
+ key_getter += " val_2 = ";
+ field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2");
+ key_getter += field_getter + ";\n";
+ key_getter += " return val_1 > val_2 ? 1 : val_1 < val_2 ? -1 : 0;\n ";
+ }
+ return key_getter;
+ }
+
+ void GenStruct(StructDef &struct_def, std::string *code_ptr) const {
+ if (struct_def.generated) return;
+ std::string &code = *code_ptr;
+
+ // Generate a struct accessor class, with methods of the form:
+ // public type name() { return bb.getType(i + offset); }
+ // or for tables of the form:
+ // public type name() {
+ // int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default;
+ // }
+ GenComment(struct_def.doc_comment, code_ptr, &comment_config);
+
+ if (parser_.opts.gen_generated) {
+ code += "@javax.annotation.Generated(value=\"flatc\")\n";
+ }
+ code += "@SuppressWarnings(\"unused\")\n";
+ if (struct_def.attributes.Lookup("private")) {
+ // For Java, we leave the struct unmarked to indicate package-private
+ } else {
+ code += "public ";
+ }
+ code += "final class " + struct_def.name;
+ code += " extends ";
+ code += struct_def.fixed ? "Struct" : "Table";
+ code += " {\n";
+
+ if (!struct_def.fixed) {
+ // Generate verson check method.
+ // Force compile time error if not using the same version runtime.
+ code += " public static void ValidateVersion() {";
+ code += " Constants.";
+ code += "FLATBUFFERS_2_0_0(); ";
+ code += "}\n";
+
+ // Generate a special accessor for the table that when used as the root
+ // of a FlatBuffer
+ std::string method_name = "getRootAs" + struct_def.name;
+ std::string method_signature =
+ " public static " + struct_def.name + " " + method_name;
+
+ // create convenience method that doesn't require an existing object
+ code += method_signature + "(ByteBuffer _bb) ";
+ code += "{ return " + method_name + "(_bb, new " + struct_def.name +
+ "()); }\n";
+
+ // create method that allows object reuse
+ code +=
+ method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { ";
+ code += "_bb.order(ByteOrder.LITTLE_ENDIAN); ";
+ code += "return (obj.__assign(_bb.getInt(_bb.";
+ code += "position()";
+ code += ") + _bb.";
+ code += "position()";
+ code += ", _bb)); }\n";
+ if (parser_.root_struct_def_ == &struct_def) {
+ if (parser_.file_identifier_.length()) {
+ // Check if a buffer has the identifier.
+ code += " public static ";
+ code += "boolean " + struct_def.name;
+ code += "BufferHasIdentifier(ByteBuffer _bb) { return ";
+ code += "__has_identifier(_bb, \"";
+ code += parser_.file_identifier_;
+ code += "\"); }\n";
+ }
+ }
+ }
+ // Generate the __init method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ code += " public void __init(int _i, ByteBuffer _bb) ";
+ code += "{ ";
+ code += "__reset(_i, _bb); ";
+ code += "}\n";
+ code +=
+ " public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) ";
+ code += "{ __init(_i, _bb); return this; }\n\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ GenComment(field.doc_comment, code_ptr, &comment_config, " ");
+ std::string type_name = GenTypeGet(field.value.type);
+ std::string type_name_dest = GenTypeNameDest(field.value.type);
+ std::string conditional_cast = "";
+ std::string optional = "";
+ std::string dest_mask = DestinationMask(field.value.type, true);
+ std::string dest_cast = DestinationCast(field.value.type);
+ std::string src_cast = SourceCast(field.value.type);
+ std::string method_start =
+ " public " +
+ (field.IsRequired() ? "" : GenNullableAnnotation(field.value.type)) +
+ GenPureAnnotation(field.value.type) + type_name_dest + optional +
+ " " + MakeCamel(field.name, false);
+ std::string obj = "obj";
+
+ // Most field accessors need to retrieve and test the field offset first,
+ // this is the prefix code for that:
+ auto offset_prefix =
+ IsArray(field.value.type)
+ ? " { return "
+ : (" { int o = __offset(" + NumToString(field.value.offset) +
+ "); return o != 0 ? ");
+ // Generate the accessors that don't do object reuse.
+ if (field.value.type.base_type == BASE_TYPE_STRUCT) {
+ // Calls the accessor that takes an accessor object with a new object.
+ code += method_start + "() { return ";
+ code += MakeCamel(field.name, false);
+ code += "(new ";
+ code += type_name + "()); }\n";
+ } else if (IsVector(field.value.type) &&
+ field.value.type.element == BASE_TYPE_STRUCT) {
+ // Accessors for vectors of structs also take accessor objects, this
+ // generates a variant without that argument.
+ code += method_start + "(int j) { return ";
+ code += MakeCamel(field.name, false);
+ code += "(new " + type_name + "(), j); }\n";
+ }
+
+ if (field.IsScalarOptional()) { code += GenOptionalScalarCheck(field); }
+ std::string getter = dest_cast + GenGetter(field.value.type);
+ code += method_start;
+ std::string default_cast = "";
+ std::string member_suffix = "; ";
+ if (IsScalar(field.value.type.base_type)) {
+ code += "()";
+ member_suffix += "";
+ if (struct_def.fixed) {
+ code += " { return " + getter;
+ code += "(bb_pos + ";
+ code += NumToString(field.value.offset) + ")";
+ code += dest_mask;
+ } else {
+ code += offset_prefix + getter;
+ code += "(o + bb_pos)" + dest_mask;
+ code += " : " + default_cast;
+ code += GenDefaultValue(field);
+ }
+ } else {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT:
+ code += "(" + type_name + " obj)";
+ if (struct_def.fixed) {
+ code += " { return " + obj + ".__assign(";
+ code += "bb_pos + " + NumToString(field.value.offset) + ", ";
+ code += "bb)";
+ } else {
+ code += offset_prefix + conditional_cast;
+ code += obj + ".__assign(";
+ code += field.value.type.struct_def->fixed
+ ? "o + bb_pos"
+ : "__indirect(o + bb_pos)";
+ code += ", bb) : null";
+ }
+ break;
+ case BASE_TYPE_STRING:
+ code += "()";
+ member_suffix += "";
+ code += offset_prefix + getter + "(o + ";
+ code += "bb_pos) : null";
+ break;
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ code += "(";
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ code += type_name + " obj, ";
+ getter = obj + ".__assign";
+ } else if (vectortype.base_type == BASE_TYPE_UNION) {
+ code += type_name + " obj, ";
+ }
+ code += "int j)";
+ const auto body = offset_prefix + conditional_cast + getter + "(";
+ if (vectortype.base_type == BASE_TYPE_UNION) {
+ code += body + "obj, ";
+ } else {
+ code += body;
+ }
+ std::string index;
+ if (IsArray(field.value.type)) {
+ index += "bb_pos + " + NumToString(field.value.offset) + " + ";
+ } else {
+ index += "__vector(o) + ";
+ }
+ index += "j * " + NumToString(InlineSize(vectortype));
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ code += vectortype.struct_def->fixed
+ ? index
+ : "__indirect(" + index + ")";
+ code += ", bb";
+ } else {
+ code += index;
+ }
+ code += ")" + dest_mask;
+ if (!IsArray(field.value.type)) {
+ code += " : ";
+ code +=
+ field.value.type.element == BASE_TYPE_BOOL
+ ? "false"
+ : (IsScalar(field.value.type.element) ? default_cast + "0"
+ : "null");
+ }
+
+ break;
+ }
+ case BASE_TYPE_UNION:
+ code += "(" + type_name + " obj)" + offset_prefix + getter;
+ code += "(obj, o + bb_pos) : null";
+ break;
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+ code += member_suffix;
+ code += "}\n";
+ if (IsVector(field.value.type)) {
+ code += " public int " + MakeCamel(field.name, false);
+ code += "Length";
+ code += "()";
+ code += offset_prefix;
+ code += "__vector_len(o) : 0; ";
+ code += "";
+ code += "}\n";
+ // 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 &key_field = **kit;
+ if (key_field.key) {
+ auto qualified_name = WrapInNameSpace(sd);
+ code += " public " + qualified_name + " ";
+ code += MakeCamel(field.name, false) + "ByKey(";
+ code += GenTypeNameDest(key_field.value.type) + " key)";
+ code += offset_prefix;
+ code += qualified_name + ".__lookup_by_key(";
+ code += "null, ";
+ code += "__vector(o), key, ";
+ code += "bb) : null; ";
+ code += "}\n";
+ code += " public " + qualified_name + " ";
+ code += MakeCamel(field.name, false) + "ByKey(";
+ code += qualified_name + " obj, ";
+ code += GenTypeNameDest(key_field.value.type) + " key)";
+ code += offset_prefix;
+ code += qualified_name + ".__lookup_by_key(obj, ";
+ code += "__vector(o), key, ";
+ code += "bb) : null; ";
+ code += "}\n";
+ break;
+ }
+ }
+ }
+ }
+ // Generate the accessors for vector of structs with vector access object
+ if (IsVector(field.value.type)) {
+ std::string vector_type_name;
+ const auto &element_base_type = field.value.type.VectorType().base_type;
+ if (IsScalar(element_base_type)) {
+ vector_type_name = MakeCamel(type_name, true) + "Vector";
+ } else if (element_base_type == BASE_TYPE_STRING) {
+ vector_type_name = "StringVector";
+ } else if (element_base_type == BASE_TYPE_UNION) {
+ vector_type_name = "UnionVector";
+ } else {
+ vector_type_name = type_name + ".Vector";
+ }
+ auto vector_method_start = GenNullableAnnotation(field.value.type) +
+ " public " + vector_type_name + optional +
+ " " + MakeCamel(field.name, false) +
+ "Vector";
+ code += vector_method_start + "() { return ";
+ code += MakeCamel(field.name, false) + "Vector";
+ code += "(new " + vector_type_name + "()); }\n";
+ code += vector_method_start + "(" + vector_type_name + " obj)";
+ code += offset_prefix + conditional_cast + obj + ".__assign(";
+ code += "__vector(o), ";
+ if (!IsScalar(element_base_type)) {
+ auto vectortype = field.value.type.VectorType();
+ code += NumToString(InlineSize(vectortype)) + ", ";
+ }
+ code += "bb) : null" + member_suffix + "}\n";
+ }
+ // Generate a ByteBuffer accessor for strings & vectors of scalars.
+ if ((IsVector(field.value.type) &&
+ IsScalar(field.value.type.VectorType().base_type)) ||
+ IsString(field.value.type)) {
+ code += " public ByteBuffer ";
+ code += MakeCamel(field.name, false);
+ code += "AsByteBuffer() { return ";
+ code += "__vector_as_bytebuffer(";
+ code += NumToString(field.value.offset) + ", ";
+ code += NumToString(IsString(field.value.type)
+ ? 1
+ : InlineSize(field.value.type.VectorType()));
+ code += "); }\n";
+ code += " public ByteBuffer ";
+ code += MakeCamel(field.name, false);
+ code += "InByteBuffer(ByteBuffer _bb) { return ";
+ code += "__vector_in_bytebuffer(_bb, ";
+ code += NumToString(field.value.offset) + ", ";
+ code += NumToString(IsString(field.value.type)
+ ? 1
+ : InlineSize(field.value.type.VectorType()));
+ code += "); }\n";
+ }
+ // generate object accessors if is nested_flatbuffer
+ if (field.nested_flatbuffer) {
+ auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
+ auto nested_method_name =
+ MakeCamel(field.name, false) + "As" + field.nested_flatbuffer->name;
+ auto get_nested_method_name = nested_method_name;
+ code += " public " + nested_type_name + " ";
+ code += nested_method_name + "() { return ";
+ code +=
+ get_nested_method_name + "(new " + nested_type_name + "()); }\n";
+ code += " public " + nested_type_name + " ";
+ code += get_nested_method_name + "(";
+ code += nested_type_name + " obj";
+ code += ") { int o = __offset(";
+ code += NumToString(field.value.offset) + "); ";
+ code += "return o != 0 ? " + conditional_cast + obj + ".__assign(";
+ code += "";
+ code += "__indirect(__vector(o)), ";
+ code += "bb) : null; }\n";
+ }
+ // Generate mutators for scalar fields or vectors of scalars.
+ if (parser_.opts.mutable_buffer) {
+ auto is_series = (IsSeries(field.value.type));
+ const auto &underlying_type =
+ is_series ? field.value.type.VectorType() : field.value.type;
+ // Boolean parameters have to be explicitly converted to byte
+ // representation.
+ auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL
+ ? "(byte)(" + field.name + " ? 1 : 0)"
+ : field.name;
+ auto mutator_prefix = MakeCamel("mutate", false);
+ // A vector mutator also needs the index of the vector element it should
+ // mutate.
+ auto mutator_params = (is_series ? "(int j, " : "(") +
+ GenTypeNameDest(underlying_type) + " " +
+ field.name + ") { ";
+ auto setter_index =
+ is_series
+ ? (IsArray(field.value.type)
+ ? "bb_pos + " + NumToString(field.value.offset)
+ : "__vector(o)") +
+ +" + j * " + NumToString(InlineSize(underlying_type))
+ : (struct_def.fixed
+ ? "bb_pos + " + NumToString(field.value.offset)
+ : "o + bb_pos");
+ if (IsScalar(underlying_type.base_type) && !IsUnion(field.value.type)) {
+ code += " public ";
+ code += struct_def.fixed ? "void " : "boolean ";
+ code += mutator_prefix + MakeCamel(field.name, true);
+ code += mutator_params;
+ if (struct_def.fixed) {
+ code += GenSetter(underlying_type) + "(" + setter_index + ", ";
+ code += src_cast + setter_parameter + "); }\n";
+ } else {
+ code += "int o = __offset(";
+ code += NumToString(field.value.offset) + ");";
+ code += " if (o != 0) { " + GenSetter(underlying_type);
+ code += "(" + setter_index + ", " + src_cast + setter_parameter +
+ "); return true; } else { return false; } }\n";
+ }
+ }
+ }
+ if (parser_.opts.java_primitive_has_method &&
+ IsScalar(field.value.type.base_type) && !struct_def.fixed) {
+ auto vt_offset_constant = " public static final int VT_" +
+ MakeScreamingCamel(field.name) + " = " +
+ NumToString(field.value.offset) + ";";
+
+ code += vt_offset_constant;
+ code += "\n";
+ }
+ }
+ code += "\n";
+ flatbuffers::FieldDef *key_field = nullptr;
+ if (struct_def.fixed) {
+ // create a struct constructor function
+ code += " public static " + GenOffsetType() + " ";
+ code += "create";
+ code += struct_def.name + "(FlatBufferBuilder builder";
+ GenStructArgs(struct_def, code_ptr, "");
+ code += ") {\n";
+ GenStructBody(struct_def, code_ptr, "");
+ code += " return ";
+ code += GenOffsetConstruct("builder." + std::string("offset()"));
+ code += ";\n }\n";
+ } else {
+ // 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;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.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...)
+ code += " public static " + GenOffsetType() + " ";
+ code += "create" + struct_def.name;
+ code += "(FlatBufferBuilder builder";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ code += ",\n ";
+ code += GenTypeBasic(DestinationType(field.value.type, false));
+ code += " ";
+ code += field.name;
+ if (!IsScalar(field.value.type.base_type)) code += "Offset";
+ }
+ code += ") {\n builder.";
+ code += "startTable(";
+ code += NumToString(struct_def.fields.vec.size()) + ");\n";
+ for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
+ size; size /= 2) {
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ auto &field = **it;
+ if (!field.deprecated &&
+ (!struct_def.sortbysize ||
+ size == SizeOf(field.value.type.base_type))) {
+ code += " " + struct_def.name + ".";
+ code += "add";
+ code += MakeCamel(field.name) + "(builder, " + field.name;
+ if (!IsScalar(field.value.type.base_type)) code += "Offset";
+ code += ");\n";
+ }
+ }
+ }
+ code += " return " + struct_def.name + ".";
+ code += "end" + struct_def.name;
+ code += "(builder);\n }\n\n";
+ }
+ // Generate a set of static methods that allow table construction,
+ // of the form:
+ // public static void addName(FlatBufferBuilder builder, short name)
+ // { builder.addShort(id, name, default); }
+ // Unlike the Create function, these always work.
+ code += " public static void start";
+ code += struct_def.name;
+ code += "(FlatBufferBuilder builder) { builder.";
+ code += "startTable(";
+ code += NumToString(struct_def.fields.vec.size()) + "); }\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ if (field.key) key_field = &field;
+ code += " public static void add";
+ code += MakeCamel(field.name);
+ code += "(FlatBufferBuilder builder, ";
+ code += GenTypeBasic(DestinationType(field.value.type, false));
+ auto argname = MakeCamel(field.name, false);
+ if (!IsScalar(field.value.type.base_type)) argname += "Offset";
+ code += " " + argname + ") { builder.add";
+ code += GenMethod(field.value.type) + "(";
+ code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
+ code += SourceCastBasic(field.value.type);
+ code += argname;
+ code += ", ";
+ code += SourceCastBasic(field.value.type);
+ code += GenDefaultValue(field);
+ code += "); }\n";
+ if (IsVector(field.value.type)) {
+ auto vector_type = field.value.type.VectorType();
+ auto alignment = InlineAlignment(vector_type);
+ auto elem_size = InlineSize(vector_type);
+ if (!IsStruct(vector_type)) {
+ // generate a method to create a vector from a java array.
+ if ((vector_type.base_type == BASE_TYPE_CHAR ||
+ vector_type.base_type == BASE_TYPE_UCHAR)) {
+ // Handle byte[] and ByteBuffers separately for Java
+ code += " public static " + GenVectorOffsetType() + " ";
+ code += "create";
+ code += MakeCamel(field.name);
+ code += "Vector(FlatBufferBuilder builder, byte[] data) ";
+ code += "{ return builder.createByteVector(data); }\n";
+
+ code += " public static " + GenVectorOffsetType() + " ";
+ code += "create";
+ code += MakeCamel(field.name);
+ code += "Vector(FlatBufferBuilder builder, ByteBuffer data) ";
+ code += "{ return builder.createByteVector(data); }\n";
+ } else {
+ code += " public static " + GenVectorOffsetType() + " ";
+ code += "create";
+ code += MakeCamel(field.name);
+ code += "Vector(FlatBufferBuilder builder, ";
+ code += GenTypeBasic(vector_type) + "[] data) ";
+ code += "{ builder.startVector(";
+ code += NumToString(elem_size);
+ code += ", data.length, ";
+ code += NumToString(alignment);
+ code += "); for (int i = data.";
+ code += "length - 1; i >= 0; i--) builder.";
+ code += "add";
+ code += GenMethod(vector_type);
+ code += "(";
+ code += SourceCastBasic(vector_type, false);
+ code += "data[i]";
+ code += "); return ";
+ code += "builder.endVector(); }\n";
+ }
+ }
+ // Generate a method to start a vector, data to be added manually
+ // after.
+ code += " public static void start";
+ code += MakeCamel(field.name);
+ code += "Vector(FlatBufferBuilder builder, int numElems) ";
+ code += "{ builder.startVector(";
+ code += NumToString(elem_size);
+ code += ", numElems, " + NumToString(alignment);
+ code += "); }\n";
+ }
+ }
+ code += " public static " + GenOffsetType() + " ";
+ code += "end" + struct_def.name;
+ code += "(FlatBufferBuilder builder) {\n int o = builder.";
+ code += "endTable();\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (!field.deprecated && field.IsRequired()) {
+ code += " builder.required(o, ";
+ code += NumToString(field.value.offset);
+ code += "); // " + field.name + "\n";
+ }
+ }
+ code += " return " + GenOffsetConstruct("o") + ";\n }\n";
+ if (parser_.root_struct_def_ == &struct_def) {
+ std::string size_prefix[] = { "", "SizePrefixed" };
+ for (int i = 0; i < 2; ++i) {
+ code += " public static void ";
+ code += "finish" + size_prefix[i] + struct_def.name;
+ code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType();
+ code += " offset) {";
+ code += " builder.finish" + size_prefix[i] + "(offset";
+
+ if (parser_.file_identifier_.length())
+ code += ", \"" + parser_.file_identifier_ + "\"";
+ code += "); }\n";
+ }
+ }
+ }
+ // Only generate key compare function for table,
+ // because `key_field` is not set for struct
+ if (struct_def.has_key && !struct_def.fixed) {
+ FLATBUFFERS_ASSERT(key_field);
+ code += "\n @Override\n protected int keysCompare(";
+ code += "Integer o1, Integer o2, ByteBuffer _bb) {";
+ code += GenKeyGetter(key_field);
+ code += " }\n";
+
+ code += "\n public static " + struct_def.name;
+ code += " __lookup_by_key(";
+ code += struct_def.name + " obj, ";
+ code += "int vectorLocation, ";
+ code += GenTypeNameDest(key_field->value.type);
+ code += " key, ByteBuffer bb) {\n";
+ if (IsString(key_field->value.type)) {
+ code += " byte[] byteKey = ";
+ code += "key.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n";
+ }
+ code += " int span = ";
+ code += "bb.getInt(vectorLocation - 4);\n";
+ code += " int start = 0;\n";
+ code += " while (span != 0) {\n";
+ code += " int middle = span / 2;\n";
+ code += GenLookupKeyGetter(key_field);
+ code += " if (comp > 0) {\n";
+ code += " span = middle;\n";
+ code += " } else if (comp < 0) {\n";
+ code += " middle++;\n";
+ code += " start += middle;\n";
+ code += " span -= middle;\n";
+ code += " } else {\n";
+ code += " return ";
+ code += "(obj == null ? new " + struct_def.name + "() : obj)";
+ code += ".__assign(tableOffset, bb);\n";
+ code += " }\n }\n";
+ code += " return null;\n";
+ code += " }\n";
+ }
+ GenVectorAccessObject(struct_def, code_ptr);
+ code += "}";
+ code += "\n\n";
+ }
+
+ std::string GenOptionalScalarCheck(FieldDef &field) const {
+ if (!field.IsScalarOptional()) return "";
+ return " public boolean has" + MakeCamel(field.name, true) +
+ "() { return 0 != __offset(" + NumToString(field.value.offset) +
+ "); }\n";
+ }
+
+ void GenVectorAccessObject(StructDef &struct_def,
+ std::string *code_ptr) const {
+ auto &code = *code_ptr;
+ // Generate a vector of structs accessor class.
+ code += "\n";
+ code += " ";
+ if (!struct_def.attributes.Lookup("private")) code += "public ";
+ code += "static ";
+ code += "final ";
+ code += "class Vector extends ";
+ code += "BaseVector {\n";
+
+ // Generate the __assign method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ std::string method_indent = " ";
+ code += method_indent + "public Vector ";
+ code += "__assign(int _vector, int _element_size, ByteBuffer _bb) { ";
+ code += "__reset(_vector, _element_size, _bb); return this; }\n\n";
+
+ auto type_name = struct_def.name;
+ auto method_start = method_indent + "public " + type_name + " get";
+ // Generate the accessors that don't do object reuse.
+ code += method_start + "(int j) { return get";
+ code += "(new " + type_name + "(), j); }\n";
+ code += method_start + "(" + type_name + " obj, int j) { ";
+ code += " return obj.__assign(";
+ std::string index = "__element(j)";
+ code += struct_def.fixed ? index : "__indirect(" + index + ", bb)";
+ code += ", bb); }\n";
+ // See if we should generate a by-key accessor.
+ if (!struct_def.fixed) {
+ auto &fields = struct_def.fields.vec;
+ for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
+ auto &key_field = **kit;
+ if (key_field.key) {
+ auto nullable_annotation =
+ parser_.opts.gen_nullable ? "@Nullable " : "";
+ code += method_indent + nullable_annotation;
+ code += "public " + type_name + " ";
+ code += "getByKey(";
+ code += GenTypeNameDest(key_field.value.type) + " key) { ";
+ code += " return __lookup_by_key(null, ";
+ code += "__vector(), key, ";
+ code += "bb); ";
+ code += "}\n";
+ code += method_indent + nullable_annotation;
+ code += "public " + type_name + " ";
+ code += "getByKey(";
+ code += type_name + " obj, ";
+ code += GenTypeNameDest(key_field.value.type) + " key) { ";
+ code += " return __lookup_by_key(obj, ";
+ code += "__vector(), key, ";
+ code += "bb); ";
+ code += "}\n";
+ break;
+ }
+ }
+ }
+ code += " }\n";
+ }
+
+ // This tracks the current namespace used to determine if a type need to be
+ // prefixed by its namespace
+ const Namespace *cur_name_space_;
+};
+} // namespace java
+
+bool GenerateJava(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ java::JavaGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp b/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp
new file mode 100644
index 0000000000..d58bb84976
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_json_schema.cpp
@@ -0,0 +1,292 @@
+/*
+ * 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.
+ */
+
+#include <iostream>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+namespace jsons {
+
+template<class T> std::string GenFullName(const T *enum_def) {
+ std::string full_name;
+ const auto &name_spaces = enum_def->defined_namespace->components;
+ for (auto ns = name_spaces.cbegin(); ns != name_spaces.cend(); ++ns) {
+ full_name.append(*ns + "_");
+ }
+ full_name.append(enum_def->name);
+ return full_name;
+}
+
+template<class T> std::string GenTypeRef(const T *enum_def) {
+ return "\"$ref\" : \"#/definitions/" + GenFullName(enum_def) + "\"";
+}
+
+std::string GenType(const std::string &name) {
+ return "\"type\" : \"" + name + "\"";
+}
+
+std::string GenType(BaseType type) {
+ switch (type) {
+ case BASE_TYPE_BOOL: return "\"type\" : \"boolean\"";
+ case BASE_TYPE_CHAR:
+ return "\"type\" : \"integer\", \"minimum\" : " +
+ NumToString(std::numeric_limits<int8_t>::min()) +
+ ", \"maximum\" : " +
+ NumToString(std::numeric_limits<int8_t>::max());
+ case BASE_TYPE_UCHAR:
+ return "\"type\" : \"integer\", \"minimum\" : 0, \"maximum\" :" +
+ NumToString(std::numeric_limits<uint8_t>::max());
+ case BASE_TYPE_SHORT:
+ return "\"type\" : \"integer\", \"minimum\" : " +
+ NumToString(std::numeric_limits<int16_t>::min()) +
+ ", \"maximum\" : " +
+ NumToString(std::numeric_limits<int16_t>::max());
+ case BASE_TYPE_USHORT:
+ return "\"type\" : \"integer\", \"minimum\" : 0, \"maximum\" : " +
+ NumToString(std::numeric_limits<uint16_t>::max());
+ case BASE_TYPE_INT:
+ return "\"type\" : \"integer\", \"minimum\" : " +
+ NumToString(std::numeric_limits<int32_t>::min()) +
+ ", \"maximum\" : " +
+ NumToString(std::numeric_limits<int32_t>::max());
+ case BASE_TYPE_UINT:
+ return "\"type\" : \"integer\", \"minimum\" : 0, \"maximum\" : " +
+ NumToString(std::numeric_limits<uint32_t>::max());
+ case BASE_TYPE_LONG:
+ return "\"type\" : \"integer\", \"minimum\" : " +
+ NumToString(std::numeric_limits<int64_t>::min()) +
+ ", \"maximum\" : " +
+ NumToString(std::numeric_limits<int64_t>::max());
+ case BASE_TYPE_ULONG:
+ return "\"type\" : \"integer\", \"minimum\" : 0, \"maximum\" : " +
+ NumToString(std::numeric_limits<uint64_t>::max());
+ case BASE_TYPE_FLOAT:
+ case BASE_TYPE_DOUBLE: return "\"type\" : \"number\"";
+ case BASE_TYPE_STRING: return "\"type\" : \"string\"";
+ default: return "";
+ }
+}
+
+std::string GenBaseType(const Type &type) {
+ if (type.struct_def != nullptr) { return GenTypeRef(type.struct_def); }
+ if (type.enum_def != nullptr) { return GenTypeRef(type.enum_def); }
+ return GenType(type.base_type);
+}
+
+std::string GenArrayType(const Type &type) {
+ std::string element_type;
+ if (type.struct_def != nullptr) {
+ element_type = GenTypeRef(type.struct_def);
+ } else if (type.enum_def != nullptr) {
+ element_type = GenTypeRef(type.enum_def);
+ } else {
+ element_type = GenType(type.element);
+ }
+
+ return "\"type\" : \"array\", \"items\" : {" + element_type + "}";
+}
+
+std::string GenType(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_VECTOR: {
+ return GenArrayType(type);
+ }
+ case BASE_TYPE_STRUCT: {
+ return GenTypeRef(type.struct_def);
+ }
+ case BASE_TYPE_UNION: {
+ std::string union_type_string("\"anyOf\": [");
+ const auto &union_types = type.enum_def->Vals();
+ for (auto ut = union_types.cbegin(); ut < union_types.cend(); ++ut) {
+ const auto &union_type = *ut;
+ if (union_type->union_type.base_type == BASE_TYPE_NONE) { continue; }
+ if (union_type->union_type.base_type == BASE_TYPE_STRUCT) {
+ union_type_string.append(
+ "{ " + GenTypeRef(union_type->union_type.struct_def) + " }");
+ }
+ if (union_type != *type.enum_def->Vals().rbegin()) {
+ union_type_string.append(",");
+ }
+ }
+ union_type_string.append("]");
+ return union_type_string;
+ }
+ case BASE_TYPE_UTYPE: return GenTypeRef(type.enum_def);
+ default: {
+ return GenBaseType(type);
+ }
+ }
+}
+
+class JsonSchemaGenerator : public BaseGenerator {
+ private:
+ std::string code_;
+
+ public:
+ JsonSchemaGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", "", "json") {}
+
+ explicit JsonSchemaGenerator(const BaseGenerator &base_generator)
+ : BaseGenerator(base_generator) {}
+
+ std::string GeneratedFileName(const std::string &path,
+ const std::string &file_name,
+ const IDLOptions &options /* unused */) const {
+ (void)options;
+ return path + file_name + ".schema.json";
+ }
+
+ // If indentation is less than 0, that indicates we don't want any newlines
+ // either.
+ std::string NewLine() const {
+ return parser_.opts.indent_step >= 0 ? "\n" : "";
+ }
+
+ std::string Indent(int indent) const {
+ const auto num_spaces = indent * std::max(parser_.opts.indent_step, 0);
+ return std::string(num_spaces, ' ');
+ }
+
+ bool generate() {
+ code_ = "";
+ if (parser_.root_struct_def_ == nullptr) { return false; }
+ code_ += "{" + NewLine();
+ code_ += Indent(1) +
+ "\"$schema\": \"https://json-schema.org/draft/2019-09/schema\"," +
+ NewLine();
+ code_ += Indent(1) + "\"definitions\": {" + NewLine();
+ for (auto e = parser_.enums_.vec.cbegin(); e != parser_.enums_.vec.cend();
+ ++e) {
+ code_ += Indent(2) + "\"" + GenFullName(*e) + "\" : {" + NewLine();
+ code_ += Indent(3) + GenType("string") + "," + NewLine();
+ auto enumdef(Indent(3) + "\"enum\": [");
+ for (auto enum_value = (*e)->Vals().begin();
+ enum_value != (*e)->Vals().end(); ++enum_value) {
+ enumdef.append("\"" + (*enum_value)->name + "\"");
+ if (*enum_value != (*e)->Vals().back()) { enumdef.append(", "); }
+ }
+ enumdef.append("]");
+ code_ += enumdef + NewLine();
+ code_ += Indent(2) + "}," + NewLine(); // close type
+ }
+ for (auto s = parser_.structs_.vec.cbegin();
+ s != parser_.structs_.vec.cend(); ++s) {
+ const auto &structure = *s;
+ code_ += Indent(2) + "\"" + GenFullName(structure) + "\" : {" + NewLine();
+ code_ += Indent(3) + GenType("object") + "," + NewLine();
+ std::string comment;
+ const auto &comment_lines = structure->doc_comment;
+ for (auto comment_line = comment_lines.cbegin();
+ comment_line != comment_lines.cend(); ++comment_line) {
+ comment.append(*comment_line);
+ }
+ if (!comment.empty()) {
+ std::string description;
+ if (!EscapeString(comment.c_str(), comment.length(), &description, true,
+ true)) {
+ return false;
+ }
+ code_ +=
+ Indent(3) + "\"description\" : " + description + "," + NewLine();
+ }
+ code_ += Indent(3) + "\"properties\" : {" + NewLine();
+
+ const auto &properties = structure->fields.vec;
+ for (auto prop = properties.cbegin(); prop != properties.cend(); ++prop) {
+ const auto &property = *prop;
+ std::string arrayInfo = "";
+ if (IsArray(property->value.type)) {
+ arrayInfo = "," + NewLine() + Indent(8) + "\"minItems\": " +
+ NumToString(property->value.type.fixed_length) + "," +
+ NewLine() + Indent(8) + "\"maxItems\": " +
+ NumToString(property->value.type.fixed_length);
+ }
+ std::string deprecated_info = "";
+ if (property->deprecated) {
+ deprecated_info =
+ "," + NewLine() + Indent(8) + "\"deprecated\" : true,";
+ }
+ std::string typeLine = Indent(4) + "\"" + property->name + "\"";
+ typeLine += " : {" + NewLine() + Indent(8);
+ typeLine += GenType(property->value.type);
+ typeLine += arrayInfo;
+ typeLine += deprecated_info;
+ typeLine += NewLine() + Indent(7) + "}";
+ if (property != properties.back()) { typeLine.append(","); }
+ code_ += typeLine + NewLine();
+ }
+ code_ += Indent(3) + "}," + NewLine(); // close properties
+
+ std::vector<FieldDef *> requiredProperties;
+ std::copy_if(properties.begin(), properties.end(),
+ back_inserter(requiredProperties),
+ [](FieldDef const *prop) { return prop->IsRequired(); });
+ if (!requiredProperties.empty()) {
+ auto required_string(Indent(3) + "\"required\" : [");
+ for (auto req_prop = requiredProperties.cbegin();
+ req_prop != requiredProperties.cend(); ++req_prop) {
+ required_string.append("\"" + (*req_prop)->name + "\"");
+ if (*req_prop != requiredProperties.back()) {
+ required_string.append(", ");
+ }
+ }
+ required_string.append("],");
+ code_ += required_string + NewLine();
+ }
+ code_ += Indent(3) + "\"additionalProperties\" : false" + NewLine();
+ auto closeType(Indent(2) + "}");
+ if (*s != parser_.structs_.vec.back()) { closeType.append(","); }
+ code_ += closeType + NewLine(); // close type
+ }
+ code_ += Indent(1) + "}," + NewLine(); // close definitions
+
+ // mark root type
+ code_ += Indent(1) + "\"$ref\" : \"#/definitions/" +
+ GenFullName(parser_.root_struct_def_) + "\"" + NewLine();
+
+ code_ += "}" + NewLine(); // close schema root
+ return true;
+ }
+
+ bool save() const {
+ const auto file_path = GeneratedFileName(path_, file_name_, parser_.opts);
+ return SaveFile(file_path.c_str(), code_, false);
+ }
+
+ const std::string getJson() { return code_; }
+};
+} // namespace jsons
+
+bool GenerateJsonSchema(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ jsons::JsonSchemaGenerator generator(parser, path, file_name);
+ if (!generator.generate()) { return false; }
+ return generator.save();
+}
+
+bool GenerateJsonSchema(const Parser &parser, std::string *json) {
+ jsons::JsonSchemaGenerator generator(parser, "", "");
+ if (!generator.generate()) { return false; }
+ *json = generator.getJson();
+ return true;
+}
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp b/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp
new file mode 100644
index 0000000000..fb4ce87a67
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_kotlin.cpp
@@ -0,0 +1,1527 @@
+/*
+ * 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/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+#if defined(FLATBUFFERS_CPP98_STL)
+# include <cctype>
+#endif // defined(FLATBUFFERS_CPP98_STL)
+
+namespace flatbuffers {
+
+namespace kotlin {
+
+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 const char *keywords[] = {
+ "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"
+};
+
+// Escape Keywords
+static std::string Esc(const std::string &name) {
+ for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) {
+ if (name == keywords[i]) { return MakeCamel(name + "_", false); }
+ }
+
+ return MakeCamel(name, false);
+}
+
+class KotlinGenerator : public BaseGenerator {
+ public:
+ KotlinGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", ".", "kt"),
+ cur_name_space_(nullptr) {}
+
+ KotlinGenerator &operator=(const KotlinGenerator &);
+ bool generate() FLATBUFFERS_OVERRIDE {
+ std::string one_file_code;
+
+ cur_name_space_ = parser_.current_namespace_;
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ CodeWriter enumWriter(ident_pad);
+ auto &enum_def = **it;
+ if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace;
+ GenEnum(enum_def, enumWriter);
+ if (parser_.opts.one_file) {
+ one_file_code += enumWriter.ToString();
+ } else {
+ if (!SaveType(enum_def.name, *enum_def.defined_namespace,
+ enumWriter.ToString(), false))
+ return false;
+ }
+ }
+
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ CodeWriter structWriter(ident_pad);
+ auto &struct_def = **it;
+ if (!parser_.opts.one_file)
+ cur_name_space_ = struct_def.defined_namespace;
+ GenStruct(struct_def, structWriter, parser_.opts);
+ if (parser_.opts.one_file) {
+ one_file_code += structWriter.ToString();
+ } else {
+ if (!SaveType(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;
+ }
+
+ // 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";
+
+ std::string namespace_name = FullNamespace(".", ns);
+ if (!namespace_name.empty()) {
+ code += "package " + namespace_name;
+ code += "\n\n";
+ }
+ if (needs_includes) {
+ code += "import java.nio.*\n";
+ code += "import kotlin.math.sign\n";
+ code += "import com.google.flatbuffers.*\n\n";
+ }
+ code += classcode;
+ auto filename = NamespaceDir(ns) + defname + ".kt";
+ return SaveFile(filename.c_str(), code, false);
+ }
+
+ const Namespace *CurrentNameSpace() const FLATBUFFERS_OVERRIDE {
+ return cur_name_space_;
+ }
+
+ static bool IsEnum(const Type &type) {
+ return type.enum_def != nullptr && IsInteger(type.base_type);
+ }
+
+ static std::string GenTypeBasic(const BaseType &type) {
+ // clang-format off
+ static const char * const kotlin_typename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
+ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE, ...) \
+ #KTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+ return kotlin_typename[type];
+ }
+
+ 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 WrapInNameSpace(*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) ? GenTypeBasic(type.base_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 ? (WrapInNameSpace(enum_def) + "." + enum_val->name)
+ : value.constant;
+ }
+
+ // Generate default values to compare against a default value when
+ // `force_defaults` is `false`.
+ // Main differences are:
+ // - Floats are upcasted to doubles
+ // - Unsigned are casted to signed
+ std::string GenFBBDefaultValue(const FieldDef &field) const {
+ if (field.IsScalarOptional()) {
+ // although default value is null, java API forces us to present a real
+ // default value for scalars, while adding a field to the buffer. This is
+ // not a problem because the default can be representing just by not
+ // calling builder.addMyField()
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_DOUBLE:
+ case BASE_TYPE_FLOAT: return "0.0";
+ case BASE_TYPE_BOOL: return "false";
+ default: return "0";
+ }
+ }
+ auto out = GenDefaultValue(field, true);
+ // All FlatBufferBuilder default floating point values are doubles
+ if (field.value.type.base_type == BASE_TYPE_FLOAT) {
+ if (out.find("Float") != std::string::npos) {
+ out.replace(0, 5, "Double");
+ }
+ }
+ // Guarantee all values are doubles
+ if (out.back() == 'f') out.pop_back();
+ return out;
+ }
+
+ // FlatBufferBuilder only store signed types, so this function
+ // returns a cast for unsigned values
+ std::string GenFBBValueCast(const FieldDef &field) const {
+ if (IsUnsigned(field.value.type.base_type)) {
+ return CastToSigned(field.value.type);
+ }
+ return "";
+ }
+
+ std::string GenDefaultValue(const FieldDef &field,
+ bool force_signed = false) const {
+ auto &value = field.value;
+ auto base_type = field.value.type.base_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";
+ }
+
+ std::string suffix = "";
+
+ if (base_type == BASE_TYPE_LONG || !force_signed) {
+ suffix = LiteralSuffix(base_type);
+ }
+ 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);
+
+ writer += "@Suppress(\"unused\")";
+ writer += "@ExperimentalUnsignedTypes";
+ writer += "class " + Esc(enum_def.name) + " private constructor() {";
+ 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 field_type = GenTypeBasic(enum_def.underlying_type.base_type);
+ auto val = enum_def.ToString(ev);
+ auto suffix = LiteralSuffix(enum_def.underlying_type.base_type);
+ writer.SetValue("name", Esc(ev.name));
+ writer.SetValue("type", field_type);
+ writer.SetValue("val", val + suffix);
+ GenerateComment(ev.doc_comment, writer, &comment_config);
+ writer += "const 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 += ")";
+ });
+ GenerateFunOneLine(
+ writer, "name", "e: Int", "String",
+ [&]() {
+ writer += "names[e\\";
+ if (enum_def.MinValue()->IsNonZero())
+ writer += " - " + enum_def.MinValue()->name + ".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:
+ case BASE_TYPE_UINT: return bb_var_name + ".getInt";
+ case BASE_TYPE_SHORT:
+ case BASE_TYPE_USHORT: return bb_var_name + ".getShort";
+ case BASE_TYPE_ULONG:
+ 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_CHAR:
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_NONE:
+ case BASE_TYPE_UTYPE: return bb_var_name + ".get";
+ case BASE_TYPE_BOOL: return "0.toByte() != " + bb_var_name + ".get";
+ default:
+ return bb_var_name + ".get" + MakeCamel(GenTypeBasic(type.base_type));
+ }
+ }
+
+ std::string ByteBufferSetter(const Type &type) const {
+ if (IsScalar(type.base_type)) {
+ switch (type.base_type) {
+ case BASE_TYPE_INT:
+ case BASE_TYPE_UINT: return "bb.putInt";
+ case BASE_TYPE_SHORT:
+ case BASE_TYPE_USHORT: return "bb.putShort";
+ case BASE_TYPE_ULONG:
+ case BASE_TYPE_LONG: return "bb.putLong";
+ case BASE_TYPE_FLOAT: return "bb.putFloat";
+ case BASE_TYPE_DOUBLE: return "bb.putDouble";
+ case BASE_TYPE_CHAR:
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_BOOL:
+ case BASE_TYPE_NONE:
+ case BASE_TYPE_UTYPE: return "bb.put";
+ default: return "bb.put" + MakeCamel(GenTypeBasic(type.base_type));
+ }
+ }
+ return "";
+ }
+
+ // 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 IsScalar(type.base_type) ? ToSignedType(type)
+ : (IsStruct(type) ? "Struct" : "Offset");
+ }
+
+ // Recursively generate arguments for a constructor, to deal with nested
+ // structs.
+ static void GenStructArgs(const StructDef &struct_def, CodeWriter &writer,
+ const char *nameprefix) {
+ 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 += MakeCamel(field.name) + ": \\";
+ writer += GenTypeBasic(field.value.type.base_type) + "\\";
+ }
+ }
+ }
+
+ // Recusively generate struct construction statements of the form:
+ // builder.putType(name);
+ // and insert manual padding.
+ static void GenStructBody(const StructDef &struct_def, CodeWriter &writer,
+ const char *nameprefix) {
+ 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 {
+ writer.SetValue("type", GenMethod(field.value.type));
+ writer.SetValue("argname", nameprefix + MakeCamel(field.name, false));
+ writer.SetValue("cast", CastToSigned(field.value.type));
+ writer += "builder.put{{type}}({{argname}}{{cast}})";
+ }
+ }
+ }
+
+ std::string GenByteBufferLength(const char *bb_name) const {
+ std::string bb_len = bb_name;
+ bb_len += ".capacity()";
+ return bb_len;
+ }
+
+ 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 += ", _bb)";
+ } else {
+ key_offset += GenByteBufferLength("bb");
+ key_offset += " - tableOffset, bb)";
+ }
+ return key_offset;
+ }
+
+ 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", Esc(struct_def.name));
+ writer.SetValue("superclass", fixed ? "Struct" : "Table");
+
+ writer += "@Suppress(\"unused\")";
+ writer += "@ExperimentalUnsignedTypes";
+ writer += "class {{struct_name}} : {{superclass}}() {\n";
+
+ writer.IncrementIdentLevel();
+
+ {
+ // Generate the __init() method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ GenerateFun(writer, "__init", "_i: Int, _bb: ByteBuffer", "",
+ [&]() { writer += "__reset(_i, _bb)"; });
+
+ // Generate assign method
+ GenerateFun(writer, "__assign", "_i: Int, _bb: ByteBuffer",
+ Esc(struct_def.name), [&]() {
+ writer += "__init(_i, _bb)";
+ writer += "return this";
+ });
+
+ // Generate all getters
+ GenerateStructGetters(struct_def, writer);
+
+ // Generate Static Fields
+ GenerateCompanionObject(writer, [&]() {
+ if (!struct_def.fixed) {
+ FieldDef *key_field = nullptr;
+
+ // Generate verson check method.
+ // Force compile time error if not using the same version
+ // runtime.
+ GenerateFunOneLine(
+ writer, "validateVersion", "", "",
+ [&]() { writer += "Constants.FLATBUFFERS_2_0_0()"; },
+ options.gen_jvmstatic);
+
+ GenerateGetRootAsAccessors(Esc(struct_def.name), writer, options);
+ GenerateBufferHasIdentifier(struct_def, writer, options);
+ 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;
+ GenerateAddField(NumToString(field_pos), field, writer, options);
+
+ if (IsVector(field.value.type)) {
+ auto vector_type = field.value.type.VectorType();
+ if (!IsStruct(vector_type)) {
+ GenerateCreateVectorField(field, writer, options);
+ }
+ GenerateStartVectorField(field, writer, options);
+ }
+ }
+
+ GenerateEndStructMethod(struct_def, writer, options);
+ auto file_identifier = parser_.file_identifier_;
+ if (parser_.root_struct_def_ == &struct_def) {
+ GenerateFinishStructBuffer(struct_def, file_identifier, writer,
+ options);
+ GenerateFinishSizePrefixed(struct_def, file_identifier, writer,
+ options);
+ }
+
+ if (struct_def.has_key) {
+ GenerateLookupByKey(key_field, struct_def, writer, options);
+ }
+ } else {
+ 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: " << Esc(struct_def.name) << "?"
+ << ", ";
+ params << "vectorLocation: Int, ";
+ params << "key: " << GenTypeGet(key_field->value.type) << ", ";
+ params << "bb: ByteBuffer";
+
+ auto statements = [&]() {
+ auto base_type = key_field->value.type.base_type;
+ writer.SetValue("struct_name", Esc(struct_def.name));
+ if (base_type == BASE_TYPE_STRING) {
+ writer +=
+ "val byteKey = key."
+ "toByteArray(java.nio.charset.StandardCharsets.UTF_8)";
+ }
+ 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 cast = CastToUsigned(key_field->value.type);
+ auto get_val = GenLookupByKey(key_field, "bb");
+ writer += "val value = " + get_val + cast;
+ 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}}()).__assign(tableOffset, bb)";
+ writer.DecrementIdentLevel();
+ writer += "}"; // end else
+ writer.DecrementIdentLevel();
+ writer += "}"; // end when
+ writer.DecrementIdentLevel();
+ writer += "}"; // end while
+ writer += "return null";
+ };
+ GenerateFun(writer, "__lookup_by_key", params.str(),
+ Esc(struct_def.name) + "?", 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 params = "builder: FlatBufferBuilder, offset: Int";
+ auto method_name = "finishSizePrefixed" + Esc(struct_def.name) + "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 params = "builder: FlatBufferBuilder, offset: Int";
+ auto method_name = "finish" + Esc(struct_def.name) + "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 = "end" + Esc(struct_def.name);
+ auto params = "builder: FlatBufferBuilder";
+ auto returns = "Int";
+ auto field_vec = struct_def.fields.vec;
+
+ GenerateFun(
+ writer, name, params, returns,
+ [&]() {
+ writer += "val o = 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 += "builder.required(o, {{offset}})";
+ }
+ 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 = "create" + MakeCamel(Esc(field.name)) + "Vector";
+ auto params = "builder: FlatBufferBuilder, data: " +
+ GenTypeBasic(vector_type.base_type) + "Array";
+ writer.SetValue("size", NumToString(InlineSize(vector_type)));
+ writer.SetValue("align", NumToString(InlineAlignment(vector_type)));
+ writer.SetValue("root", GenMethod(vector_type));
+ writer.SetValue("cast", CastToSigned(vector_type));
+
+ GenerateFun(
+ writer, method_name, params, "Int",
+ [&]() {
+ writer += "builder.startVector({{size}}, data.size, {{align}})";
+ writer += "for (i in data.size - 1 downTo 0) {";
+ writer.IncrementIdentLevel();
+ writer += "builder.add{{root}}(data[i]{{cast}})";
+ 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, "start" + MakeCamel(Esc(field.name) + "Vector", true), 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 = GenTypeBasic(field.value.type.base_type);
+ auto secondArg = MakeCamel(Esc(field.name), false) + ": " + field_type;
+
+ GenerateFunOneLine(
+ writer, "add" + MakeCamel(Esc(field.name), true),
+ "builder: FlatBufferBuilder, " + secondArg, "",
+ [&]() {
+ auto method = GenMethod(field.value.type);
+ writer.SetValue("field_name", MakeCamel(Esc(field.name), false));
+ writer.SetValue("method_name", method);
+ writer.SetValue("pos", field_pos);
+ writer.SetValue("default", GenFBBDefaultValue(field));
+ writer.SetValue("cast", GenFBBValueCast(field));
+
+ writer += "builder.add{{method_name}}({{pos}}, \\";
+ writer += "{{field_name}}{{cast}}, {{default}})";
+ },
+ options.gen_jvmstatic);
+ }
+
+ static std::string ToSignedType(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_UINT: return GenTypeBasic(BASE_TYPE_INT);
+ case BASE_TYPE_ULONG: return GenTypeBasic(BASE_TYPE_LONG);
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_NONE:
+ case BASE_TYPE_UTYPE: return GenTypeBasic(BASE_TYPE_CHAR);
+ case BASE_TYPE_USHORT: return GenTypeBasic(BASE_TYPE_SHORT);
+ case BASE_TYPE_VECTOR: return ToSignedType(type.VectorType());
+ default: return GenTypeBasic(type.base_type);
+ }
+ }
+
+ static std::string FlexBufferBuilderCast(const std::string &method,
+ FieldDef &field, bool isFirst) {
+ auto field_type = GenTypeBasic(field.value.type.base_type);
+ std::string to_type;
+ if (method == "Boolean")
+ to_type = "Boolean";
+ else if (method == "Long")
+ to_type = "Long";
+ else if (method == "Int" || method == "Offset" || method == "Struct")
+ to_type = "Int";
+ else if (method == "Byte" || method.empty())
+ to_type = isFirst ? "Byte" : "Int";
+ else if (method == "Short")
+ to_type = isFirst ? "Short" : "Int";
+ else if (method == "Double")
+ to_type = "Double";
+ else if (method == "Float")
+ to_type = isFirst ? "Float" : "Double";
+ else if (method == "UByte")
+
+ if (field_type != to_type) return ".to" + to_type + "()";
+ return "";
+ }
+
+ // fun startMonster(builder: FlatBufferBuilder) = builder.startTable(11)
+ void GenerateStartStructMethod(StructDef &struct_def, CodeWriter &code,
+ const IDLOptions options) const {
+ GenerateFunOneLine(
+ code, "start" + Esc(struct_def.name), "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 = "create" + Esc(struct_def.name);
+ 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 << ", " << MakeCamel(Esc(field.name), false);
+ if (!IsScalar(field.value.type.base_type)) {
+ params << "Offset: ";
+ } else {
+ params << ": ";
+ }
+ auto optional = field.IsScalarOptional() ? "?" : "";
+ params << GenTypeBasic(field.value.type.base_type) << optional;
+ }
+
+ GenerateFun(
+ writer, name, params.str(), "Int",
+ [&]() {
+ writer.SetValue("vec_size", NumToString(fields_vec.size()));
+
+ 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("camel_field_name",
+ MakeCamel(Esc(field.name), true));
+ writer.SetValue("field_name",
+ MakeCamel(Esc(field.name), false));
+
+ // we wrap on null check for scalar optionals
+ writer += field.IsScalarOptional()
+ ? "{{field_name}}?.run { \\"
+ : "\\";
+
+ writer += "add{{camel_field_name}}(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{{struct_name}}(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 = MakeCamel(Esc(struct_def.name), false);
+ GenerateFunOneLine(
+ writer, name + "BufferHasIdentifier", "_bb: ByteBuffer", "Boolean",
+ [&]() {
+ writer += "__has_identifier(_bb, \"" + 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 = MakeCamel(Esc(field.name), false);
+ 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 ucast = CastToUsigned(field);
+ 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);
+ writer.SetValue("ucast", ucast);
+
+ // 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, [&]() {
+ writer += "{{bbgetter}}(bb_pos + {{offset}}){{ucast}}";
+ });
+ } else {
+ GenerateGetter(writer, field_name, return_type, [&]() {
+ writer += "val o = __offset({{offset}})";
+ writer +=
+ "return if(o != 0) {{bbgetter}}"
+ "(o + bb_pos){{ucast}} else "
+ "{{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.__assign(bb_pos + 4, bb)
+ // ? adds nullability annotation
+ GenerateFunOneLine(
+ writer, field_name, "obj: " + field_type, return_type,
+ [&]() { writer += "obj.__assign(bb_pos + {{offset}}, bb)"; });
+ } else {
+ // create getter with object reuse
+ // ex:
+ // fun pos(obj: Vec3) : Vec3? {
+ // val o = __offset(4)
+ // return if(o != 0) {
+ // obj.__assign(o + bb_pos, bb)
+ // else {
+ // null
+ // }
+ // }
+ // ? adds nullability annotation
+ GenerateFun(
+ writer, field_name, "obj: " + field_type, return_type, [&]() {
+ auto fixed = field.value.type.struct_def->fixed;
+
+ writer.SetValue("seek", Indirect("o + bb_pos", fixed));
+ OffsetWrapper(
+ writer, offset_val,
+ [&]() { writer += "obj.__assign({{seek}}, bb)"; },
+ [&]() { writer += "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 + bb_pos) else null
+ // }
+ // ? adds nullability annotation
+ GenerateGetter(writer, field_name, return_type, [&]() {
+ writer += "val o = __offset({{offset}})";
+ writer += "return if (o != 0) __string(o + bb_pos) else null";
+ });
+ break;
+ case BASE_TYPE_VECTOR: {
+ // e.g.
+ // fun inventory(j: Int) : UByte {
+ // val o = __offset(14)
+ // return if (o != 0) {
+ // bb.get(__vector(o) + 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";
+ }
+
+ GenerateFun(writer, field_name, params, return_type, [&]() {
+ auto inline_size = NumToString(InlineSize(vectortype));
+ auto index = "__vector(o) + j * " + inline_size;
+ auto not_found = NotFoundReturn(field.value.type.element);
+ auto found = "";
+ writer.SetValue("index", index);
+ switch (vectortype.base_type) {
+ case BASE_TYPE_STRUCT: {
+ bool fixed = vectortype.struct_def->fixed;
+ writer.SetValue("index", Indirect(index, fixed));
+ found = "obj.__assign({{index}}, bb)";
+ break;
+ }
+ case BASE_TYPE_UNION:
+ found = "{{bbgetter}}(obj, {{index}}){{ucast}}";
+ break;
+ default: found = "{{bbgetter}}({{index}}){{ucast}}";
+ }
+ OffsetWrapper(
+ writer, offset_val, [&]() { writer += found; },
+ [&]() { writer += not_found; });
+ });
+ break;
+ }
+ case BASE_TYPE_UNION:
+ GenerateFun(
+ writer, field_name, "obj: " + field_type, return_type, [&]() {
+ writer += OffsetWrapperOneLine(
+ offset_val, bbgetter + "(obj, o + bb_pos)", "null");
+ });
+ break;
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+
+ if (value_base_type == BASE_TYPE_VECTOR) {
+ // Generate Lenght functions for vectors
+ GenerateGetter(writer, field_name + "Length", "Int", [&]() {
+ writer += OffsetWrapperOneLine(offset_val, "__vector_len(o)", "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 = WrapInNameSpace(sd);
+ auto name = MakeCamel(Esc(field.name), false) + "ByKey";
+ auto params = "key: " + GenTypeGet(kfield.value.type);
+ auto rtype = qualified_name + "?";
+ GenerateFun(writer, name, params, rtype, [&]() {
+ OffsetWrapper(
+ writer, offset_val,
+ [&]() {
+ writer += qualified_name +
+ ".__lookup_by_key(null, __vector(o), key, bb)";
+ },
+ [&]() { writer += "null"; });
+ });
+
+ auto param2 = "obj: " + qualified_name +
+ ", key: " + GenTypeGet(kfield.value.type);
+ GenerateFun(writer, name, param2, rtype, [&]() {
+ OffsetWrapper(
+ writer, offset_val,
+ [&]() {
+ writer += qualified_name +
+ ".__lookup_by_key(obj, __vector(o), key, bb)";
+ },
+ [&]() { writer += "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.
+ // val inventoryByteBuffer: ByteBuffer
+ // get = __vector_as_bytebuffer(14, 1)
+
+ GenerateGetterOneLine(
+ writer, field_name + "AsByteBuffer", "ByteBuffer", [&]() {
+ writer.SetValue("end", end_idx);
+ writer += "__vector_as_bytebuffer({{offset}}, {{end}})";
+ });
+
+ // Generate a ByteBuffer accessor for strings & vectors of scalars.
+ // e.g.
+ // fun inventoryInByteBuffer(_bb: Bytebuffer):
+ // ByteBuffer = __vector_as_bytebuffer(_bb, 14, 1)
+ GenerateFunOneLine(
+ writer, field_name + "InByteBuffer", "_bb: ByteBuffer",
+ "ByteBuffer", [&]() {
+ writer.SetValue("end", end_idx);
+ writer += "__vector_in_bytebuffer(_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 = WrapInNameSpace(*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 + "())";
+ });
+
+ GenerateFun(writer, nested_method_name, "obj: " + nested_type_name,
+ nested_type_name + "?", [&]() {
+ OffsetWrapper(
+ writer, offset_val,
+ [&]() {
+ writer +=
+ "obj.__assign(__indirect(__vector(o)), bb)";
+ },
+ [&]() { writer += "null"; });
+ });
+ }
+
+ // Generate mutators for scalar fields or vectors of scalars.
+ if (parser_.opts.mutable_buffer) {
+ auto value_type = field.value.type;
+ auto underlying_type = value_base_type == BASE_TYPE_VECTOR
+ ? value_type.VectorType()
+ : value_type;
+ auto name = "mutate" + MakeCamel(Esc(field.name), true);
+ auto size = NumToString(InlineSize(underlying_type));
+ auto params = Esc(field.name) + ": " + GenTypeGet(underlying_type);
+ // A vector mutator also needs the index of the vector element it should
+ // mutate.
+ if (value_base_type == BASE_TYPE_VECTOR) params.insert(0, "j: Int, ");
+
+ // Boolean parameters have to be explicitly converted to byte
+ // representation.
+ auto setter_parameter =
+ underlying_type.base_type == BASE_TYPE_BOOL
+ ? "(if(" + Esc(field.name) + ") 1 else 0).toByte()"
+ : Esc(field.name);
+
+ auto setter_index =
+ value_base_type == BASE_TYPE_VECTOR
+ ? "__vector(o) + j * " + size
+ : (struct_def.fixed ? "bb_pos + " + offset_val : "o + bb_pos");
+ if (IsScalar(value_base_type) ||
+ (value_base_type == BASE_TYPE_VECTOR &&
+ IsScalar(value_type.VectorType().base_type))) {
+ auto statements = [&]() {
+ writer.SetValue("bbsetter", ByteBufferSetter(underlying_type));
+ writer.SetValue("index", setter_index);
+ writer.SetValue("params", setter_parameter);
+ writer.SetValue("cast", CastToSigned(field));
+ if (struct_def.fixed) {
+ writer += "{{bbsetter}}({{index}}, {{params}}{{cast}})";
+ } else {
+ OffsetWrapper(
+ writer, offset_val,
+ [&]() {
+ writer += "{{bbsetter}}({{index}}, {{params}}{{cast}})";
+ writer += "true";
+ },
+ [&]() { writer += "false"; });
+ }
+ };
+
+ if (struct_def.fixed) {
+ GenerateFunOneLine(writer, name, params, "ByteBuffer", statements);
+ } else {
+ GenerateFun(writer, name, params, "Boolean", statements);
+ }
+ }
+ }
+ }
+ if (struct_def.has_key && !struct_def.fixed) {
+ // Key Comparison method
+ GenerateOverrideFun(
+ writer, "keysCompare", "o1: Int, o2: Int, _bb: ByteBuffer", "Int",
+ [&]() {
+ if (IsString(key_field->value.type)) {
+ writer.SetValue("offset", NumToString(key_field->value.offset));
+ writer +=
+ " return compareStrings(__offset({{offset}}, o1, "
+ "_bb), __offset({{offset}}, o2, _bb), _bb)";
+
+ } else {
+ auto getter1 = GenLookupByKey(key_field, "_bb", "o1");
+ auto getter2 = GenLookupByKey(key_field, "_bb", "o2");
+ writer += "val val_1 = " + getter1;
+ writer += "val val_2 = " + getter2;
+ writer += "return (val_1 - val_2).sign";
+ }
+ });
+ }
+ }
+
+ static std::string CastToUsigned(const FieldDef &field) {
+ return CastToUsigned(field.value.type);
+ }
+
+ static std::string CastToUsigned(const Type type) {
+ switch (type.base_type) {
+ case BASE_TYPE_UINT: return ".toUInt()";
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_UTYPE: return ".toUByte()";
+ case BASE_TYPE_USHORT: return ".toUShort()";
+ case BASE_TYPE_ULONG: return ".toULong()";
+ case BASE_TYPE_VECTOR: return CastToUsigned(type.VectorType());
+ default: return "";
+ }
+ }
+
+ static std::string CastToSigned(const FieldDef &field) {
+ return CastToSigned(field.value.type);
+ }
+
+ static std::string CastToSigned(const Type type) {
+ switch (type.base_type) {
+ case BASE_TYPE_UINT: return ".toInt()";
+ case BASE_TYPE_UCHAR:
+ case BASE_TYPE_UTYPE: return ".toByte()";
+ case BASE_TYPE_USHORT: return ".toShort()";
+ case BASE_TYPE_ULONG: return ".toLong()";
+ case BASE_TYPE_VECTOR: return CastToSigned(type.VectorType());
+ default: return "";
+ }
+ }
+
+ static std::string LiteralSuffix(const BaseType type) {
+ switch (type) {
+ 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 "";
+ }
+ }
+
+ 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);
+ }
+ }
+
+ static void GenerateGetRootAsAccessors(const std::string &struct_name,
+ CodeWriter &writer,
+ IDLOptions options) {
+ // Generate a special accessor for the table that when used as the root
+ // ex: fun getRootAsMonster(_bb: ByteBuffer): Monster {...}
+ writer.SetValue("gr_name", struct_name);
+ writer.SetValue("gr_method", "getRootAs" + struct_name);
+
+ // create convenience method that doesn't require an existing object
+ GenerateJvmStaticAnnotation(writer, options.gen_jvmstatic);
+ writer += "fun {{gr_method}}(_bb: ByteBuffer): {{gr_name}} = \\";
+ writer += "{{gr_method}}(_bb, {{gr_name}}())";
+
+ // create method that allows object reuse
+ // ex: fun Monster getRootAsMonster(_bb: ByteBuffer, obj: Monster) {...}
+ GenerateJvmStaticAnnotation(writer, options.gen_jvmstatic);
+ writer +=
+ "fun {{gr_method}}"
+ "(_bb: ByteBuffer, obj: {{gr_name}}): {{gr_name}} {";
+ writer.IncrementIdentLevel();
+ writer += "_bb.order(ByteOrder.LITTLE_ENDIAN)";
+ writer +=
+ "return (obj.__assign(_bb.getInt(_bb.position())"
+ " + _bb.position(), _bb))";
+ writer.DecrementIdentLevel();
+ writer += "}";
+ }
+
+ static void GenerateStaticConstructor(const StructDef &struct_def,
+ CodeWriter &code,
+ const IDLOptions options) {
+ // create a struct constructor function
+ auto params = StructConstructorParams(struct_def);
+ GenerateFun(
+ code, "create" + Esc(struct_def.name), params, "Int",
+ [&]() {
+ GenStructBody(struct_def, code, "");
+ code += "return builder.offset()";
+ },
+ options.gen_jvmstatic);
+ }
+
+ static std::string StructConstructorParams(const StructDef &struct_def,
+ const std::string &prefix = "") {
+ // 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 + (Esc(field.name) + "_"));
+ } else {
+ out << ", " << prefix << MakeCamel(Esc(field.name), false) << ": "
+ << GenTypeBasic(field.value.type.base_type);
+ }
+ }
+ return out.str();
+ }
+
+ 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 &params,
+ 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 &params,
+ 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)
+ writer.SetValue("name", name);
+ writer.SetValue("params", params);
+ writer.SetValue("return_type_p",
+ returnType.empty() ? "" : " : " + returnType);
+ GenerateJvmStaticAnnotation(writer, gen_jvmstatic);
+ writer += "fun {{name}}({{params}}){{return_type_p}} = \\";
+ body();
+ }
+
+ static void GenerateOverrideFun(CodeWriter &writer, const std::string &name,
+ const std::string &params,
+ 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 &params,
+ 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 OffsetWrapperOneLine(const std::string &offset,
+ const std::string &found,
+ const std::string &not_found) {
+ return "val o = __offset(" + offset + "); return if (o != 0) " + found +
+ " else " + not_found;
+ }
+
+ static void OffsetWrapper(CodeWriter &code, const std::string &offset,
+ const std::function<void()> &found,
+ const std::function<void()> &not_found) {
+ code += "val o = __offset(" + offset + ")";
+ code += "return if (o != 0) {";
+ code.IncrementIdentLevel();
+ found();
+ code.DecrementIdentLevel();
+ code += "} else {";
+ code.IncrementIdentLevel();
+ not_found();
+ code.DecrementIdentLevel();
+ code += "}";
+ }
+
+ 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"; }
+ }
+
+ // This tracks the current namespace used to determine if a type need to be
+ // prefixed by its namespace
+ const Namespace *cur_name_space_;
+};
+} // namespace kotlin
+
+bool GenerateKotlin(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ kotlin::KotlinGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp b/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp
new file mode 100644
index 0000000000..6fdd6dc26a
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_lobster.cpp
@@ -0,0 +1,391 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#include <string>
+#include <unordered_set>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+namespace lobster {
+
+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 */, "_",
+ "lobster") {
+ static const char *const keywords[] = {
+ "nil", "true", "false", "return", "struct", "class",
+ "import", "int", "float", "string", "any", "def",
+ "is", "from", "program", "private", "coroutine", "resource",
+ "enum", "typeof", "var", "let", "pakfile", "switch",
+ "case", "default", "namespace", "not", "and", "or",
+ "bool",
+ };
+ keywords_.insert(std::begin(keywords), std::end(keywords));
+ }
+
+ std::string EscapeKeyword(const std::string &name) const {
+ return keywords_.find(name) == keywords_.end() ? name : name + "_";
+ }
+
+ std::string NormalizedName(const Definition &definition) const {
+ return EscapeKeyword(definition.name);
+ }
+
+ std::string NormalizedName(const EnumVal &ev) const {
+ return EscapeKeyword(ev.name);
+ }
+
+ std::string NamespacedName(const Definition &def) {
+ return WrapInNameSpace(def.defined_namespace, NormalizedName(def));
+ }
+
+ std::string GenTypeName(const Type &type) {
+ auto bits = NumToString(SizeOf(type.base_type) * 8);
+ if (IsInteger(type.base_type)) return "int" + bits;
+ if (IsFloat(type.base_type)) return "float" + bits;
+ if (IsString(type)) return "string";
+ if (type.base_type == BASE_TYPE_STRUCT) return "table";
+ return "none";
+ }
+
+ std::string LobsterType(const Type &type) {
+ if (IsFloat(type.base_type)) return "float";
+ if (IsScalar(type.base_type) && type.enum_def)
+ return NormalizedName(*type.enum_def);
+ if (!IsScalar(type.base_type)) return "flatbuffers_offset";
+ return "int";
+ }
+
+ // Returns the method name for use with add/put calls.
+ std::string GenMethod(const Type &type) {
+ return IsScalar(type.base_type)
+ ? MakeCamel(GenTypeBasic(type))
+ : (IsStruct(type) ? "Struct" : "UOffsetTRelative");
+ }
+
+ // This uses Python names for now..
+ std::string GenTypeBasic(const Type &type) {
+ // clang-format off
+ static const char *ctypename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
+ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, ...) \
+ #PTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+ return ctypename[type.base_type];
+ }
+
+ // Generate a struct field, conditioned on its child type(s).
+ void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ GenComment(field.doc_comment, code_ptr, nullptr, " ");
+ std::string &code = *code_ptr;
+ auto offsets = NumToString(field.value.offset);
+ auto def = " def " + NormalizedName(field);
+ if (IsScalar(field.value.type.base_type)) {
+ std::string acc;
+ if (struct_def.fixed) {
+ acc = "buf_.read_" + GenTypeName(field.value.type) + "_le(pos_ + " +
+ offsets + ")";
+
+ } else {
+ auto defval = field.IsOptional() ? "0" : field.value.constant;
+ acc = "buf_.flatbuffers_field_" + GenTypeName(field.value.type) +
+ "(pos_, " + offsets + ", " + defval + ")";
+ }
+ if (field.value.type.enum_def)
+ acc = NormalizedName(*field.value.type.enum_def) + "(" + acc + ")";
+ if (field.IsOptional())
+ acc += ", buf_.flatbuffers_field_present(pos_, " + offsets + ")";
+ code += def + "():\n return " + acc + "\n";
+ return;
+ }
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ auto name = NamespacedName(*field.value.type.struct_def);
+ code += def + "():\n ";
+ if (struct_def.fixed) {
+ code += "return " + name + "{ buf_, pos_ + " + offsets + " }\n";
+ } else {
+ code += std::string("let o = buf_.flatbuffers_field_") +
+ (field.value.type.struct_def->fixed ? "struct" : "table") +
+ "(pos_, " + offsets + ")\n return if o: " + name +
+ " { buf_, o } else: nil\n";
+ }
+ break;
+ }
+ case BASE_TYPE_STRING:
+ code += def +
+ "():\n return buf_.flatbuffers_field_string(pos_, " +
+ offsets + ")\n";
+ break;
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ code += def + "(i:int):\n return ";
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ auto start = "buf_.flatbuffers_field_vector(pos_, " + offsets +
+ ") + i * " + NumToString(InlineSize(vectortype));
+ if (!(vectortype.struct_def->fixed)) {
+ start = "buf_.flatbuffers_indirect(" + start + ")";
+ }
+ code += NamespacedName(*field.value.type.struct_def) + " { buf_, " +
+ start + " }\n";
+ } else {
+ if (IsString(vectortype))
+ code += "buf_.flatbuffers_string";
+ else
+ code += "buf_.read_" + GenTypeName(vectortype) + "_le";
+ code += "(buf_.flatbuffers_field_vector(pos_, " + offsets +
+ ") + i * " + NumToString(InlineSize(vectortype)) + ")\n";
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ for (auto it = field.value.type.enum_def->Vals().begin();
+ it != field.value.type.enum_def->Vals().end(); ++it) {
+ auto &ev = **it;
+ if (ev.IsNonZero()) {
+ code += def + "_as_" + ev.name + "():\n return " +
+ NamespacedName(*ev.union_type.struct_def) +
+ " { buf_, buf_.flatbuffers_field_table(pos_, " + offsets +
+ ") }\n";
+ }
+ }
+ break;
+ }
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ if (IsVector(field.value.type)) {
+ code += def +
+ "_length():\n return "
+ "buf_.flatbuffers_field_vector_len(pos_, " +
+ offsets + ")\n";
+ }
+ }
+
+ // Generate table constructors, conditioned on its members' types.
+ 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";
+ code += " def start():\n b_.StartObject(" +
+ NumToString(struct_def.fields.vec.size()) +
+ ")\n return this\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto offset = it - struct_def.fields.vec.begin();
+ code += " def add_" + NormalizedName(field) + "(" +
+ NormalizedName(field) + ":" + LobsterType(field.value.type) +
+ "):\n b_.Prepend" + GenMethod(field.value.type) + "Slot(" +
+ NumToString(offset) + ", " + NormalizedName(field);
+ if (IsScalar(field.value.type.base_type) && !field.IsOptional())
+ code += ", " + field.value.constant;
+ code += ")\n return this\n";
+ }
+ code += " def end():\n return b_.EndObject()\n\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ if (IsVector(field.value.type)) {
+ code += "def " + NormalizedName(struct_def) + "Start" +
+ MakeCamel(NormalizedName(field)) +
+ "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);
+ code +=
+ NumToString(elem_size) + ", n_, " + NumToString(alignment) + ")\n";
+ if (vector_type.base_type != BASE_TYPE_STRUCT ||
+ !vector_type.struct_def->fixed) {
+ code += "def " + NormalizedName(struct_def) + "Create" +
+ MakeCamel(NormalizedName(field)) +
+ "Vector(b_:flatbuffers_builder, v_:[" +
+ LobsterType(vector_type) + "]):\n b_.StartVector(" +
+ NumToString(elem_size) + ", v_.length, " +
+ NumToString(alignment) + ")\n reverse(v_) e_: b_.Prepend" +
+ GenMethod(vector_type) +
+ "(e_)\n return b_.EndVector(v_.length)\n";
+ }
+ code += "\n";
+ }
+ }
+ }
+
+ void GenStructPreDecl(const StructDef &struct_def, std::string *code_ptr) {
+ if (struct_def.generated) return;
+ std::string &code = *code_ptr;
+ CheckNameSpace(struct_def, &code);
+ code += "class " + NormalizedName(struct_def) + "\n\n";
+ }
+
+ // Generate struct or table methods.
+ void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
+ if (struct_def.generated) return;
+ 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";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ GenStructAccessor(struct_def, field, code_ptr);
+ }
+ code += "\n";
+ if (!struct_def.fixed) {
+ // Generate a special accessor for the table that has been declared as
+ // the root type.
+ code += "def GetRootAs" + NormalizedName(struct_def) +
+ "(buf:string): return " + NormalizedName(struct_def) +
+ " { buf, buf.flatbuffers_indirect(0) }\n\n";
+ }
+ if (struct_def.fixed) {
+ // create a struct constructor function
+ GenStructBuilder(struct_def, code_ptr);
+ } else {
+ // Create a set of functions that allow table construction.
+ GenTableBuilders(struct_def, code_ptr);
+ }
+ }
+
+ // Generate enum declarations.
+ void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
+ if (enum_def.generated) return;
+ std::string &code = *code_ptr;
+ CheckNameSpace(enum_def, &code);
+ GenComment(enum_def.doc_comment, code_ptr, nullptr, "");
+ code += "enum " + NormalizedName(enum_def) + ":\n";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ GenComment(ev.doc_comment, code_ptr, nullptr, " ");
+ code += " " + enum_def.name + "_" + NormalizedName(ev) + " = " +
+ enum_def.ToString(ev) + "\n";
+ }
+ code += "\n";
+ }
+
+ // Recursively generate arguments for a constructor, to deal with nested
+ // structs.
+ void StructBuilderArgs(const StructDef &struct_def, const char *nameprefix,
+ std::string *code_ptr) {
+ 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.
+ StructBuilderArgs(*field.value.type.struct_def,
+ (nameprefix + (NormalizedName(field) + "_")).c_str(),
+ code_ptr);
+ } else {
+ std::string &code = *code_ptr;
+ code += ", " + (nameprefix + NormalizedName(field)) + ":" +
+ LobsterType(field.value.type);
+ }
+ }
+ }
+
+ // Recursively generate struct construction statements and instert manual
+ // padding.
+ void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += " b_.Prep(" + NumToString(struct_def.minalign) + ", " +
+ NumToString(struct_def.bytesize) + ")\n";
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ auto &field = **it;
+ if (field.padding)
+ code += " b_.Pad(" + NumToString(field.padding) + ")\n";
+ if (IsStruct(field.value.type)) {
+ StructBuilderBody(*field.value.type.struct_def,
+ (nameprefix + (NormalizedName(field) + "_")).c_str(),
+ code_ptr);
+ } else {
+ code += " b_.Prepend" + GenMethod(field.value.type) + "(" +
+ nameprefix + NormalizedName(field) + ")\n";
+ }
+ }
+ }
+
+ // Create a struct with a builder and the struct's arguments.
+ void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code +=
+ "def Create" + NormalizedName(struct_def) + "(b_:flatbuffers_builder";
+ StructBuilderArgs(struct_def, "", code_ptr);
+ code += "):\n";
+ StructBuilderBody(struct_def, "", code_ptr);
+ code += " return b_.Offset()\n\n";
+ }
+
+ void CheckNameSpace(const Definition &def, std::string *code_ptr) {
+ auto ns = GetNameSpace(def);
+ if (ns == current_namespace_) return;
+ current_namespace_ = ns;
+ std::string &code = *code_ptr;
+ code += "namespace " + ns + "\n\n";
+ }
+
+ bool generate() {
+ std::string code;
+ code += std::string("// ") + FlatBuffersGeneratedWarning() +
+ "\nimport flatbuffers\n\n";
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ auto &enum_def = **it;
+ GenEnum(enum_def, &code);
+ }
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ auto &struct_def = **it;
+ GenStructPreDecl(struct_def, &code);
+ }
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ auto &struct_def = **it;
+ GenStruct(struct_def, &code);
+ }
+ return SaveFile(GeneratedFileName(path_, file_name_, parser_.opts).c_str(),
+ code, false);
+ }
+
+ private:
+ std::unordered_set<std::string> keywords_;
+ std::string current_namespace_;
+};
+
+} // namespace lobster
+
+bool GenerateLobster(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ lobster::LobsterGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_lua.cpp b/contrib/libs/flatbuffers/src/idl_gen_lua.cpp
new file mode 100644
index 0000000000..9efc435e24
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_lua.cpp
@@ -0,0 +1,745 @@
+/*
+ * 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 <string>
+#include <unordered_set>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+namespace lua {
+
+// Hardcode spaces per indentation.
+const CommentConfig def_comment = { nullptr, "--", nullptr };
+const char *Indent = " ";
+const char *Comment = "-- ";
+const char *End = "end\n";
+const char *EndFunc = "end\n";
+const char *SelfData = "self.view";
+const char *SelfDataPos = "self.view.pos";
+const char *SelfDataBytes = "self.view.bytes";
+
+class LuaGenerator : public BaseGenerator {
+ public:
+ LuaGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "" /* not used */,
+ "" /* not used */, "lua") {
+ static const char *const keywords[] = {
+ "and", "break", "do", "else", "elseif", "end", "false", "for",
+ "function", "goto", "if", "in", "local", "nil", "not", "or",
+ "repeat", "return", "then", "true", "until", "while"
+ };
+ keywords_.insert(std::begin(keywords), std::end(keywords));
+ }
+
+ // Most field accessors need to retrieve and test the field offset first,
+ // this is the prefix code for that.
+ std::string OffsetPrefix(const FieldDef &field) {
+ return std::string(Indent) + "local o = " + SelfData + ":Offset(" +
+ NumToString(field.value.offset) + ")\n" + Indent +
+ "if o ~= 0 then\n";
+ }
+
+ // Begin a class declaration.
+ void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "local " + NormalizedName(struct_def) + " = {} -- the module\n";
+ code += "local " + NormalizedMetaName(struct_def) +
+ " = {} -- the class metatable\n";
+ code += "\n";
+ }
+
+ // Begin enum code with a class declaration.
+ void BeginEnum(const std::string &class_name, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "local " + class_name + " = {\n";
+ }
+
+ std::string EscapeKeyword(const std::string &name) const {
+ return keywords_.find(name) == keywords_.end() ? name : "_" + name;
+ }
+
+ std::string NormalizedName(const Definition &definition) const {
+ return EscapeKeyword(definition.name);
+ }
+
+ std::string NormalizedName(const EnumVal &ev) const {
+ return EscapeKeyword(ev.name);
+ }
+
+ std::string NormalizedMetaName(const Definition &definition) const {
+ return EscapeKeyword(definition.name) + "_mt";
+ }
+
+ // A single enum member.
+ void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += std::string(Indent) + NormalizedName(ev) + " = " +
+ enum_def.ToString(ev) + ",\n";
+ }
+
+ // End enum code.
+ void EndEnum(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "}\n";
+ }
+
+ void GenerateNewObjectPrototype(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "function " + NormalizedName(struct_def) + ".New()\n";
+ code += std::string(Indent) + "local o = {}\n";
+ code += std::string(Indent) +
+ "setmetatable(o, {__index = " + NormalizedMetaName(struct_def) +
+ "})\n";
+ code += std::string(Indent) + "return o\n";
+ code += EndFunc;
+ }
+
+ // Initialize a new struct or table from existing data.
+ void NewRootTypeFromBuffer(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "function " + NormalizedName(struct_def) + ".GetRootAs" +
+ NormalizedName(struct_def) + "(buf, offset)\n";
+ code += std::string(Indent) + "if type(buf) == \"string\" then\n";
+ code += std::string(Indent) + Indent +
+ "buf = flatbuffers.binaryArray.New(buf)\n";
+ code += std::string(Indent) + "end\n";
+ code += std::string(Indent) +
+ "local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)\n";
+ code += std::string(Indent) + "local o = " + NormalizedName(struct_def) +
+ ".New()\n";
+ code += std::string(Indent) + "o:Init(buf, n + offset)\n";
+ code += std::string(Indent) + "return o\n";
+ code += EndFunc;
+ }
+
+ // Initialize an existing object with other data, to avoid an allocation.
+ void InitializeExisting(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += "Init(buf, pos)\n";
+ code +=
+ std::string(Indent) + SelfData + " = flatbuffers.view.New(buf, pos)\n";
+ code += EndFunc;
+ }
+
+ // Get the length of a vector.
+ void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field)) + "Length()\n";
+ code += OffsetPrefix(field);
+ code +=
+ std::string(Indent) + Indent + "return " + SelfData + ":VectorLen(o)\n";
+ code += std::string(Indent) + End;
+ code += std::string(Indent) + "return 0\n";
+ code += EndFunc;
+ }
+
+ // Get the value of a struct's scalar.
+ void GetScalarFieldOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ std::string getter = GenGetter(field.value.type);
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "()\n";
+ code += std::string(Indent) + "return " + getter;
+ code += std::string(SelfDataPos) + " + " + NumToString(field.value.offset) +
+ ")\n";
+ code += EndFunc;
+ }
+
+ // Get the value of a table's scalar.
+ void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ std::string getter = GenGetter(field.value.type);
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "()\n";
+ code += OffsetPrefix(field);
+ getter += std::string("o + ") + SelfDataPos + ")";
+ auto is_bool = field.value.type.base_type == BASE_TYPE_BOOL;
+ if (is_bool) { getter = "(" + getter + " ~= 0)"; }
+ code += std::string(Indent) + Indent + "return " + getter + "\n";
+ code += std::string(Indent) + End;
+ std::string default_value;
+ if (is_bool) {
+ default_value = field.value.constant == "0" ? "false" : "true";
+ } else {
+ default_value = field.value.constant;
+ }
+ code += std::string(Indent) + "return " + default_value + "\n";
+ code += EndFunc;
+ }
+
+ // Get a struct by initializing an existing struct.
+ // Specific to Struct.
+ void GetStructFieldOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(obj)\n";
+ code += std::string(Indent) + "obj:Init(" + SelfDataBytes + ", " +
+ SelfDataPos + " + ";
+ code += NumToString(field.value.offset) + ")\n";
+ code += std::string(Indent) + "return obj\n";
+ code += EndFunc;
+ }
+
+ // Get a struct by initializing an existing struct.
+ // Specific to Table.
+ void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "()\n";
+ code += OffsetPrefix(field);
+ if (field.value.type.struct_def->fixed) {
+ code +=
+ std::string(Indent) + Indent + "local x = o + " + SelfDataPos + "\n";
+ } else {
+ code += std::string(Indent) + Indent + "local x = " + SelfData +
+ ":Indirect(o + " + SelfDataPos + ")\n";
+ }
+ code += std::string(Indent) + Indent + "local obj = require('" +
+ TypeNameWithNamespace(field) + "').New()\n";
+ code +=
+ std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
+ code += std::string(Indent) + Indent + "return obj\n";
+ code += std::string(Indent) + End;
+ code += EndFunc;
+ }
+
+ // Get the value of a string.
+ void GetStringField(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "()\n";
+ code += OffsetPrefix(field);
+ code +=
+ std::string(Indent) + Indent + "return " + GenGetter(field.value.type);
+ code += std::string("o + ") + SelfDataPos + ")\n";
+ code += std::string(Indent) + End;
+ code += EndFunc;
+ }
+
+ // Get the value of a union from an object.
+ void GetUnionField(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field)) + "()\n";
+ code += OffsetPrefix(field);
+
+ // TODO(rw): this works and is not the good way to it:
+ // bool is_native_table = TypeName(field) == "*flatbuffers.Table";
+ // if (is_native_table) {
+ // code += std::string(Indent) + Indent + "from flatbuffers.table import
+ // Table\n";
+ //} else {
+ // code += std::string(Indent) + Indent +
+ // code += "from ." + TypeName(field) + " import " + TypeName(field) +
+ // "\n";
+ //}
+ code +=
+ std::string(Indent) + Indent +
+ "local obj = "
+ "flatbuffers.view.New(require('flatbuffers.binaryarray').New(0), 0)\n";
+ code += std::string(Indent) + Indent + GenGetter(field.value.type) +
+ "obj, o)\n";
+ code += std::string(Indent) + Indent + "return obj\n";
+ code += std::string(Indent) + End;
+ code += EndFunc;
+ }
+
+ // Get the value of a vector's struct member.
+ void GetMemberOfVectorOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(j)\n";
+ code += OffsetPrefix(field);
+ code +=
+ std::string(Indent) + Indent + "local x = " + SelfData + ":Vector(o)\n";
+ code += std::string(Indent) + Indent + "x = x + ((j-1) * ";
+ code += NumToString(InlineSize(vectortype)) + ")\n";
+ if (!(vectortype.struct_def->fixed)) {
+ code +=
+ std::string(Indent) + Indent + "x = " + SelfData + ":Indirect(x)\n";
+ }
+ code += std::string(Indent) + Indent + "local obj = require('" +
+ TypeNameWithNamespace(field) + "').New()\n";
+ code +=
+ std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
+ code += std::string(Indent) + Indent + "return obj\n";
+ code += std::string(Indent) + End;
+ code += EndFunc;
+ }
+
+ // Get the value of a vector's non-struct member. Uses a named return
+ // argument to conveniently set the zero value for the result.
+ void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(j)\n";
+ code += OffsetPrefix(field);
+ code +=
+ std::string(Indent) + Indent + "local a = " + SelfData + ":Vector(o)\n";
+ code += std::string(Indent) + Indent;
+ code += "return " + GenGetter(field.value.type);
+ code += "a + ((j-1) * ";
+ code += NumToString(InlineSize(vectortype)) + "))\n";
+ code += std::string(Indent) + End;
+ if (IsString(vectortype)) {
+ code += std::string(Indent) + "return ''\n";
+ } else {
+ code += std::string(Indent) + "return 0\n";
+ }
+ code += EndFunc;
+ }
+
+ // Access a byte/ubyte vector as a string
+ void AccessByteVectorAsString(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "AsString(start, stop)\n";
+ code += std::string(Indent) + "return " + SelfData + ":VectorAsString(" +
+ NumToString(field.value.offset) + ", start, stop)\n";
+ code += EndFunc;
+ }
+
+ // Begin the creator function signature.
+ void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "function " + NormalizedName(struct_def) + ".Create" +
+ NormalizedName(struct_def);
+ code += "(builder";
+ }
+
+ // Recursively generate arguments for a constructor, to deal with nested
+ // structs.
+ void StructBuilderArgs(const StructDef &struct_def, const char *nameprefix,
+ std::string *code_ptr) {
+ 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.
+ StructBuilderArgs(*field.value.type.struct_def,
+ (nameprefix + (NormalizedName(field) + "_")).c_str(),
+ code_ptr);
+ } else {
+ std::string &code = *code_ptr;
+ code += std::string(", ") + nameprefix;
+ code += MakeCamel(NormalizedName(field), false);
+ }
+ }
+ }
+
+ // End the creator function signature.
+ void EndBuilderArgs(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += ")\n";
+ }
+
+ // Recursively generate struct construction statements and instert manual
+ // padding.
+ void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += std::string(Indent) + "builder:Prep(" +
+ NumToString(struct_def.minalign) + ", ";
+ code += NumToString(struct_def.bytesize) + ")\n";
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ auto &field = **it;
+ if (field.padding)
+ code += std::string(Indent) + "builder:Pad(" +
+ NumToString(field.padding) + ")\n";
+ if (IsStruct(field.value.type)) {
+ StructBuilderBody(*field.value.type.struct_def,
+ (nameprefix + (NormalizedName(field) + "_")).c_str(),
+ code_ptr);
+ } else {
+ code +=
+ std::string(Indent) + "builder:Prepend" + GenMethod(field) + "(";
+ code += nameprefix + MakeCamel(NormalizedName(field), false) + ")\n";
+ }
+ }
+ }
+
+ void EndBuilderBody(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += std::string(Indent) + "return builder:Offset()\n";
+ code += EndFunc;
+ }
+
+ // Get the value of a table's starting offset.
+ void GetStartOfTable(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "function " + NormalizedName(struct_def) + ".Start";
+ code += "(builder) ";
+ code += "builder:StartObject(";
+ code += NumToString(struct_def.fields.vec.size());
+ code += ") end\n";
+ }
+
+ // Set the value of a table's field.
+ void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
+ const size_t offset, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "function " + NormalizedName(struct_def) + ".Add" +
+ MakeCamel(NormalizedName(field));
+ code += "(builder, ";
+ code += MakeCamel(NormalizedName(field), false);
+ code += ") ";
+ code += "builder:Prepend";
+ code += GenMethod(field) + "Slot(";
+ code += NumToString(offset) + ", ";
+ // todo: i don't need to cast in Lua, but am I missing something?
+ // if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
+ // code += "flatbuffers.N.UOffsetTFlags.py_type";
+ // code += "(";
+ // code += MakeCamel(NormalizedName(field), false) + ")";
+ // } else {
+ code += MakeCamel(NormalizedName(field), false);
+ // }
+ code += ", " + field.value.constant;
+ code += ") end\n";
+ }
+
+ // Set the value of one of the members of a table's vector.
+ void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "function " + NormalizedName(struct_def) + ".Start";
+ code += MakeCamel(NormalizedName(field));
+ code += "Vector(builder, numElems) return builder:StartVector(";
+ auto vector_type = field.value.type.VectorType();
+ auto alignment = InlineAlignment(vector_type);
+ auto elem_size = InlineSize(vector_type);
+ code += NumToString(elem_size);
+ code += ", numElems, " + NumToString(alignment);
+ code += ") end\n";
+ }
+
+ // Get the offset of the end of a table.
+ void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "function " + NormalizedName(struct_def) + ".End";
+ code += "(builder) ";
+ code += "return builder:EndObject() end\n";
+ }
+
+ // Generate the receiver for function signatures.
+ void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "function " + NormalizedMetaName(struct_def) + ":";
+ }
+
+ // Generate a struct field, conditioned on its child type(s).
+ void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ GenComment(field.doc_comment, code_ptr, &def_comment);
+ if (IsScalar(field.value.type.base_type)) {
+ if (struct_def.fixed) {
+ GetScalarFieldOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetScalarFieldOfTable(struct_def, field, code_ptr);
+ }
+ } else {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT:
+ if (struct_def.fixed) {
+ GetStructFieldOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetStructFieldOfTable(struct_def, field, code_ptr);
+ }
+ break;
+ case BASE_TYPE_STRING:
+ GetStringField(struct_def, field, code_ptr);
+ break;
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
+ if (vectortype.base_type == BASE_TYPE_CHAR ||
+ vectortype.base_type == BASE_TYPE_UCHAR) {
+ AccessByteVectorAsString(struct_def, field, code_ptr);
+ }
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+ if (IsVector(field.value.type)) {
+ GetVectorLen(struct_def, field, code_ptr);
+ }
+ }
+
+ // Generate table constructors, conditioned on its members' types.
+ void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) {
+ GetStartOfTable(struct_def, code_ptr);
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ auto offset = it - struct_def.fields.vec.begin();
+ BuildFieldOfTable(struct_def, field, offset, code_ptr);
+ if (IsVector(field.value.type)) {
+ BuildVectorOfTable(struct_def, field, code_ptr);
+ }
+ }
+
+ GetEndOffsetOnTable(struct_def, code_ptr);
+ }
+
+ // Generate struct or table methods.
+ void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
+ if (struct_def.generated) return;
+
+ GenComment(struct_def.doc_comment, code_ptr, &def_comment);
+ BeginClass(struct_def, code_ptr);
+
+ GenerateNewObjectPrototype(struct_def, code_ptr);
+
+ if (!struct_def.fixed) {
+ // Generate a special accessor for the table that has been declared as
+ // the root type.
+ NewRootTypeFromBuffer(struct_def, code_ptr);
+ }
+
+ // Generate the Init method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ InitializeExisting(struct_def, code_ptr);
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ GenStructAccessor(struct_def, field, code_ptr);
+ }
+
+ if (struct_def.fixed) {
+ // create a struct constructor function
+ GenStructBuilder(struct_def, code_ptr);
+ } else {
+ // Create a set of functions that allow table construction.
+ GenTableBuilders(struct_def, code_ptr);
+ }
+ }
+
+ // Generate enum declarations.
+ void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
+ if (enum_def.generated) return;
+
+ GenComment(enum_def.doc_comment, code_ptr, &def_comment);
+ BeginEnum(NormalizedName(enum_def), code_ptr);
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ GenComment(ev.doc_comment, code_ptr, &def_comment, Indent);
+ EnumMember(enum_def, ev, code_ptr);
+ }
+ EndEnum(code_ptr);
+ }
+
+ // Returns the function name that is able to read a value of the given type.
+ std::string GenGetter(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return std::string(SelfData) + ":String(";
+ case BASE_TYPE_UNION: return std::string(SelfData) + ":Union(";
+ case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
+ default:
+ return std::string(SelfData) + ":Get(flatbuffers.N." +
+ MakeCamel(GenTypeGet(type)) + ", ";
+ }
+ }
+
+ // Returns the method name for use with add/put calls.
+ std::string GenMethod(const FieldDef &field) {
+ return IsScalar(field.value.type.base_type)
+ ? MakeCamel(GenTypeBasic(field.value.type))
+ : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
+ }
+
+ std::string GenTypeBasic(const Type &type) {
+ // clang-format off
+ static const char *ctypename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
+ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, ...) \
+ #PTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+ return ctypename[type.base_type];
+ }
+
+ std::string GenTypePointer(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return "string";
+ case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
+ case BASE_TYPE_STRUCT: return type.struct_def->name;
+ case BASE_TYPE_UNION:
+ // fall through
+ default: return "*flatbuffers.Table";
+ }
+ }
+
+ std::string GenTypeGet(const Type &type) {
+ return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
+ }
+
+ std::string GetNamespace(const Type &type) {
+ return type.struct_def->defined_namespace->GetFullyQualifiedName(
+ type.struct_def->name);
+ }
+
+ std::string TypeName(const FieldDef &field) {
+ return GenTypeGet(field.value.type);
+ }
+
+ std::string TypeNameWithNamespace(const FieldDef &field) {
+ return GetNamespace(field.value.type);
+ }
+
+ // Create a struct with a builder and the struct's arguments.
+ void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) {
+ BeginBuilderArgs(struct_def, code_ptr);
+ StructBuilderArgs(struct_def, "", code_ptr);
+ EndBuilderArgs(code_ptr);
+
+ StructBuilderBody(struct_def, "", code_ptr);
+ EndBuilderBody(code_ptr);
+ }
+
+ bool generate() {
+ if (!generateEnums()) return false;
+ if (!generateStructs()) return false;
+ return true;
+ }
+
+ private:
+ bool generateEnums() {
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ auto &enum_def = **it;
+ std::string enumcode;
+ GenEnum(enum_def, &enumcode);
+ if (!SaveType(enum_def, enumcode, false)) return false;
+ }
+ return true;
+ }
+
+ bool generateStructs() {
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ auto &struct_def = **it;
+ std::string declcode;
+ GenStruct(struct_def, &declcode);
+ if (!SaveType(struct_def, declcode, true)) return false;
+ }
+ return true;
+ }
+
+ // Begin by declaring namespace and imports.
+ void BeginFile(const std::string &name_space_name, const bool needs_imports,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += std::string(Comment) + FlatBuffersGeneratedWarning() + "\n\n";
+ code += std::string(Comment) + "namespace: " + name_space_name + "\n\n";
+ if (needs_imports) {
+ code += "local flatbuffers = require('flatbuffers')\n\n";
+ }
+ }
+
+ // Save out the generated code for a Lua Table type.
+ bool SaveType(const Definition &def, const std::string &classcode,
+ bool needs_imports) {
+ if (!classcode.length()) return true;
+
+ std::string namespace_dir = path_;
+ auto &namespaces = def.defined_namespace->components;
+ for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
+ if (it != namespaces.begin()) namespace_dir += kPathSeparator;
+ namespace_dir += *it;
+ // std::string init_py_filename = namespace_dir + "/__init__.py";
+ // SaveFile(init_py_filename.c_str(), "", false);
+ }
+
+ std::string code = "";
+ BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
+ code += classcode;
+ code += "\n";
+ code +=
+ "return " + NormalizedName(def) + " " + Comment + "return the module";
+ std::string filename =
+ NamespaceDir(*def.defined_namespace) + NormalizedName(def) + ".lua";
+ return SaveFile(filename.c_str(), code, false);
+ }
+
+ private:
+ std::unordered_set<std::string> keywords_;
+};
+
+} // namespace lua
+
+bool GenerateLua(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ lua::LuaGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_php.cpp b/contrib/libs/flatbuffers/src/idl_gen_php.cpp
new file mode 100644
index 0000000000..dd3ed68189
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_php.cpp
@@ -0,0 +1,939 @@
+/*
+ * 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 <string>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+namespace php {
+// Hardcode spaces per indentation.
+const std::string Indent = " ";
+class PhpGenerator : public BaseGenerator {
+ public:
+ PhpGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "\\", "\\", "php") {}
+ bool generate() {
+ if (!GenerateEnums()) return false;
+ if (!GenerateStructs()) return false;
+ return true;
+ }
+
+ private:
+ bool GenerateEnums() {
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ auto &enum_def = **it;
+ std::string enumcode;
+ GenEnum(enum_def, &enumcode);
+ if (!SaveType(enum_def, enumcode, false)) return false;
+ }
+ return true;
+ }
+
+ bool GenerateStructs() {
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ auto &struct_def = **it;
+ std::string declcode;
+ GenStruct(struct_def, &declcode);
+ if (!SaveType(struct_def, declcode, true)) return false;
+ }
+ return true;
+ }
+
+ // Begin by declaring namespace and imports.
+ void BeginFile(const std::string &name_space_name, const bool needs_imports,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += "<?php\n";
+ code = code + "// " + FlatBuffersGeneratedWarning() + "\n\n";
+
+ if (!name_space_name.empty()) {
+ code += "namespace " + name_space_name + ";\n\n";
+ }
+
+ if (needs_imports) {
+ code += "use \\Google\\FlatBuffers\\Struct;\n";
+ code += "use \\Google\\FlatBuffers\\Table;\n";
+ code += "use \\Google\\FlatBuffers\\ByteBuffer;\n";
+ code += "use \\Google\\FlatBuffers\\FlatBufferBuilder;\n";
+ code += "\n";
+ }
+ }
+
+ // Save out the generated code for a Php Table type.
+ bool SaveType(const Definition &def, const std::string &classcode,
+ bool needs_imports) {
+ if (!classcode.length()) return true;
+
+ std::string code = "";
+ BeginFile(FullNamespace("\\", *def.defined_namespace), needs_imports,
+ &code);
+ code += classcode;
+
+ std::string filename =
+ NamespaceDir(*def.defined_namespace) + def.name + ".php";
+ return SaveFile(filename.c_str(), code, false);
+ }
+
+ // Begin a class declaration.
+ static void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ if (struct_def.fixed) {
+ code += "class " + struct_def.name + " extends Struct\n";
+ } else {
+ code += "class " + struct_def.name + " extends Table\n";
+ }
+ code += "{\n";
+ }
+
+ static void EndClass(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "}\n";
+ }
+
+ // Begin enum code with a class declaration.
+ static void BeginEnum(const std::string &class_name, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "class " + class_name + "\n{\n";
+ }
+
+ // A single enum member.
+ static void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += Indent + "const ";
+ code += ev.name;
+ code += " = ";
+ code += enum_def.ToString(ev) + ";\n";
+ }
+
+ // End enum code.
+ static void EndEnum(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "}\n";
+ }
+
+ // Initialize a new struct or table from existing data.
+ static void NewRootTypeFromBuffer(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "/**\n";
+ code += Indent + " * @param ByteBuffer $bb\n";
+ code += Indent + " * @return " + struct_def.name + "\n";
+ code += Indent + " */\n";
+ code += Indent + "public static function getRootAs";
+ code += struct_def.name;
+ code += "(ByteBuffer $bb)\n";
+ code += Indent + "{\n";
+
+ code += Indent + Indent + "$obj = new " + struct_def.name + "();\n";
+ code += Indent + Indent;
+ code += "return ($obj->init($bb->getInt($bb->getPosition())";
+ code += " + $bb->getPosition(), $bb));\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Initialize an existing object with other data, to avoid an allocation.
+ static void InitializeExisting(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "/**\n";
+ code += Indent + " * @param int $_i offset\n";
+ code += Indent + " * @param ByteBuffer $_bb\n";
+ code += Indent + " * @return " + struct_def.name + "\n";
+ code += Indent + " **/\n";
+ code += Indent + "public function init($_i, ByteBuffer $_bb)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$this->bb_pos = $_i;\n";
+ code += Indent + Indent + "$this->bb = $_bb;\n";
+ code += Indent + Indent + "return $this;\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Get the length of a vector.
+ static void GetVectorLen(const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "/**\n";
+ code += Indent + " * @return int\n";
+ code += Indent + " */\n";
+ code += Indent + "public function get";
+ code += MakeCamel(field.name) + "Length()\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$o = $this->__offset(";
+ code += NumToString(field.value.offset) + ");\n";
+ code += Indent + Indent;
+ code += "return $o != 0 ? $this->__vector_len($o) : 0;\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Get a [ubyte] vector as a byte array.
+ static void GetUByte(const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "/**\n";
+ code += Indent + " * @return string\n";
+ code += Indent + " */\n";
+ code += Indent + "public function get";
+ code += MakeCamel(field.name) + "Bytes()\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "return $this->__vector_as_bytes(";
+ code += NumToString(field.value.offset) + ");\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Get the value of a struct's scalar.
+ static void GetScalarFieldOfStruct(const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ std::string getter = GenGetter(field.value.type);
+
+ code += Indent + "/**\n";
+ code += Indent + " * @return ";
+ code += GenTypeGet(field.value.type) + "\n";
+ code += Indent + " */\n";
+ code += Indent + "public function " + getter;
+ code += MakeCamel(field.name) + "()\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "return ";
+
+ code += "$this->bb->get";
+ code += MakeCamel(GenTypeGet(field.value.type));
+ code += "($this->bb_pos + ";
+ code += NumToString(field.value.offset) + ")";
+ code += ";\n";
+
+ code += Indent + "}\n\n";
+ }
+
+ // Get the value of a table's scalar.
+ void GetScalarFieldOfTable(const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "/**\n";
+ code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
+ code += Indent + " */\n";
+ code += Indent + "public function get";
+ code += MakeCamel(field.name);
+ code += "()\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$o = $this->__offset(" +
+ NumToString(field.value.offset) + ");\n" + Indent + Indent +
+ "return $o != 0 ? ";
+ code += "$this->bb->get";
+ code += MakeCamel(GenTypeGet(field.value.type)) + "($o + $this->bb_pos)";
+ code += " : " + GenDefaultValue(field.value) + ";\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Get a struct by initializing an existing struct.
+ // Specific to Struct.
+ void GetStructFieldOfStruct(const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "/**\n";
+ code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
+ code += Indent + " */\n";
+ code += Indent + "public function get";
+ code += MakeCamel(field.name) + "()\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$obj = new ";
+ code += GenTypeGet(field.value.type) + "();\n";
+ code += Indent + Indent + "$obj->init($this->bb_pos + ";
+ code += NumToString(field.value.offset) + ", $this->bb);";
+ code += "\n" + Indent + Indent + "return $obj;\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Get a struct by initializing an existing struct.
+ // Specific to Table.
+ void GetStructFieldOfTable(const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "public function get";
+ code += MakeCamel(field.name);
+ code += "()\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$obj = new ";
+ code += MakeCamel(GenTypeGet(field.value.type)) + "();\n";
+ code += Indent + Indent + "$o = $this->__offset(" +
+ NumToString(field.value.offset) + ");\n";
+ code += Indent + Indent;
+ code += "return $o != 0 ? $obj->init(";
+ if (field.value.type.struct_def->fixed) {
+ code += "$o + $this->bb_pos, $this->bb) : ";
+ } else {
+ code += "$this->__indirect($o + $this->bb_pos), $this->bb) : ";
+ }
+ code += GenDefaultValue(field.value) + ";\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Get the value of a string.
+ void GetStringField(const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += Indent + "public function get";
+ code += MakeCamel(field.name);
+ code += "()\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$o = $this->__offset(" +
+ NumToString(field.value.offset) + ");\n";
+ code += Indent + Indent;
+ code += "return $o != 0 ? $this->__string($o + $this->bb_pos) : ";
+ code += GenDefaultValue(field.value) + ";\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Get the value of a union from an object.
+ void GetUnionField(const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "/**\n";
+ code += Indent + " * @return" + GenTypeBasic(field.value.type) + "\n";
+ code += Indent + " */\n";
+ code += Indent + "public function get";
+ code += MakeCamel(field.name) + "($obj)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$o = $this->__offset(" +
+ NumToString(field.value.offset) + ");\n";
+ code += Indent + Indent;
+ code += "return $o != 0 ? $this->__union($obj, $o) : null;\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Get the value of a vector's struct member.
+ void GetMemberOfVectorOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ code += Indent + "/**\n";
+ code += Indent + " * @return" + GenTypeBasic(field.value.type) + "\n";
+ code += Indent + " */\n";
+ code += Indent + "public function get";
+ code += MakeCamel(field.name);
+ code += "($j)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$o = $this->__offset(" +
+ NumToString(field.value.offset) + ");\n";
+ code += Indent + Indent + "$obj = new ";
+ code += MakeCamel(GenTypeGet(field.value.type)) + "();\n";
+
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT:
+ if (struct_def.fixed) {
+ code += Indent + Indent;
+ code += "return $o != 0 ? $obj->init($this->bb_pos +" +
+ NumToString(field.value.offset) + ", $this->bb) : null;\n";
+ } else {
+ code += Indent + Indent + "return $o != 0 ? $obj->init(";
+ code += field.value.type.struct_def->fixed
+ ? "$o + $this->bb_pos"
+ : "$this->__indirect($o + $this->bb_pos)";
+ code += ", $this->bb) : null;\n";
+ }
+ break;
+ case BASE_TYPE_STRING:
+ code += "// base_type_string\n";
+ // TODO(chobie): do we need this?
+ break;
+ case BASE_TYPE_VECTOR:
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ code += Indent + Indent + "return $o != 0 ? $obj->init(";
+ if (vectortype.struct_def->fixed) {
+ code += "$this->__vector($o) + $j *";
+ code += NumToString(InlineSize(vectortype));
+ } else {
+ code += "$this->__indirect($this->__vector($o) + $j * ";
+ code += NumToString(InlineSize(vectortype)) + ")";
+ }
+ code += ", $this->bb) : null;\n";
+ }
+ break;
+ case BASE_TYPE_UNION:
+ code += Indent + Indent + "return $o != 0 ? $this->";
+ code += GenGetter(field.value.type) + "($obj, $o); null;\n";
+ break;
+ default: break;
+ }
+
+ code += Indent + "}\n\n";
+ }
+
+ // Get the value of a vector's non-struct member. Uses a named return
+ // argument to conveniently set the zero value for the result.
+ void GetMemberOfVectorOfNonStruct(const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ code += Indent + "/**\n";
+ code += Indent + " * @param int offset\n";
+ code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
+ code += Indent + " */\n";
+ code += Indent + "public function get";
+ code += MakeCamel(field.name);
+ code += "($j)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$o = $this->__offset(" +
+ NumToString(field.value.offset) + ");\n";
+
+ if (IsString(field.value.type.VectorType())) {
+ code += Indent + Indent;
+ code += "return $o != 0 ? $this->__string($this->__vector($o) + $j * ";
+ code += NumToString(InlineSize(vectortype)) + ") : ";
+ code += GenDefaultValue(field.value) + ";\n";
+ } else {
+ code += Indent + Indent + "return $o != 0 ? $this->bb->get";
+ code += MakeCamel(GenTypeGet(field.value.type));
+ code += "($this->__vector($o) + $j * ";
+ code += NumToString(InlineSize(vectortype)) + ") : ";
+ code += GenDefaultValue(field.value) + ";\n";
+ }
+ code += Indent + "}\n\n";
+ }
+
+ // Get the value of a vector's union member. Uses a named return
+ // argument to conveniently set the zero value for the result.
+ void GetMemberOfVectorOfUnion(const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ code += Indent + "/**\n";
+ code += Indent + " * @param int offset\n";
+ code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
+ code += Indent + " */\n";
+ code += Indent + "public function get";
+ code += MakeCamel(field.name);
+ code += "($j, $obj)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$o = $this->__offset(" +
+ NumToString(field.value.offset) + ");\n";
+ code += Indent + Indent + "return $o != 0 ? ";
+ code += "$this->__union($obj, $this->__vector($o) + $j * ";
+ code += NumToString(InlineSize(vectortype)) + " - $this->bb_pos) : null;\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Recursively generate arguments for a constructor, to deal with nested
+ // structs.
+ static void StructBuilderArgs(const StructDef &struct_def,
+ const char *nameprefix, std::string *code_ptr) {
+ 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.
+ StructBuilderArgs(*field.value.type.struct_def,
+ (nameprefix + (field.name + "_")).c_str(), code_ptr);
+ } else {
+ std::string &code = *code_ptr;
+ code += std::string(", $") + nameprefix;
+ code += MakeCamel(field.name, false);
+ }
+ }
+ }
+
+ // Recursively generate struct construction statements and instert manual
+ // padding.
+ static void StructBuilderBody(const StructDef &struct_def,
+ const char *nameprefix, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += Indent + Indent + "$builder->prep(";
+ code += NumToString(struct_def.minalign) + ", ";
+ code += NumToString(struct_def.bytesize) + ");\n";
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ auto &field = **it;
+ if (field.padding) {
+ code += Indent + Indent + "$builder->pad(";
+ code += NumToString(field.padding) + ");\n";
+ }
+ if (IsStruct(field.value.type)) {
+ StructBuilderBody(*field.value.type.struct_def,
+ (nameprefix + (field.name + "_")).c_str(), code_ptr);
+ } else {
+ code += Indent + Indent + "$builder->put" + GenMethod(field) + "($";
+ code += nameprefix + MakeCamel(field.name, false) + ");\n";
+ }
+ }
+ }
+
+ // Get the value of a table's starting offset.
+ static void GetStartOfTable(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "/**\n";
+ code += Indent + " * @param FlatBufferBuilder $builder\n";
+ code += Indent + " * @return void\n";
+ code += Indent + " */\n";
+ code += Indent + "public static function start" + struct_def.name;
+ code += "(FlatBufferBuilder $builder)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$builder->StartObject(";
+ code += NumToString(struct_def.fields.vec.size());
+ code += ");\n";
+ code += Indent + "}\n\n";
+
+ code += Indent + "/**\n";
+ code += Indent + " * @param FlatBufferBuilder $builder\n";
+ code += Indent + " * @return " + struct_def.name + "\n";
+ code += Indent + " */\n";
+ code += Indent + "public static function create" + struct_def.name;
+ code += "(FlatBufferBuilder $builder, ";
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+
+ if (field.deprecated) continue;
+ code += "$" + field.name;
+ if (it != struct_def.fields.vec.begin()) { code += ", "; }
+ }
+ code += ")\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$builder->startObject(";
+ code += NumToString(struct_def.fields.vec.size());
+ code += ");\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ code += Indent + Indent + "self::add";
+ code += MakeCamel(field.name) + "($builder, $" + field.name + ");\n";
+ }
+
+ code += Indent + Indent + "$o = $builder->endObject();\n";
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (!field.deprecated && field.IsRequired()) {
+ code += Indent + Indent + "$builder->required($o, ";
+ code += NumToString(field.value.offset);
+ code += "); // " + field.name + "\n";
+ }
+ }
+ code += Indent + Indent + "return $o;\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Set the value of a table's field.
+ static void BuildFieldOfTable(const FieldDef &field, const size_t offset,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "/**\n";
+ code += Indent + " * @param FlatBufferBuilder $builder\n";
+ code += Indent + " * @param " + GenTypeBasic(field.value.type) + "\n";
+ code += Indent + " * @return void\n";
+ code += Indent + " */\n";
+ code += Indent + "public static function ";
+ code += "add" + MakeCamel(field.name);
+ code += "(FlatBufferBuilder $builder, ";
+ code += "$" + MakeCamel(field.name, false);
+ code += ")\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$builder->add";
+ code += GenMethod(field) + "X(";
+ code += NumToString(offset) + ", ";
+
+ code += "$" + MakeCamel(field.name, false);
+ code += ", ";
+
+ if (field.value.type.base_type == BASE_TYPE_BOOL) {
+ code += "false";
+ } else {
+ code += field.value.constant;
+ }
+ code += ");\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Set the value of one of the members of a table's vector.
+ static void BuildVectorOfTable(const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ auto vector_type = field.value.type.VectorType();
+ auto alignment = InlineAlignment(vector_type);
+ auto elem_size = InlineSize(vector_type);
+ code += Indent + "/**\n";
+ code += Indent + " * @param FlatBufferBuilder $builder\n";
+ code += Indent + " * @param array offset array\n";
+ code += Indent + " * @return int vector offset\n";
+ code += Indent + " */\n";
+ code += Indent + "public static function create";
+ code += MakeCamel(field.name);
+ code += "Vector(FlatBufferBuilder $builder, array $data)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$builder->startVector(";
+ code += NumToString(elem_size);
+ code += ", count($data), " + NumToString(alignment);
+ code += ");\n";
+ code += Indent + Indent;
+ code += "for ($i = count($data) - 1; $i >= 0; $i--) {\n";
+ if (IsScalar(field.value.type.VectorType().base_type)) {
+ code += Indent + Indent + Indent;
+ code += "$builder->put";
+ code += MakeCamel(GenTypeBasic(field.value.type.VectorType()));
+ code += "($data[$i]);\n";
+ } else {
+ code += Indent + Indent + Indent;
+ code += "$builder->putOffset($data[$i]);\n";
+ }
+ code += Indent + Indent + "}\n";
+ code += Indent + Indent + "return $builder->endVector();\n";
+ code += Indent + "}\n\n";
+
+ code += Indent + "/**\n";
+ code += Indent + " * @param FlatBufferBuilder $builder\n";
+ code += Indent + " * @param int $numElems\n";
+ code += Indent + " * @return void\n";
+ code += Indent + " */\n";
+ code += Indent + "public static function start";
+ code += MakeCamel(field.name);
+ code += "Vector(FlatBufferBuilder $builder, $numElems)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$builder->startVector(";
+ code += NumToString(elem_size);
+ code += ", $numElems, " + NumToString(alignment);
+ code += ");\n";
+ code += Indent + "}\n\n";
+ }
+
+ // Get the offset of the end of a table.
+ void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += Indent + "/**\n";
+ code += Indent + " * @param FlatBufferBuilder $builder\n";
+ code += Indent + " * @return int table offset\n";
+ code += Indent + " */\n";
+ code += Indent + "public static function end" + struct_def.name;
+ code += "(FlatBufferBuilder $builder)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$o = $builder->endObject();\n";
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (!field.deprecated && field.IsRequired()) {
+ code += Indent + Indent + "$builder->required($o, ";
+ code += NumToString(field.value.offset);
+ code += "); // " + field.name + "\n";
+ }
+ }
+ code += Indent + Indent + "return $o;\n";
+ code += Indent + "}\n";
+
+ if (parser_.root_struct_def_ == &struct_def) {
+ code += "\n";
+ code += Indent + "public static function finish";
+ code += struct_def.name;
+ code += "Buffer(FlatBufferBuilder $builder, $offset)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$builder->finish($offset";
+
+ if (parser_.file_identifier_.length())
+ code += ", \"" + parser_.file_identifier_ + "\"";
+ code += ");\n";
+ code += Indent + "}\n";
+ }
+ }
+
+ // Generate a struct field, conditioned on its child type(s).
+ void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ GenComment(field.doc_comment, code_ptr, nullptr, Indent.c_str());
+
+ if (IsScalar(field.value.type.base_type)) {
+ if (struct_def.fixed) {
+ GetScalarFieldOfStruct(field, code_ptr);
+ } else {
+ GetScalarFieldOfTable(field, code_ptr);
+ }
+ } else {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT:
+ if (struct_def.fixed) {
+ GetStructFieldOfStruct(field, code_ptr);
+ } else {
+ GetStructFieldOfTable(field, code_ptr);
+ }
+ break;
+ case BASE_TYPE_STRING: GetStringField(field, code_ptr); break;
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ if (vectortype.base_type == BASE_TYPE_UNION) {
+ GetMemberOfVectorOfUnion(field, code_ptr);
+ } else if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetMemberOfVectorOfNonStruct(field, code_ptr);
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: GetUnionField(field, code_ptr); break;
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+ if (IsVector(field.value.type)) {
+ GetVectorLen(field, code_ptr);
+ if (field.value.type.element == BASE_TYPE_UCHAR) {
+ GetUByte(field, code_ptr);
+ }
+ }
+ }
+
+ // Generate table constructors, conditioned on its members' types.
+ void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) {
+ GetStartOfTable(struct_def, code_ptr);
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ auto offset = it - struct_def.fields.vec.begin();
+ if (field.value.type.base_type == BASE_TYPE_UNION) {
+ std::string &code = *code_ptr;
+ code += Indent + "public static function add";
+ code += MakeCamel(field.name);
+ code += "(FlatBufferBuilder $builder, $offset)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "$builder->addOffsetX(";
+ code += NumToString(offset) + ", $offset, 0);\n";
+ code += Indent + "}\n\n";
+ } else {
+ BuildFieldOfTable(field, offset, code_ptr);
+ }
+ if (IsVector(field.value.type)) { BuildVectorOfTable(field, code_ptr); }
+ }
+
+ GetEndOffsetOnTable(struct_def, code_ptr);
+ }
+
+ // Generate struct or table methods.
+ void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
+ if (struct_def.generated) return;
+
+ GenComment(struct_def.doc_comment, code_ptr, nullptr);
+ BeginClass(struct_def, code_ptr);
+
+ if (!struct_def.fixed) {
+ // Generate a special accessor for the table that has been declared as
+ // the root type.
+ NewRootTypeFromBuffer(struct_def, code_ptr);
+ }
+
+ std::string &code = *code_ptr;
+ if (!struct_def.fixed) {
+ if (parser_.file_identifier_.length()) {
+ // Return the identifier
+ code += Indent + "public static function " + struct_def.name;
+ code += "Identifier()\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "return \"";
+ code += parser_.file_identifier_ + "\";\n";
+ code += Indent + "}\n\n";
+
+ // Check if a buffer has the identifier.
+ code += Indent + "public static function " + struct_def.name;
+ code += "BufferHasIdentifier(ByteBuffer $buf)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "return self::";
+ code += "__has_identifier($buf, self::";
+ code += struct_def.name + "Identifier());\n";
+ code += Indent + "}\n\n";
+ }
+
+ if (parser_.file_extension_.length()) {
+ // Return the extension
+ code += Indent + "public static function " + struct_def.name;
+ code += "Extension()\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "return \"" + parser_.file_extension_;
+ code += "\";\n";
+ code += Indent + "}\n\n";
+ }
+ }
+
+ // Generate the Init method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ InitializeExisting(struct_def, code_ptr);
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ GenStructAccessor(struct_def, field, code_ptr);
+ }
+
+ if (struct_def.fixed) {
+ // create a struct constructor function
+ GenStructBuilder(struct_def, code_ptr);
+ } else {
+ // Create a set of functions that allow table construction.
+ GenTableBuilders(struct_def, code_ptr);
+ }
+ EndClass(code_ptr);
+ }
+
+ // Generate enum declarations.
+ static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
+ if (enum_def.generated) return;
+
+ GenComment(enum_def.doc_comment, code_ptr, nullptr);
+ BeginEnum(enum_def.name, code_ptr);
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ GenComment(ev.doc_comment, code_ptr, nullptr, Indent.c_str());
+ EnumMember(enum_def, ev, code_ptr);
+ }
+
+ std::string &code = *code_ptr;
+ code += "\n";
+ code += Indent + "private static $names = array(\n";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ code += Indent + Indent + enum_def.name + "::" + ev.name + "=>" + "\"" +
+ ev.name + "\",\n";
+ }
+
+ code += Indent + ");\n\n";
+ code += Indent + "public static function Name($e)\n";
+ code += Indent + "{\n";
+ code += Indent + Indent + "if (!isset(self::$names[$e])) {\n";
+ code += Indent + Indent + Indent + "throw new \\Exception();\n";
+ code += Indent + Indent + "}\n";
+ code += Indent + Indent + "return self::$names[$e];\n";
+ code += Indent + "}\n";
+ EndEnum(code_ptr);
+ }
+
+ // Returns the function name that is able to read a value of the given type.
+ static std::string GenGetter(const Type &type) {
+ 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 GenGetter(type.VectorType());
+ default: return "Get";
+ }
+ }
+
+ // Returns the method name for use with add/put calls.
+ static std::string GenMethod(const FieldDef &field) {
+ return IsScalar(field.value.type.base_type)
+ ? MakeCamel(GenTypeBasic(field.value.type))
+ : (IsStruct(field.value.type) ? "Struct" : "Offset");
+ }
+
+ static std::string GenTypeBasic(const Type &type) {
+ // clang-format off
+ static const char *ctypename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
+ CTYPE, JTYPE, GTYPE, NTYPE, ...) \
+ #NTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+ return ctypename[type.base_type];
+ }
+
+ std::string GenDefaultValue(const Value &value) {
+ if (value.type.enum_def) {
+ if (auto val = value.type.enum_def->FindByValue(value.constant)) {
+ return WrapInNameSpace(*value.type.enum_def) + "::" + val->name;
+ }
+ }
+
+ switch (value.type.base_type) {
+ case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true";
+
+ case BASE_TYPE_STRING: return "null";
+
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG:
+ if (value.constant != "0") {
+ int64_t constant = StringToInt(value.constant.c_str());
+ return NumToString(constant);
+ }
+ return "0";
+
+ default: return value.constant;
+ }
+ }
+
+ static std::string GenTypePointer(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return "string";
+ case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
+ case BASE_TYPE_STRUCT: return type.struct_def->name;
+ case BASE_TYPE_UNION:
+ // fall through
+ default: return "Table";
+ }
+ }
+
+ static std::string GenTypeGet(const Type &type) {
+ return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
+ }
+
+ // Create a struct with a builder and the struct's arguments.
+ static void GenStructBuilder(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "\n";
+ code += Indent + "/**\n";
+ code += Indent + " * @return int offset\n";
+ code += Indent + " */\n";
+ code += Indent + "public static function create" + struct_def.name;
+ code += "(FlatBufferBuilder $builder";
+ StructBuilderArgs(struct_def, "", code_ptr);
+ code += ")\n";
+ code += Indent + "{\n";
+
+ StructBuilderBody(struct_def, "", code_ptr);
+
+ code += Indent + Indent + "return $builder->offset();\n";
+ code += Indent + "}\n";
+ }
+};
+} // namespace php
+
+bool GeneratePhp(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ php::PhpGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_python.cpp b/contrib/libs/flatbuffers/src/idl_gen_python.cpp
new file mode 100644
index 0000000000..b3f394ebf9
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_python.cpp
@@ -0,0 +1,1782 @@
+/*
+ * 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 <cctype>
+#include <set>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+namespace python {
+
+// Hardcode spaces per indentation.
+const CommentConfig def_comment = { nullptr, "#", nullptr };
+const std::string Indent = " ";
+
+class PythonGenerator : public BaseGenerator {
+ public:
+ PythonGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "" /* not used */,
+ "" /* not used */, "py"),
+ float_const_gen_("float('nan')", "float('inf')", "float('-inf')") {
+ static const char *const keywords[] = {
+ "False", "None", "True", "and", "as", "assert", "break",
+ "class", "continue", "def", "del", "elif", "else", "except",
+ "finally", "for", "from", "global", "if", "import", "in",
+ "is", "lambda", "nonlocal", "not", "or", "pass", "raise",
+ "return", "try", "while", "with", "yield"
+ };
+ keywords_.insert(std::begin(keywords), std::end(keywords));
+ }
+
+ // Most field accessors need to retrieve and test the field offset first,
+ // this is the prefix code for that.
+ std::string OffsetPrefix(const FieldDef &field) {
+ return "\n" + Indent + Indent +
+ "o = flatbuffers.number_types.UOffsetTFlags.py_type" +
+ "(self._tab.Offset(" + NumToString(field.value.offset) + "))\n" +
+ Indent + Indent + "if o != 0:\n";
+ }
+
+ // Begin a class declaration.
+ void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += "class " + NormalizedName(struct_def) + "(object):\n";
+ code += Indent + "__slots__ = ['_tab']";
+ code += "\n\n";
+ }
+
+ // Begin enum code with a class declaration.
+ void BeginEnum(const std::string &class_name, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += "class " + class_name + "(object):\n";
+ }
+
+ std::string EscapeKeyword(const std::string &name) const {
+ return keywords_.find(name) == keywords_.end() ? name : name + "_";
+ }
+
+ std::string NormalizedName(const Definition &definition) const {
+ return EscapeKeyword(definition.name);
+ }
+
+ std::string NormalizedName(const EnumVal &ev) const {
+ return EscapeKeyword(ev.name);
+ }
+
+ // Converts the name of a definition into upper Camel format.
+ std::string MakeUpperCamel(const Definition &definition) const {
+ return MakeCamel(NormalizedName(definition), true);
+ }
+
+ // Converts the name of a definition into lower Camel format.
+ std::string MakeLowerCamel(const Definition &definition) const {
+ auto name = MakeCamel(NormalizedName(definition), false);
+ name[0] = CharToLower(name[0]);
+ return name;
+ }
+
+ // Starts a new line and then indents.
+ std::string GenIndents(int num) {
+ return "\n" + std::string(num * Indent.length(), ' ');
+ }
+
+ // A single enum member.
+ void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += Indent;
+ code += NormalizedName(ev);
+ code += " = ";
+ code += enum_def.ToString(ev) + "\n";
+ }
+
+ // End enum code.
+ void EndEnum(std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += "\n";
+ }
+
+ // Initialize a new struct or table from existing data.
+ void NewRootTypeFromBuffer(const StructDef &struct_def,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+
+ code += Indent + "@classmethod\n";
+ code += Indent + "def GetRootAs";
+ code += "(cls, buf, offset=0):";
+ code += "\n";
+ code += Indent + Indent;
+ code += "n = flatbuffers.encode.Get";
+ code += "(flatbuffers.packer.uoffset, buf, offset)\n";
+ code += Indent + Indent + "x = " + NormalizedName(struct_def) + "()\n";
+ code += Indent + Indent + "x.Init(buf, n + offset)\n";
+ code += Indent + Indent + "return x\n";
+ code += "\n";
+
+ // Add an alias with the old name
+ code += Indent + "@classmethod\n";
+ code += Indent + "def GetRootAs";
+ code += NormalizedName(struct_def);
+ code += "(cls, buf, offset=0):\n";
+ code += Indent + Indent + "\"\"\"This method is deprecated. Please switch to GetRootAs.\"\"\"\n";
+ code += Indent + Indent + "return cls.GetRootAs(buf, offset)\n";
+ }
+
+ // Initialize an existing object with other data, to avoid an allocation.
+ void InitializeExisting(const StructDef &struct_def, std::string *code_ptr) {
+ auto &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += "Init(self, buf, pos):\n";
+ code += Indent + Indent + "self._tab = flatbuffers.table.Table(buf, pos)\n";
+ code += "\n";
+ }
+
+ // Get the length of a vector.
+ void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field)) + "Length(self";
+ code += "):" + OffsetPrefix(field);
+ code += Indent + Indent + Indent + "return self._tab.VectorLen(o)\n";
+ code += Indent + Indent + "return 0\n\n";
+ }
+
+ // Determines whether a vector is none or not.
+ void GetVectorIsNone(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field)) + "IsNone(self";
+ code += "):";
+ code += GenIndents(2) +
+ "o = flatbuffers.number_types.UOffsetTFlags.py_type" +
+ "(self._tab.Offset(" + NumToString(field.value.offset) + "))";
+ code += GenIndents(2) + "return o == 0";
+ code += "\n\n";
+ }
+
+ // Get the value of a struct's scalar.
+ void GetScalarFieldOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ std::string getter = GenGetter(field.value.type);
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(self): return " + getter;
+ code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
+ code += NumToString(field.value.offset) + "))\n";
+ }
+
+ // Get the value of a table's scalar.
+ void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ std::string getter = GenGetter(field.value.type);
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(self):";
+ code += OffsetPrefix(field);
+ getter += "o + self._tab.Pos)";
+ auto is_bool = IsBool(field.value.type.base_type);
+ if (is_bool) { getter = "bool(" + getter + ")"; }
+ code += Indent + Indent + Indent + "return " + getter + "\n";
+ std::string default_value;
+ if (is_bool) {
+ default_value = field.value.constant == "0" ? "False" : "True";
+ } else {
+ default_value = IsFloat(field.value.type.base_type)
+ ? float_const_gen_.GenFloatConstant(field)
+ : field.value.constant;
+ }
+ code += Indent + Indent + "return " + default_value + "\n\n";
+ }
+
+ // Get a struct by initializing an existing struct.
+ // Specific to Struct.
+ void GetStructFieldOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(self, obj):\n";
+ code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
+ code += NumToString(field.value.offset) + ")";
+ code += "\n" + Indent + Indent + "return obj\n\n";
+ }
+
+ // Get the value of a fixed size array.
+ void GetArrayOfStruct(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ const auto vec_type = field.value.type.VectorType();
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ if (IsStruct(vec_type)) {
+ code += "(self, obj, i):\n";
+ code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
+ code += NumToString(field.value.offset) + " + i * ";
+ code += NumToString(InlineSize(vec_type));
+ code += ")\n" + Indent + Indent + "return obj\n\n";
+ } else {
+ auto getter = GenGetter(vec_type);
+ code += "(self): return [" + getter;
+ code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
+ code += NumToString(field.value.offset) + " + i * ";
+ code += NumToString(InlineSize(vec_type));
+ code += ")) for i in range(";
+ code += NumToString(field.value.type.fixed_length) + ")]\n";
+ }
+ }
+
+ // Get a struct by initializing an existing struct.
+ // Specific to Table.
+ void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(self):";
+ code += OffsetPrefix(field);
+ if (field.value.type.struct_def->fixed) {
+ code += Indent + Indent + Indent + "x = o + self._tab.Pos\n";
+ } else {
+ code += Indent + Indent + Indent;
+ code += "x = self._tab.Indirect(o + self._tab.Pos)\n";
+ }
+ if (parser_.opts.include_dependence_headers) {
+ code += Indent + Indent + Indent;
+ code += "from " + GenPackageReference(field.value.type) + " import " +
+ TypeName(field) + "\n";
+ }
+ code += Indent + Indent + Indent + "obj = " + TypeName(field) + "()\n";
+ code += Indent + Indent + Indent + "obj.Init(self._tab.Bytes, x)\n";
+ code += Indent + Indent + Indent + "return obj\n";
+ code += Indent + Indent + "return None\n\n";
+ }
+
+ // Get the value of a string.
+ void GetStringField(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(self):";
+ code += OffsetPrefix(field);
+ code += Indent + Indent + Indent + "return " + GenGetter(field.value.type);
+ code += "o + self._tab.Pos)\n";
+ code += Indent + Indent + "return None\n\n";
+ }
+
+ // Get the value of a union from an object.
+ void GetUnionField(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field)) + "(self):";
+ code += OffsetPrefix(field);
+
+ // TODO(rw): this works and is not the good way to it:
+ bool is_native_table = TypeName(field) == "*flatbuffers.Table";
+ if (is_native_table) {
+ code +=
+ Indent + Indent + Indent + "from flatbuffers.table import Table\n";
+ } else if (parser_.opts.include_dependence_headers) {
+ code += Indent + Indent + Indent;
+ code += "from " + GenPackageReference(field.value.type) + " import " +
+ TypeName(field) + "\n";
+ }
+ code += Indent + Indent + Indent + "obj = Table(bytearray(), 0)\n";
+ code += Indent + Indent + Indent + GenGetter(field.value.type);
+ code += "obj, o)\n" + Indent + Indent + Indent + "return obj\n";
+ code += Indent + Indent + "return None\n\n";
+ }
+
+ // Generate the package reference when importing a struct or enum from its
+ // module.
+ std::string GenPackageReference(const Type &type) {
+ Namespace *namespaces;
+ if (type.struct_def) {
+ namespaces = type.struct_def->defined_namespace;
+ } else if (type.enum_def) {
+ namespaces = type.enum_def->defined_namespace;
+ } else {
+ return "." + GenTypeGet(type);
+ }
+
+ return namespaces->GetFullyQualifiedName(GenTypeGet(type));
+ }
+
+ // Get the value of a vector's struct member.
+ void GetMemberOfVectorOfStruct(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(self, j):" + OffsetPrefix(field);
+ code += Indent + Indent + Indent + "x = self._tab.Vector(o)\n";
+ code += Indent + Indent + Indent;
+ code += "x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * ";
+ code += NumToString(InlineSize(vectortype)) + "\n";
+ if (!(vectortype.struct_def->fixed)) {
+ code += Indent + Indent + Indent + "x = self._tab.Indirect(x)\n";
+ }
+ if (parser_.opts.include_dependence_headers) {
+ code += Indent + Indent + Indent;
+ code += "from " + GenPackageReference(field.value.type) + " import " +
+ TypeName(field) + "\n";
+ }
+ code += Indent + Indent + Indent + "obj = " + TypeName(field) + "()\n";
+ code += Indent + Indent + Indent + "obj.Init(self._tab.Bytes, x)\n";
+ code += Indent + Indent + Indent + "return obj\n";
+ code += Indent + Indent + "return None\n\n";
+ }
+
+ // Get the value of a vector's non-struct member. Uses a named return
+ // argument to conveniently set the zero value for the result.
+ void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(self, j):";
+ code += OffsetPrefix(field);
+ code += Indent + Indent + Indent + "a = self._tab.Vector(o)\n";
+ code += Indent + Indent + Indent;
+ code += "return " + GenGetter(field.value.type);
+ code += "a + flatbuffers.number_types.UOffsetTFlags.py_type(j * ";
+ code += NumToString(InlineSize(vectortype)) + "))\n";
+ if (IsString(vectortype)) {
+ code += Indent + Indent + "return \"\"\n";
+ } else {
+ code += Indent + Indent + "return 0\n";
+ }
+ code += "\n";
+ }
+
+ // Returns a non-struct vector as a numpy array. Much faster
+ // than iterating over the vector element by element.
+ void GetVectorOfNonStructAsNumpy(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ // Currently, we only support accessing as numpy array if
+ // the vector type is a scalar.
+ if (!(IsScalar(vectortype.base_type))) { return; }
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field)) + "AsNumpy(self):";
+ code += OffsetPrefix(field);
+
+ code += Indent + Indent + Indent;
+ code += "return ";
+ code += "self._tab.GetVectorAsNumpy(flatbuffers.number_types.";
+ code += MakeCamel(GenTypeGet(field.value.type));
+ code += "Flags, o)\n";
+
+ if (IsString(vectortype)) {
+ code += Indent + Indent + "return \"\"\n";
+ } else {
+ code += Indent + Indent + "return 0\n";
+ }
+ code += "\n";
+ }
+
+ // Returns a nested flatbuffer as itself.
+ void GetVectorAsNestedFlatbuffer(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ auto nested = field.attributes.Lookup("nested_flatbuffer");
+ if (!nested) { return; } // There is no nested flatbuffer.
+
+ std::string unqualified_name = nested->constant;
+ std::string qualified_name = nested->constant;
+ auto nested_root = parser_.LookupStruct(nested->constant);
+ if (nested_root == nullptr) {
+ qualified_name =
+ parser_.current_namespace_->GetFullyQualifiedName(nested->constant);
+ nested_root = parser_.LookupStruct(qualified_name);
+ }
+ FLATBUFFERS_ASSERT(nested_root); // Guaranteed to exist by parser.
+ (void)nested_root;
+
+ auto &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field)) + "NestedRoot(self):";
+
+ code += OffsetPrefix(field);
+
+ code += Indent + Indent + Indent;
+ code += "from " + qualified_name + " import " + unqualified_name + "\n";
+ code += Indent + Indent + Indent + "return " + unqualified_name;
+ code += ".GetRootAs";
+ code += "(self._tab.Bytes, self._tab.Vector(o))\n";
+ code += Indent + Indent + "return 0\n";
+ code += "\n";
+ }
+
+ // Begin the creator function signature.
+ void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) {
+ auto &code = *code_ptr;
+
+ code += "\n";
+ code += "def Create" + NormalizedName(struct_def);
+ code += "(builder";
+ }
+
+ // Recursively generate arguments for a constructor, to deal with nested
+ // structs.
+ void StructBuilderArgs(const StructDef &struct_def,
+ const std::string nameprefix,
+ const std::string namesuffix, bool has_field_name,
+ const std::string fieldname_suffix,
+ std::string *code_ptr) {
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ const auto &field_type = field.value.type;
+ const auto &type =
+ IsArray(field_type) ? field_type.VectorType() : field_type;
+ if (IsStruct(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.
+ auto subprefix = nameprefix;
+ if (has_field_name) {
+ subprefix += NormalizedName(field) + fieldname_suffix;
+ }
+ StructBuilderArgs(*field.value.type.struct_def, subprefix, namesuffix,
+ has_field_name, fieldname_suffix, code_ptr);
+ } else {
+ auto &code = *code_ptr;
+ code += std::string(", ") + nameprefix;
+ if (has_field_name) { code += MakeCamel(NormalizedName(field), false); }
+ code += namesuffix;
+ }
+ }
+ }
+
+ // End the creator function signature.
+ void EndBuilderArgs(std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += "):\n";
+ }
+
+ // Recursively generate struct construction statements and instert manual
+ // padding.
+ void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
+ std::string *code_ptr, size_t index = 0,
+ bool in_array = false) {
+ auto &code = *code_ptr;
+ std::string indent(index * 4, ' ');
+ code +=
+ indent + " builder.Prep(" + NumToString(struct_def.minalign) + ", ";
+ code += NumToString(struct_def.bytesize) + ")\n";
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ auto &field = **it;
+ const auto &field_type = field.value.type;
+ const auto &type =
+ IsArray(field_type) ? field_type.VectorType() : field_type;
+ if (field.padding)
+ code +=
+ indent + " builder.Pad(" + NumToString(field.padding) + ")\n";
+ if (IsStruct(field_type)) {
+ StructBuilderBody(*field_type.struct_def,
+ (nameprefix + (NormalizedName(field) + "_")).c_str(),
+ code_ptr, index, in_array);
+ } else {
+ const auto index_var = "_idx" + NumToString(index);
+ if (IsArray(field_type)) {
+ code += indent + " for " + index_var + " in range(";
+ code += NumToString(field_type.fixed_length);
+ code += " , 0, -1):\n";
+ in_array = true;
+ }
+ if (IsStruct(type)) {
+ StructBuilderBody(
+ *field_type.struct_def,
+ (nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr,
+ index + 1, in_array);
+ } else {
+ code += IsArray(field_type) ? " " : "";
+ code += indent + " builder.Prepend" + GenMethod(field) + "(";
+ code += nameprefix + MakeCamel(NormalizedName(field), false);
+ size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
+ for (size_t i = 0; in_array && i < array_cnt; i++) {
+ code += "[_idx" + NumToString(i) + "-1]";
+ }
+ code += ")\n";
+ }
+ }
+ }
+ }
+
+ void EndBuilderBody(std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += " return builder.Offset()\n";
+ }
+
+ // Get the value of a table's starting offset.
+ void GetStartOfTable(const StructDef &struct_def, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += "def Start(builder): ";
+ code += "builder.StartObject(";
+ code += NumToString(struct_def.fields.vec.size());
+ code += ")\n";
+
+ // Add alias with the old name.
+ code += "def " + NormalizedName(struct_def) + "Start(builder):\n";
+ code += Indent + "\"\"\"This method is deprecated. Please switch to Start.\"\"\"\n";
+ code += Indent + "return Start(builder)\n";
+ }
+
+ // Set the value of a table's field.
+ void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
+ const size_t offset, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += "def Add" + MakeCamel(NormalizedName(field));
+ code += "(builder, ";
+ code += MakeCamel(NormalizedName(field), false);
+ code += "): ";
+ code += "builder.Prepend";
+ code += GenMethod(field) + "Slot(";
+ code += NumToString(offset) + ", ";
+ if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
+ code += "flatbuffers.number_types.UOffsetTFlags.py_type";
+ code += "(";
+ code += MakeCamel(NormalizedName(field), false) + ")";
+ } else {
+ code += MakeCamel(NormalizedName(field), false);
+ }
+ code += ", ";
+ code += IsFloat(field.value.type.base_type)
+ ? float_const_gen_.GenFloatConstant(field)
+ : field.value.constant;
+ code += ")\n";
+
+ // Add alias with the old name.
+ code += "def " + NormalizedName(struct_def) + "Add" + MakeCamel(NormalizedName(field));
+ code += "(builder, ";
+ code += MakeCamel(NormalizedName(field), false);
+ code += "):\n";
+ code += Indent + "\"\"\"This method is deprecated. Please switch to Add";
+ code += MakeCamel(NormalizedName(field)) + ".\"\"\"\n";
+ code += Indent + "return Add" + MakeCamel(NormalizedName(field));
+ code += "(builder, ";
+ code += MakeCamel(NormalizedName(field), false);
+ code += ")\n";
+
+ // Add alias with the old name.
+ }
+
+ // Set the value of one of the members of a table's vector.
+ void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += "def Start";
+ code += MakeCamel(NormalizedName(field));
+ code += "Vector(builder, numElems): return builder.StartVector(";
+ auto vector_type = field.value.type.VectorType();
+ auto alignment = InlineAlignment(vector_type);
+ auto elem_size = InlineSize(vector_type);
+ code += NumToString(elem_size);
+ code += ", numElems, " + NumToString(alignment);
+ code += ")\n";
+
+ // Add alias with the old name.
+ code += "def " + NormalizedName(struct_def) + "Start";
+ code += MakeCamel(NormalizedName(field));
+ code += "Vector(builder, numElems):\n";
+ code += Indent + "\"\"\"This method is deprecated. Please switch to Start.\"\"\"\n";
+ code += Indent + "return Start";
+ code += MakeCamel(NormalizedName(field));
+ code += "Vector(builder, numElems)\n";
+ }
+
+ // Set the value of one of the members of a table's vector and fills in the
+ // elements from a bytearray. This is for simplifying the use of nested
+ // flatbuffers.
+ void BuildVectorOfTableFromBytes(const FieldDef &field, std::string *code_ptr) {
+ auto nested = field.attributes.Lookup("nested_flatbuffer");
+ if (!nested) { return; } // There is no nested flatbuffer.
+
+ std::string unqualified_name = nested->constant;
+ std::string qualified_name = nested->constant;
+ auto nested_root = parser_.LookupStruct(nested->constant);
+ if (nested_root == nullptr) {
+ qualified_name =
+ parser_.current_namespace_->GetFullyQualifiedName(nested->constant);
+ nested_root = parser_.LookupStruct(qualified_name);
+ }
+ FLATBUFFERS_ASSERT(nested_root); // Guaranteed to exist by parser.
+ (void)nested_root;
+
+ auto &code = *code_ptr;
+ code += "def MakeVectorFromBytes(builder, bytes):\n";
+ code += Indent + "builder.StartVector(";
+ auto vector_type = field.value.type.VectorType();
+ auto alignment = InlineAlignment(vector_type);
+ auto elem_size = InlineSize(vector_type);
+ code += NumToString(elem_size);
+ code += ", len(bytes), " + NumToString(alignment);
+ code += ")\n";
+ code += Indent + "builder.head = builder.head - len(bytes)\n";
+ code += Indent + "builder.Bytes[builder.head : builder.head + len(bytes)]";
+ code += " = bytes\n";
+ code += Indent + "return builder.EndVector()\n";
+
+ // Add alias with the old name.
+ code += "def Make" + MakeCamel(NormalizedName(field));
+ code += "VectorFromBytes(builder, bytes):\n";
+ code += Indent + "builder.StartVector(";
+ code += NumToString(elem_size);
+ code += ", len(bytes), " + NumToString(alignment);
+ code += ")\n";
+ code += Indent + "builder.head = builder.head - len(bytes)\n";
+ code += Indent + "builder.Bytes[builder.head : builder.head + len(bytes)]";
+ code += " = bytes\n";
+ code += Indent + "return builder.EndVector()\n";
+ }
+
+ // Get the offset of the end of a table.
+ void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += "def End(builder): return builder.EndObject()\n";
+
+ // Add alias with the old name.
+ code += "def " + NormalizedName(struct_def) + "End(builder):\n";
+ code += Indent + "\"\"\"This method is deprecated. Please switch to End.\"\"\"\n";
+ code += Indent + "return End(builder)";
+ }
+
+ // Generate the receiver for function signatures.
+ void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += Indent + "# " + NormalizedName(struct_def) + "\n";
+ code += Indent + "def ";
+ }
+
+ // Generate a struct field, conditioned on its child type(s).
+ void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ GenComment(field.doc_comment, code_ptr, &def_comment, Indent.c_str());
+ if (IsScalar(field.value.type.base_type)) {
+ if (struct_def.fixed) {
+ GetScalarFieldOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetScalarFieldOfTable(struct_def, field, code_ptr);
+ }
+ } else if (IsArray(field.value.type)) {
+ GetArrayOfStruct(struct_def, field, code_ptr);
+ } else {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT:
+ if (struct_def.fixed) {
+ GetStructFieldOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetStructFieldOfTable(struct_def, field, code_ptr);
+ }
+ break;
+ case BASE_TYPE_STRING:
+ GetStringField(struct_def, field, code_ptr);
+ break;
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
+ } else {
+ GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
+ GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
+ GetVectorAsNestedFlatbuffer(struct_def, field, code_ptr);
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+ if (IsVector(field.value.type) || IsArray(field.value.type)) {
+ GetVectorLen(struct_def, field, code_ptr);
+ GetVectorIsNone(struct_def, field, code_ptr);
+ }
+ }
+
+ // Generate struct sizeof.
+ void GenStructSizeOf(const StructDef &struct_def, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += Indent + "@classmethod\n";
+ code += Indent + "def SizeOf(cls):\n";
+ code +=
+ Indent + Indent + "return " + NumToString(struct_def.bytesize) + "\n";
+ code += "\n";
+ }
+
+ // Generate table constructors, conditioned on its members' types.
+ void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) {
+ GetStartOfTable(struct_def, code_ptr);
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ auto offset = it - struct_def.fields.vec.begin();
+ BuildFieldOfTable(struct_def, field, offset, code_ptr);
+ if (IsVector(field.value.type)) {
+ BuildVectorOfTable(struct_def, field, code_ptr);
+ BuildVectorOfTableFromBytes(field, code_ptr);
+ }
+ }
+
+ GetEndOffsetOnTable(struct_def, code_ptr);
+ }
+
+ // Generate function to check for proper file identifier
+ void GenHasFileIdentifier(const StructDef &struct_def,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ std::string escapedID;
+ // In the event any of file_identifier characters are special(NULL, \, etc),
+ // problems occur. To prevent this, convert all chars to their hex-escaped
+ // equivalent.
+ for (auto it = parser_.file_identifier_.begin();
+ it != parser_.file_identifier_.end(); ++it) {
+ escapedID += "\\x" + IntToStringHex(*it, 2);
+ }
+
+ code += Indent + "@classmethod\n";
+ code += Indent + "def " + NormalizedName(struct_def);
+ code += "BufferHasIdentifier(cls, buf, offset, size_prefixed=False):";
+ code += "\n";
+ code += Indent + Indent;
+ code += "return flatbuffers.util.BufferHasIdentifier(buf, offset, b\"";
+ code += escapedID;
+ code += "\", size_prefixed=size_prefixed)\n";
+ code += "\n";
+ }
+
+ // Generates struct or table methods.
+ void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
+ if (struct_def.generated) return;
+
+ GenComment(struct_def.doc_comment, code_ptr, &def_comment);
+ BeginClass(struct_def, code_ptr);
+ if (!struct_def.fixed) {
+ // Generate a special accessor for the table that has been declared as
+ // the root type.
+ NewRootTypeFromBuffer(struct_def, code_ptr);
+ if (parser_.file_identifier_.length()) {
+ // Generate a special function to test file_identifier
+ GenHasFileIdentifier(struct_def, code_ptr);
+ }
+ } else {
+ // Generates the SizeOf method for all structs.
+ GenStructSizeOf(struct_def, code_ptr);
+ }
+ // Generates the Init method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ InitializeExisting(struct_def, code_ptr);
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ GenStructAccessor(struct_def, field, code_ptr);
+ }
+
+ if (struct_def.fixed) {
+ // creates a struct constructor function
+ GenStructBuilder(struct_def, code_ptr);
+ } else {
+ // Creates a set of functions that allow table construction.
+ GenTableBuilders(struct_def, code_ptr);
+ }
+ }
+
+ void GenReceiverForObjectAPI(const StructDef &struct_def,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += GenIndents(1) + "# " + NormalizedName(struct_def) + "T";
+ code += GenIndents(1) + "def ";
+ }
+
+ void BeginClassForObjectAPI(const StructDef &struct_def,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code += "\n";
+ code += "class " + NormalizedName(struct_def) + "T(object):";
+ code += "\n";
+ }
+
+ // Gets the accoresponding python builtin type of a BaseType for scalars and
+ // string.
+ std::string GetBasePythonTypeForScalarAndString(const BaseType &base_type) {
+ if (IsBool(base_type)) {
+ return "bool";
+ } else if (IsFloat(base_type)) {
+ return "float";
+ } else if (IsInteger(base_type)) {
+ return "int";
+ } else if (base_type == BASE_TYPE_STRING) {
+ return "str";
+ } else {
+ FLATBUFFERS_ASSERT(false && "base_type is not a scalar or string type.");
+ return "";
+ }
+ }
+
+ std::string GetDefaultValue(const FieldDef &field) {
+ BaseType base_type = field.value.type.base_type;
+ if (IsBool(base_type)) {
+ return field.value.constant == "0" ? "False" : "True";
+ } else if (IsFloat(base_type)) {
+ return float_const_gen_.GenFloatConstant(field);
+ } else if (IsInteger(base_type)) {
+ return field.value.constant;
+ } else {
+ // For string, struct, and table.
+ return "None";
+ }
+ }
+
+ void GenUnionInit(const FieldDef &field, std::string *field_types_ptr,
+ std::set<std::string> *import_list,
+ std::set<std::string> *import_typing_list) {
+ // Gets all possible types in the union.
+ import_typing_list->insert("Union");
+ auto &field_types = *field_types_ptr;
+ field_types = "Union[";
+
+ std::string separator_string = ", ";
+ auto enum_def = field.value.type.enum_def;
+ for (auto it = enum_def->Vals().begin(); it != enum_def->Vals().end();
+ ++it) {
+ auto &ev = **it;
+ // Union only supports string and table.
+ std::string field_type;
+ switch (ev.union_type.base_type) {
+ case BASE_TYPE_STRUCT:
+ field_type = GenTypeGet(ev.union_type) + "T";
+ if (parser_.opts.include_dependence_headers) {
+ auto package_reference = GenPackageReference(ev.union_type);
+ field_type = package_reference + "." + field_type;
+ import_list->insert("import " + package_reference);
+ }
+ break;
+ case BASE_TYPE_STRING: field_type += "str"; break;
+ case BASE_TYPE_NONE: field_type += "None"; break;
+ default: break;
+ }
+ field_types += field_type + separator_string;
+ }
+
+ // Removes the last separator_string.
+ field_types.erase(field_types.length() - separator_string.size());
+ field_types += "]";
+
+ // Gets the import lists for the union.
+ if (parser_.opts.include_dependence_headers) {
+ // The package reference is generated based on enum_def, instead
+ // of struct_def in field.type. That's why GenPackageReference() is
+ // not used.
+ Namespace *namespaces = field.value.type.enum_def->defined_namespace;
+ auto package_reference = namespaces->GetFullyQualifiedName(
+ MakeUpperCamel(*(field.value.type.enum_def)));
+ auto union_name = MakeUpperCamel(*(field.value.type.enum_def));
+ import_list->insert("import " + package_reference);
+ }
+ }
+
+ void GenStructInit(const FieldDef &field, std::string *field_type_ptr,
+ std::set<std::string> *import_list,
+ std::set<std::string> *import_typing_list) {
+ import_typing_list->insert("Optional");
+ auto &field_type = *field_type_ptr;
+ if (parser_.opts.include_dependence_headers) {
+ auto package_reference = GenPackageReference(field.value.type);
+ field_type = package_reference + "." + TypeName(field) + "T]";
+ import_list->insert("import " + package_reference);
+ } else {
+ field_type = TypeName(field) + "T]";
+ }
+ field_type = "Optional[" + field_type;
+ }
+
+ void GenVectorInit(const FieldDef &field, std::string *field_type_ptr,
+ std::set<std::string> *import_list,
+ std::set<std::string> *import_typing_list) {
+ import_typing_list->insert("List");
+ auto &field_type = *field_type_ptr;
+ auto base_type = field.value.type.VectorType().base_type;
+ if (base_type == BASE_TYPE_STRUCT) {
+ field_type = GenTypeGet(field.value.type.VectorType()) + "T]";
+ if (parser_.opts.include_dependence_headers) {
+ auto package_reference =
+ GenPackageReference(field.value.type.VectorType());
+ field_type = package_reference + "." +
+ GenTypeGet(field.value.type.VectorType()) + "T]";
+ import_list->insert("import " + package_reference);
+ }
+ field_type = "List[" + field_type;
+ } else {
+ field_type =
+ "List[" + GetBasePythonTypeForScalarAndString(base_type) + "]";
+ }
+ }
+
+ void GenInitialize(const StructDef &struct_def, std::string *code_ptr,
+ std::set<std::string> *import_list) {
+ std::string code;
+ std::set<std::string> import_typing_list;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ // Determines field type, default value, and typing imports.
+ auto base_type = field.value.type.base_type;
+ std::string field_type;
+ switch (base_type) {
+ case BASE_TYPE_UNION: {
+ GenUnionInit(field, &field_type, import_list, &import_typing_list);
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ GenStructInit(field, &field_type, import_list, &import_typing_list);
+ break;
+ }
+ case BASE_TYPE_VECTOR:
+ case BASE_TYPE_ARRAY: {
+ GenVectorInit(field, &field_type, import_list, &import_typing_list);
+ break;
+ }
+ default:
+ // Scalar or sting fields.
+ field_type = GetBasePythonTypeForScalarAndString(base_type);
+ break;
+ }
+
+ auto default_value = GetDefaultValue(field);
+ // Wrties the init statement.
+ auto field_instance_name = MakeLowerCamel(field);
+ code += GenIndents(2) + "self." + field_instance_name + " = " +
+ default_value + " # type: " + field_type;
+ }
+
+ // Writes __init__ method.
+ auto &code_base = *code_ptr;
+ GenReceiverForObjectAPI(struct_def, code_ptr);
+ code_base += "__init__(self):";
+ if (code.empty()) {
+ code_base += GenIndents(2) + "pass";
+ } else {
+ code_base += code;
+ }
+ code_base += "\n";
+
+ // Merges the typing imports into import_list.
+ if (!import_typing_list.empty()) {
+ // Adds the try statement.
+ std::string typing_imports = "try:";
+ typing_imports += GenIndents(1) + "from typing import ";
+ std::string separator_string = ", ";
+ for (auto it = import_typing_list.begin(); it != import_typing_list.end();
+ ++it) {
+ const std::string &im = *it;
+ typing_imports += im + separator_string;
+ }
+ // Removes the last separator_string.
+ typing_imports.erase(typing_imports.length() - separator_string.size());
+
+ // Adds the except statement.
+ typing_imports += "\n";
+ typing_imports += "except:";
+ typing_imports += GenIndents(1) + "pass";
+ import_list->insert(typing_imports);
+ }
+
+ // Removes the import of the struct itself, if applied.
+ auto package_reference =
+ struct_def.defined_namespace->GetFullyQualifiedName(
+ MakeUpperCamel(struct_def));
+ auto struct_import = "import " + package_reference;
+ import_list->erase(struct_import);
+ }
+
+ void InitializeFromBuf(const StructDef &struct_def, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto instance_name = MakeLowerCamel(struct_def);
+ auto struct_name = NormalizedName(struct_def);
+
+ code += GenIndents(1) + "@classmethod";
+ code += GenIndents(1) + "def InitFromBuf(cls, buf, pos):";
+ code += GenIndents(2) + instance_name + " = " + struct_name + "()";
+ code += GenIndents(2) + instance_name + ".Init(buf, pos)";
+ code += GenIndents(2) + "return cls.InitFromObj(" + instance_name + ")";
+ code += "\n";
+ }
+
+ void InitializeFromObjForObject(const StructDef &struct_def,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto instance_name = MakeLowerCamel(struct_def);
+ auto struct_name = NormalizedName(struct_def);
+
+ code += GenIndents(1) + "@classmethod";
+ code += GenIndents(1) + "def InitFromObj(cls, " + instance_name + "):";
+ code += GenIndents(2) + "x = " + struct_name + "T()";
+ code += GenIndents(2) + "x._UnPack(" + instance_name + ")";
+ code += GenIndents(2) + "return x";
+ code += "\n";
+ }
+
+ void GenUnPackForStruct(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto struct_instance_name = MakeLowerCamel(struct_def);
+ auto field_instance_name = MakeLowerCamel(field);
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto field_type = TypeName(field);
+
+ if (parser_.opts.include_dependence_headers) {
+ auto package_reference = GenPackageReference(field.value.type);
+ field_type = package_reference + "." + TypeName(field);
+ }
+
+ code += GenIndents(2) + "if " + struct_instance_name + "." +
+ field_accessor_name + "(";
+ // if field is a struct, we need to create an instance for it first.
+ if (struct_def.fixed && field.value.type.base_type == BASE_TYPE_STRUCT) {
+ code += field_type + "()";
+ }
+ code += ") is not None:";
+ code += GenIndents(3) + "self." + field_instance_name + " = " + field_type +
+ "T.InitFromObj(" + struct_instance_name + "." +
+ field_accessor_name + "(";
+ // A struct's accessor requires a struct buf instance.
+ if (struct_def.fixed && field.value.type.base_type == BASE_TYPE_STRUCT) {
+ code += field_type + "()";
+ }
+ code += "))";
+ }
+
+ void GenUnPackForUnion(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto field_instance_name = MakeLowerCamel(field);
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto struct_instance_name = MakeLowerCamel(struct_def);
+ auto union_name = MakeUpperCamel(*(field.value.type.enum_def));
+
+ if (parser_.opts.include_dependence_headers) {
+ Namespace *namespaces = field.value.type.enum_def->defined_namespace;
+ auto package_reference = namespaces->GetFullyQualifiedName(
+ MakeUpperCamel(*(field.value.type.enum_def)));
+ union_name = package_reference + "." + union_name;
+ }
+ code += GenIndents(2) + "self." + field_instance_name + " = " + union_name +
+ "Creator(" + "self." + field_instance_name + "Type, " +
+ struct_instance_name + "." + field_accessor_name + "())";
+ }
+
+ void GenUnPackForStructVector(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto field_instance_name = MakeLowerCamel(field);
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto struct_instance_name = MakeLowerCamel(struct_def);
+
+ code += GenIndents(2) + "if not " + struct_instance_name + "." +
+ field_accessor_name + "IsNone():";
+ code += GenIndents(3) + "self." + field_instance_name + " = []";
+ code += GenIndents(3) + "for i in range(" + struct_instance_name + "." +
+ field_accessor_name + "Length()):";
+
+ auto field_type_name = TypeName(field);
+ auto one_instance = field_type_name + "_";
+ one_instance[0] = CharToLower(one_instance[0]);
+
+ if (parser_.opts.include_dependence_headers) {
+ auto package_reference = GenPackageReference(field.value.type);
+ field_type_name = package_reference + "." + TypeName(field);
+ }
+
+ code += GenIndents(4) + "if " + struct_instance_name + "." +
+ field_accessor_name + "(i) is None:";
+ code += GenIndents(5) + "self." + field_instance_name + ".append(None)";
+ code += GenIndents(4) + "else:";
+ code += GenIndents(5) + one_instance + " = " + field_type_name +
+ "T.InitFromObj(" + struct_instance_name + "." +
+ field_accessor_name + "(i))";
+ code += GenIndents(5) + "self." + field_instance_name + ".append(" +
+ one_instance + ")";
+ }
+
+ void GenUnpackforScalarVectorHelper(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr, int indents) {
+ auto &code = *code_ptr;
+ auto field_instance_name = MakeLowerCamel(field);
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto struct_instance_name = MakeLowerCamel(struct_def);
+
+ code += GenIndents(indents) + "self." + field_instance_name + " = []";
+ code += GenIndents(indents) + "for i in range(" + struct_instance_name +
+ "." + field_accessor_name + "Length()):";
+ code += GenIndents(indents + 1) + "self." + field_instance_name +
+ ".append(" + struct_instance_name + "." + field_accessor_name +
+ "(i))";
+ }
+
+ void GenUnPackForScalarVector(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto field_instance_name = MakeLowerCamel(field);
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto struct_instance_name = MakeLowerCamel(struct_def);
+
+ code += GenIndents(2) + "if not " + struct_instance_name + "." +
+ field_accessor_name + "IsNone():";
+
+ // String does not have the AsNumpy method.
+ if (!(IsScalar(field.value.type.VectorType().base_type))) {
+ GenUnpackforScalarVectorHelper(struct_def, field, code_ptr, 3);
+ return;
+ }
+
+ code += GenIndents(3) + "if np is None:";
+ GenUnpackforScalarVectorHelper(struct_def, field, code_ptr, 4);
+
+ // If numpy exists, use the AsNumpy method to optimize the unpack speed.
+ code += GenIndents(3) + "else:";
+ code += GenIndents(4) + "self." + field_instance_name + " = " +
+ struct_instance_name + "." + field_accessor_name + "AsNumpy()";
+ }
+
+ void GenUnPackForScalar(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto field_instance_name = MakeLowerCamel(field);
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto struct_instance_name = MakeLowerCamel(struct_def);
+
+ code += GenIndents(2) + "self." + field_instance_name + " = " +
+ struct_instance_name + "." + field_accessor_name + "()";
+ }
+
+ // Generates the UnPack method for the object class.
+ void GenUnPack(const StructDef &struct_def, std::string *code_ptr) {
+ std::string code;
+ // Items that needs to be imported. No duplicate modules will be imported.
+ std::set<std::string> import_list;
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ auto field_type = TypeName(field);
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ GenUnPackForStruct(struct_def, field, &code);
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ GenUnPackForUnion(struct_def, field, &code);
+ break;
+ }
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ GenUnPackForStructVector(struct_def, field, &code);
+ } else {
+ GenUnPackForScalarVector(struct_def, field, &code);
+ }
+ break;
+ }
+ case BASE_TYPE_ARRAY: {
+ GenUnPackForScalarVector(struct_def, field, &code);
+ break;
+ }
+ default: GenUnPackForScalar(struct_def, field, &code);
+ }
+ }
+
+ // Writes import statements and code into the generated file.
+ auto &code_base = *code_ptr;
+ auto struct_instance_name = MakeLowerCamel(struct_def);
+ auto struct_name = MakeUpperCamel(struct_def);
+
+ GenReceiverForObjectAPI(struct_def, code_ptr);
+ code_base += "_UnPack(self, " + struct_instance_name + "):";
+ code_base += GenIndents(2) + "if " + struct_instance_name + " is None:";
+ code_base += GenIndents(3) + "return";
+
+ // Write the import statements.
+ for (std::set<std::string>::iterator it = import_list.begin();
+ it != import_list.end(); ++it) {
+ code_base += GenIndents(2) + *it;
+ }
+
+ // Write the code.
+ code_base += code;
+ code_base += "\n";
+ }
+
+ void GenPackForStruct(const StructDef &struct_def, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto struct_name = MakeUpperCamel(struct_def);
+
+ GenReceiverForObjectAPI(struct_def, code_ptr);
+ code += "Pack(self, builder):";
+ code += GenIndents(2) + "return Create" + struct_name + "(builder";
+
+ StructBuilderArgs(struct_def,
+ /* nameprefix = */ "self.",
+ /* namesuffix = */ "",
+ /* has_field_name = */ true,
+ /* fieldname_suffix = */ ".", code_ptr);
+ code += ")\n";
+ }
+
+ void GenPackForStructVectorField(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_prefix_ptr,
+ std::string *code_ptr) {
+ auto &code_prefix = *code_prefix_ptr;
+ auto &code = *code_ptr;
+ auto field_instance_name = MakeLowerCamel(field);
+ auto struct_name = NormalizedName(struct_def);
+ auto field_accessor_name = MakeUpperCamel(field);
+
+ // Creates the field.
+ code_prefix +=
+ GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ if (field.value.type.struct_def->fixed) {
+ code_prefix += GenIndents(3) + "Start" +
+ field_accessor_name + "Vector(builder, len(self." +
+ field_instance_name + "))";
+ code_prefix += GenIndents(3) + "for i in reversed(range(len(self." +
+ field_instance_name + "))):";
+ code_prefix +=
+ GenIndents(4) + "self." + field_instance_name + "[i].Pack(builder)";
+ code_prefix +=
+ GenIndents(3) + field_instance_name + " = builder.EndVector()";
+ } else {
+ // If the vector is a struct vector, we need to first build accessor for
+ // each struct element.
+ code_prefix += GenIndents(3) + field_instance_name + "list = []";
+ code_prefix += GenIndents(3);
+ code_prefix += "for i in range(len(self." + field_instance_name + ")):";
+ code_prefix += GenIndents(4) + field_instance_name + "list.append(self." +
+ field_instance_name + "[i].Pack(builder))";
+
+ code_prefix += GenIndents(3) + "Start" +
+ field_accessor_name + "Vector(builder, len(self." +
+ field_instance_name + "))";
+ code_prefix += GenIndents(3) + "for i in reversed(range(len(self." +
+ field_instance_name + "))):";
+ code_prefix += GenIndents(4) + "builder.PrependUOffsetTRelative" + "(" +
+ field_instance_name + "list[i])";
+ code_prefix +=
+ GenIndents(3) + field_instance_name + " = builder.EndVector()";
+ }
+
+ // Adds the field into the struct.
+ code += GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ code += GenIndents(3) + "Add" + field_accessor_name +
+ "(builder, " + field_instance_name + ")";
+ }
+
+ void GenPackForScalarVectorFieldHelper(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr, int indents) {
+ auto &code = *code_ptr;
+ auto field_instance_name = MakeLowerCamel(field);
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto struct_name = NormalizedName(struct_def);
+ auto vectortype = field.value.type.VectorType();
+
+ code += GenIndents(indents) + "Start" + field_accessor_name +
+ "Vector(builder, len(self." + field_instance_name + "))";
+ code += GenIndents(indents) + "for i in reversed(range(len(self." +
+ field_instance_name + "))):";
+ code += GenIndents(indents + 1) + "builder.Prepend";
+
+ std::string type_name;
+ switch (vectortype.base_type) {
+ case BASE_TYPE_BOOL: type_name = "Bool"; break;
+ case BASE_TYPE_CHAR: type_name = "Byte"; break;
+ case BASE_TYPE_UCHAR: type_name = "Uint8"; break;
+ case BASE_TYPE_SHORT: type_name = "Int16"; break;
+ case BASE_TYPE_USHORT: type_name = "Uint16"; break;
+ case BASE_TYPE_INT: type_name = "Int32"; break;
+ case BASE_TYPE_UINT: type_name = "Uint32"; break;
+ case BASE_TYPE_LONG: type_name = "Int64"; break;
+ case BASE_TYPE_ULONG: type_name = "Uint64"; break;
+ case BASE_TYPE_FLOAT: type_name = "Float32"; break;
+ case BASE_TYPE_DOUBLE: type_name = "Float64"; break;
+ case BASE_TYPE_STRING: type_name = "UOffsetTRelative"; break;
+ default: type_name = "VOffsetT"; break;
+ }
+ code += type_name;
+ }
+
+ void GenPackForScalarVectorField(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_prefix_ptr,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto &code_prefix = *code_prefix_ptr;
+ auto field_instance_name = MakeLowerCamel(field);
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto struct_name = NormalizedName(struct_def);
+
+ // Adds the field into the struct.
+ code += GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ code += GenIndents(3) + "Add" + field_accessor_name +
+ "(builder, " + field_instance_name + ")";
+
+ // Creates the field.
+ code_prefix +=
+ GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ // If the vector is a string vector, we need to first build accessor for
+ // each string element. And this generated code, needs to be
+ // placed ahead of code_prefix.
+ auto vectortype = field.value.type.VectorType();
+ if (IsString(vectortype)) {
+ code_prefix += GenIndents(3) + MakeLowerCamel(field) + "list = []";
+ code_prefix += GenIndents(3) + "for i in range(len(self." +
+ field_instance_name + ")):";
+ code_prefix += GenIndents(4) + MakeLowerCamel(field) +
+ "list.append(builder.CreateString(self." +
+ field_instance_name + "[i]))";
+ GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 3);
+ code_prefix += "(" + MakeLowerCamel(field) + "list[i])";
+ code_prefix +=
+ GenIndents(3) + field_instance_name + " = builder.EndVector()";
+ return;
+ }
+
+ code_prefix += GenIndents(3) + "if np is not None and type(self." +
+ field_instance_name + ") is np.ndarray:";
+ code_prefix += GenIndents(4) + field_instance_name +
+ " = builder.CreateNumpyVector(self." + field_instance_name +
+ ")";
+ code_prefix += GenIndents(3) + "else:";
+ GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 4);
+ code_prefix += "(self." + field_instance_name + "[i])";
+ code_prefix +=
+ GenIndents(4) + field_instance_name + " = builder.EndVector()";
+ }
+
+ void GenPackForStructField(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_prefix_ptr,
+ std::string *code_ptr) {
+ auto &code_prefix = *code_prefix_ptr;
+ auto &code = *code_ptr;
+ auto field_instance_name = MakeLowerCamel(field);
+
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto struct_name = NormalizedName(struct_def);
+
+ if (field.value.type.struct_def->fixed) {
+ // Pure struct fields need to be created along with their parent
+ // structs.
+ code +=
+ GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ code += GenIndents(3) + field_instance_name + " = self." +
+ field_instance_name + ".Pack(builder)";
+ } else {
+ // Tables need to be created before their parent structs are created.
+ code_prefix +=
+ GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ code_prefix += GenIndents(3) + field_instance_name + " = self." +
+ field_instance_name + ".Pack(builder)";
+ code +=
+ GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ }
+
+ code += GenIndents(3) + "Add" + field_accessor_name +
+ "(builder, " + field_instance_name + ")";
+ }
+
+ void GenPackForUnionField(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_prefix_ptr,
+ std::string *code_ptr) {
+ auto &code_prefix = *code_prefix_ptr;
+ auto &code = *code_ptr;
+ auto field_instance_name = MakeLowerCamel(field);
+
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto struct_name = NormalizedName(struct_def);
+
+ // TODO(luwa): TypeT should be moved under the None check as well.
+ code_prefix +=
+ GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ code_prefix += GenIndents(3) + field_instance_name + " = self." +
+ field_instance_name + ".Pack(builder)";
+ code += GenIndents(2) + "if self." + field_instance_name + " is not None:";
+ code += GenIndents(3) + "Add" + field_accessor_name +
+ "(builder, " + field_instance_name + ")";
+ }
+
+ void GenPackForTable(const StructDef &struct_def, std::string *code_ptr) {
+ auto &code_base = *code_ptr;
+ std::string code, code_prefix;
+ auto struct_instance_name = MakeLowerCamel(struct_def);
+ auto struct_name = NormalizedName(struct_def);
+
+ GenReceiverForObjectAPI(struct_def, code_ptr);
+ code_base += "Pack(self, builder):";
+ code += GenIndents(2) + "Start(builder)";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ auto field_accessor_name = MakeUpperCamel(field);
+ auto field_instance_name = MakeLowerCamel(field);
+
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ GenPackForStructField(struct_def, field, &code_prefix, &code);
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ GenPackForUnionField(struct_def, field, &code_prefix, &code);
+ break;
+ }
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ GenPackForStructVectorField(struct_def, field, &code_prefix, &code);
+ } else {
+ GenPackForScalarVectorField(struct_def, field, &code_prefix, &code);
+ }
+ break;
+ }
+ case BASE_TYPE_ARRAY: {
+ GenPackForScalarVectorField(struct_def, field, &code_prefix, &code);
+ break;
+ }
+ case BASE_TYPE_STRING: {
+ code_prefix += GenIndents(2) + "if self." + field_instance_name +
+ " is not None:";
+ code_prefix += GenIndents(3) + field_instance_name +
+ " = builder.CreateString(self." + field_instance_name +
+ ")";
+ code += GenIndents(2) + "if self." + field_instance_name +
+ " is not None:";
+ code += GenIndents(3) + "Add" + field_accessor_name +
+ "(builder, " + field_instance_name + ")";
+ break;
+ }
+ default:
+ // Generates code for scalar values. If the value equals to the
+ // default value, builder will automatically ignore it. So we don't
+ // need to check the value ahead.
+ code += GenIndents(2) + "Add" + field_accessor_name +
+ "(builder, self." + field_instance_name + ")";
+ break;
+ }
+ }
+
+ code += GenIndents(2) + struct_instance_name + " = " + "End(builder)";
+ code += GenIndents(2) + "return " + struct_instance_name;
+
+ code_base += code_prefix + code;
+ code_base += "\n";
+ }
+
+ void GenStructForObjectAPI(const StructDef &struct_def,
+ std::string *code_ptr) {
+ if (struct_def.generated) return;
+
+ std::set<std::string> import_list;
+ std::string code;
+
+ // Creates an object class for a struct or a table
+ BeginClassForObjectAPI(struct_def, &code);
+
+ GenInitialize(struct_def, &code, &import_list);
+
+ InitializeFromBuf(struct_def, &code);
+
+ InitializeFromObjForObject(struct_def, &code);
+
+ GenUnPack(struct_def, &code);
+
+ if (struct_def.fixed) {
+ GenPackForStruct(struct_def, &code);
+ } else {
+ GenPackForTable(struct_def, &code);
+ }
+
+ // Adds the imports at top.
+ auto &code_base = *code_ptr;
+ code_base += "\n";
+ for (auto it = import_list.begin(); it != import_list.end(); it++) {
+ auto im = *it;
+ code_base += im + "\n";
+ }
+ code_base += code;
+ }
+
+ void GenUnionCreatorForStruct(const EnumDef &enum_def, const EnumVal &ev,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto union_name = NormalizedName(enum_def);
+ auto field_name = NormalizedName(ev);
+ auto field_type = GenTypeGet(ev.union_type) + "T";
+
+ code += GenIndents(1) + "if unionType == " + union_name + "()." +
+ field_name + ":";
+ if (parser_.opts.include_dependence_headers) {
+ auto package_reference = GenPackageReference(ev.union_type);
+ code += GenIndents(2) + "import " + package_reference;
+ field_type = package_reference + "." + field_type;
+ }
+ code += GenIndents(2) + "return " + field_type +
+ ".InitFromBuf(table.Bytes, table.Pos)";
+ }
+
+ void GenUnionCreatorForString(const EnumDef &enum_def, const EnumVal &ev,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto union_name = NormalizedName(enum_def);
+ auto field_name = NormalizedName(ev);
+
+ code += GenIndents(1) + "if unionType == " + union_name + "()." +
+ field_name + ":";
+ code += GenIndents(2) + "tab = Table(table.Bytes, table.Pos)";
+ code += GenIndents(2) + "union = tab.String(table.Pos)";
+ code += GenIndents(2) + "return union";
+ }
+
+ // Creates an union object based on union type.
+ void GenUnionCreator(const EnumDef &enum_def, std::string *code_ptr) {
+ auto &code = *code_ptr;
+ auto union_name = MakeUpperCamel(enum_def);
+
+ code += "\n";
+ code += "def " + union_name + "Creator(unionType, table):";
+ code += GenIndents(1) + "from flatbuffers.table import Table";
+ code += GenIndents(1) + "if not isinstance(table, Table):";
+ code += GenIndents(2) + "return None";
+
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ // Union only supports string and table.
+ switch (ev.union_type.base_type) {
+ case BASE_TYPE_STRUCT:
+ GenUnionCreatorForStruct(enum_def, ev, &code);
+ break;
+ case BASE_TYPE_STRING:
+ GenUnionCreatorForString(enum_def, ev, &code);
+ break;
+ default: break;
+ }
+ }
+ code += GenIndents(1) + "return None";
+ code += "\n";
+ }
+
+ // Generate enum declarations.
+ void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
+ if (enum_def.generated) return;
+
+ GenComment(enum_def.doc_comment, code_ptr, &def_comment);
+ BeginEnum(NormalizedName(enum_def), code_ptr);
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ GenComment(ev.doc_comment, code_ptr, &def_comment, Indent.c_str());
+ EnumMember(enum_def, ev, code_ptr);
+ }
+ EndEnum(code_ptr);
+ }
+
+ // Returns the function name that is able to read a value of the given type.
+ std::string GenGetter(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return "self._tab.String(";
+ case BASE_TYPE_UNION: return "self._tab.Union(";
+ case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
+ default:
+ return "self._tab.Get(flatbuffers.number_types." +
+ MakeCamel(GenTypeGet(type)) + "Flags, ";
+ }
+ }
+
+ // Returns the method name for use with add/put calls.
+ std::string GenMethod(const FieldDef &field) {
+ return (IsScalar(field.value.type.base_type) || IsArray(field.value.type))
+ ? MakeCamel(GenTypeBasic(field.value.type))
+ : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
+ }
+
+ std::string GenTypeBasic(const Type &type) {
+ // clang-format off
+ static const char *ctypename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
+ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, ...) \
+ #PTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+ return ctypename[IsArray(type) ? type.VectorType().base_type
+ : type.base_type];
+ }
+
+ std::string GenTypePointer(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return "string";
+ case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
+ case BASE_TYPE_STRUCT: return type.struct_def->name;
+ case BASE_TYPE_UNION:
+ // fall through
+ default: return "*flatbuffers.Table";
+ }
+ }
+
+ std::string GenTypeGet(const Type &type) {
+ return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
+ }
+
+ std::string TypeName(const FieldDef &field) {
+ return GenTypeGet(field.value.type);
+ }
+
+ // Create a struct with a builder and the struct's arguments.
+ void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) {
+ BeginBuilderArgs(struct_def, code_ptr);
+ StructBuilderArgs(struct_def,
+ /* nameprefix = */ "",
+ /* namesuffix = */ "",
+ /* has_field_name = */ true,
+ /* fieldname_suffix = */ "_", code_ptr);
+ EndBuilderArgs(code_ptr);
+
+ StructBuilderBody(struct_def, "", code_ptr);
+ EndBuilderBody(code_ptr);
+ }
+
+ bool generate() {
+ if (!generateEnums()) return false;
+ if (!generateStructs()) return false;
+ return true;
+ }
+
+ private:
+ bool generateEnums() {
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ auto &enum_def = **it;
+ std::string enumcode;
+ GenEnum(enum_def, &enumcode);
+ if (parser_.opts.generate_object_based_api & enum_def.is_union) {
+ GenUnionCreator(enum_def, &enumcode);
+ }
+ if (!SaveType(enum_def, enumcode, false)) return false;
+ }
+ return true;
+ }
+
+ bool generateStructs() {
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ auto &struct_def = **it;
+ std::string declcode;
+ GenStruct(struct_def, &declcode);
+ if (parser_.opts.generate_object_based_api) {
+ GenStructForObjectAPI(struct_def, &declcode);
+ }
+ if (!SaveType(struct_def, declcode, true)) return false;
+ }
+ return true;
+ }
+
+ // Begin by declaring namespace and imports.
+ void BeginFile(const std::string &name_space_name, const bool needs_imports,
+ std::string *code_ptr) {
+ auto &code = *code_ptr;
+ code = code + "# " + FlatBuffersGeneratedWarning() + "\n\n";
+ code += "# namespace: " + name_space_name + "\n\n";
+ if (needs_imports) {
+ code += "import flatbuffers\n";
+ code += "from flatbuffers.compat import import_numpy\n";
+ code += "np = import_numpy()\n\n";
+ }
+ }
+
+ // Save out the generated code for a Python Table type.
+ bool SaveType(const Definition &def, const std::string &classcode,
+ bool needs_imports) {
+ if (!classcode.length()) return true;
+
+ std::string namespace_dir = path_;
+ auto &namespaces = def.defined_namespace->components;
+ for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
+ if (it != namespaces.begin()) namespace_dir += kPathSeparator;
+ namespace_dir += *it;
+ std::string init_py_filename = namespace_dir + "/__init__.py";
+ SaveFile(init_py_filename.c_str(), "", false);
+ }
+
+ std::string code = "";
+ BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
+ code += classcode;
+ std::string filename =
+ NamespaceDir(*def.defined_namespace) + NormalizedName(def) + ".py";
+ return SaveFile(filename.c_str(), code, false);
+ }
+
+ private:
+ std::unordered_set<std::string> keywords_;
+ const SimpleFloatConstantGenerator float_const_gen_;
+};
+
+} // namespace python
+
+bool GeneratePython(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ python::PythonGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_rust.cpp b/contrib/libs/flatbuffers/src/idl_gen_rust.cpp
new file mode 100644
index 0000000000..455780cd94
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_rust.cpp
@@ -0,0 +1,2817 @@
+/*
+ * Copyright 2018 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 "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+// Convert a camelCaseIdentifier or CamelCaseIdentifier to a
+// snake_case_identifier.
+std::string MakeSnakeCase(const std::string &in) {
+ std::string s;
+ for (size_t i = 0; i < in.length(); i++) {
+ if (i == 0) {
+ s += CharToLower(in[0]);
+ } else if (in[i] == '_') {
+ s += '_';
+ } else if (!islower(in[i])) {
+ // Prevent duplicate underscores for Upper_Snake_Case strings
+ // and UPPERCASE strings.
+ if (islower(in[i - 1])) { s += '_'; }
+ s += CharToLower(in[i]);
+ } else {
+ s += in[i];
+ }
+ }
+ return s;
+}
+
+// Convert a string to all uppercase.
+std::string MakeUpper(const std::string &in) {
+ std::string s;
+ for (size_t i = 0; i < in.length(); i++) { s += CharToUpper(in[i]); }
+ return s;
+}
+
+// Encapsulate all logical field types in this enum. This allows us to write
+// field logic based on type switches, instead of branches on the properties
+// set on the Type.
+// TODO(rw): for backwards compatibility, we can't use a strict `enum class`
+// declaration here. could we use the `-Wswitch-enum` warning to
+// achieve the same effect?
+enum FullType {
+ ftInteger = 0,
+ ftFloat = 1,
+ ftBool = 2,
+
+ ftStruct = 3,
+ ftTable = 4,
+
+ ftEnumKey = 5,
+ ftUnionKey = 6,
+
+ ftUnionValue = 7,
+
+ // TODO(rw): bytestring?
+ ftString = 8,
+
+ ftVectorOfInteger = 9,
+ ftVectorOfFloat = 10,
+ ftVectorOfBool = 11,
+ ftVectorOfEnumKey = 12,
+ ftVectorOfStruct = 13,
+ ftVectorOfTable = 14,
+ ftVectorOfString = 15,
+ ftVectorOfUnionValue = 16,
+
+ ftArrayOfBuiltin = 17,
+ ftArrayOfEnum = 18,
+ ftArrayOfStruct = 19,
+};
+
+// Convert a Type to a FullType (exhaustive).
+FullType GetFullType(const Type &type) {
+ // N.B. The order of these conditionals matters for some types.
+
+ if (IsString(type)) {
+ return ftString;
+ } else if (type.base_type == BASE_TYPE_STRUCT) {
+ if (type.struct_def->fixed) {
+ return ftStruct;
+ } else {
+ return ftTable;
+ }
+ } else if (IsVector(type)) {
+ switch (GetFullType(type.VectorType())) {
+ case ftInteger: {
+ return ftVectorOfInteger;
+ }
+ case ftFloat: {
+ return ftVectorOfFloat;
+ }
+ case ftBool: {
+ return ftVectorOfBool;
+ }
+ case ftStruct: {
+ return ftVectorOfStruct;
+ }
+ case ftTable: {
+ return ftVectorOfTable;
+ }
+ case ftString: {
+ return ftVectorOfString;
+ }
+ case ftEnumKey: {
+ return ftVectorOfEnumKey;
+ }
+ case ftUnionKey:
+ case ftUnionValue: {
+ FLATBUFFERS_ASSERT(false && "vectors of unions are unsupported");
+ break;
+ }
+ default: {
+ FLATBUFFERS_ASSERT(false && "vector of vectors are unsupported");
+ }
+ }
+ } else if (IsArray(type)) {
+ switch (GetFullType(type.VectorType())) {
+ case ftInteger:
+ case ftFloat:
+ case ftBool: {
+ return ftArrayOfBuiltin;
+ }
+ case ftStruct: {
+ return ftArrayOfStruct;
+ }
+ case ftEnumKey: {
+ return ftArrayOfEnum;
+ }
+ default: {
+ FLATBUFFERS_ASSERT(false && "Unsupported type for fixed array");
+ }
+ }
+ } else if (type.enum_def != nullptr) {
+ if (type.enum_def->is_union) {
+ if (type.base_type == BASE_TYPE_UNION) {
+ return ftUnionValue;
+ } else if (IsInteger(type.base_type)) {
+ return ftUnionKey;
+ } else {
+ FLATBUFFERS_ASSERT(false && "unknown union field type");
+ }
+ } else {
+ return ftEnumKey;
+ }
+ } else if (IsScalar(type.base_type)) {
+ if (IsBool(type.base_type)) {
+ return ftBool;
+ } else if (IsInteger(type.base_type)) {
+ return ftInteger;
+ } else if (IsFloat(type.base_type)) {
+ return ftFloat;
+ } else {
+ FLATBUFFERS_ASSERT(false && "unknown number type");
+ }
+ }
+
+ FLATBUFFERS_ASSERT(false && "completely unknown type");
+
+ // this is only to satisfy the compiler's return analysis.
+ return ftBool;
+}
+
+// If the second parameter is false then wrap the first with Option<...>
+std::string WrapInOptionIfNotRequired(std::string s, bool required) {
+ if (required) {
+ return s;
+ } else {
+ return "Option<" + s + ">";
+ }
+}
+
+// If the second parameter is false then add .unwrap()
+std::string AddUnwrapIfRequired(std::string s, bool required) {
+ if (required) {
+ return s + ".unwrap()";
+ } else {
+ return s;
+ }
+}
+
+bool IsBitFlagsEnum(const EnumDef &enum_def) {
+ return enum_def.attributes.Lookup("bit_flags") != nullptr;
+}
+bool IsBitFlagsEnum(const FieldDef &field) {
+ EnumDef *ed = field.value.type.enum_def;
+ return ed && IsBitFlagsEnum(*ed);
+}
+
+// TableArgs make required non-scalars "Option<_>".
+// TODO(cneo): Rework how we do defaults and stuff.
+bool IsOptionalToBuilder(const FieldDef &field) {
+ return field.IsOptional() || !IsScalar(field.value.type.base_type);
+}
+
+namespace rust {
+
+class RustGenerator : public BaseGenerator {
+ public:
+ RustGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", "::", "rs"),
+ cur_name_space_(nullptr) {
+ const char *keywords[] = {
+ // clang-format off
+ // list taken from:
+ // https://doc.rust-lang.org/book/second-edition/appendix-01-keywords.html
+ //
+ // we write keywords one per line so that we can easily compare them with
+ // changes to that webpage in the future.
+
+ // currently-used keywords
+ "as",
+ "break",
+ "const",
+ "continue",
+ "crate",
+ "else",
+ "enum",
+ "extern",
+ "false",
+ "fn",
+ "for",
+ "if",
+ "impl",
+ "in",
+ "let",
+ "loop",
+ "match",
+ "mod",
+ "move",
+ "mut",
+ "pub",
+ "ref",
+ "return",
+ "Self",
+ "self",
+ "static",
+ "struct",
+ "super",
+ "trait",
+ "true",
+ "type",
+ "unsafe",
+ "use",
+ "where",
+ "while",
+
+ // future possible keywords
+ "abstract",
+ "alignof",
+ "become",
+ "box",
+ "do",
+ "final",
+ "macro",
+ "offsetof",
+ "override",
+ "priv",
+ "proc",
+ "pure",
+ "sizeof",
+ "typeof",
+ "unsized",
+ "virtual",
+ "yield",
+
+ // other rust terms we should not use
+ "std",
+ "usize",
+ "isize",
+ "u8",
+ "i8",
+ "u16",
+ "i16",
+ "u32",
+ "i32",
+ "u64",
+ "i64",
+ "u128",
+ "i128",
+ "f32",
+ "f64",
+
+ // These are terms the code generator can implement on types.
+ //
+ // In Rust, the trait resolution rules (as described at
+ // https://github.com/rust-lang/rust/issues/26007) mean that, as long
+ // as we impl table accessors as inherent methods, we'll never create
+ // conflicts with these keywords. However, that's a fairly nuanced
+ // implementation detail, and how we implement methods could change in
+ // the future. as a result, we proactively block these out as reserved
+ // words.
+ "follow",
+ "push",
+ "size",
+ "alignment",
+ "to_little_endian",
+ "from_little_endian",
+ nullptr,
+
+ // used by Enum constants
+ "ENUM_MAX",
+ "ENUM_MIN",
+ "ENUM_VALUES",
+ };
+ for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
+ }
+
+ // Iterate through all definitions we haven't generated code for (enums,
+ // structs, and tables) and output them to a single file.
+ bool generate() {
+ code_.Clear();
+ code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
+
+ assert(!cur_name_space_);
+
+ // Generate imports for the global scope in case no namespace is used
+ // in the schema file.
+ GenNamespaceImports(0);
+ code_ += "";
+
+ // Generate all code in their namespaces, once, because Rust does not
+ // permit re-opening modules.
+ //
+ // TODO(rw): Use a set data structure to reduce namespace evaluations from
+ // O(n**2) to O(n).
+ for (auto ns_it = parser_.namespaces_.begin();
+ ns_it != parser_.namespaces_.end(); ++ns_it) {
+ const auto &ns = *ns_it;
+
+ // Generate code for all the enum declarations.
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ const auto &enum_def = **it;
+ if (enum_def.defined_namespace == ns && !enum_def.generated) {
+ SetNameSpace(enum_def.defined_namespace);
+ GenEnum(enum_def);
+ }
+ }
+
+ // Generate code for all structs.
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (struct_def.defined_namespace == ns && struct_def.fixed &&
+ !struct_def.generated) {
+ SetNameSpace(struct_def.defined_namespace);
+ GenStruct(struct_def);
+ }
+ }
+
+ // Generate code for all tables.
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (struct_def.defined_namespace == ns && !struct_def.fixed &&
+ !struct_def.generated) {
+ SetNameSpace(struct_def.defined_namespace);
+ GenTable(struct_def);
+ if (parser_.opts.generate_object_based_api) {
+ GenTableObject(struct_def);
+ }
+ }
+ }
+
+ // Generate global helper functions.
+ if (parser_.root_struct_def_) {
+ auto &struct_def = *parser_.root_struct_def_;
+ if (struct_def.defined_namespace != ns) { continue; }
+ SetNameSpace(struct_def.defined_namespace);
+ GenRootTableFuncs(struct_def);
+ }
+ }
+ if (cur_name_space_) SetNameSpace(nullptr);
+
+ const auto file_path = GeneratedFileName(path_, file_name_, parser_.opts);
+ const auto final_code = code_.ToString();
+ return SaveFile(file_path.c_str(), final_code, false);
+ }
+
+ private:
+ CodeWriter code_;
+
+ std::set<std::string> keywords_;
+
+ // This tracks the current namespace so we can insert namespace declarations.
+ const Namespace *cur_name_space_;
+
+ const Namespace *CurrentNameSpace() const { return cur_name_space_; }
+
+ // Determine if a Type needs a lifetime template parameter when used in the
+ // Rust builder args.
+ bool TableBuilderTypeNeedsLifetime(const Type &type) const {
+ switch (GetFullType(type)) {
+ case ftInteger:
+ case ftFloat:
+ case ftBool:
+ case ftEnumKey:
+ case ftUnionKey:
+ case ftUnionValue: {
+ return false;
+ }
+ default: {
+ return true;
+ }
+ }
+ }
+
+ // Determine if a table args rust type needs a lifetime template parameter.
+ bool TableBuilderArgsNeedsLifetime(const StructDef &struct_def) const {
+ FLATBUFFERS_ASSERT(!struct_def.fixed);
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) { continue; }
+
+ if (TableBuilderTypeNeedsLifetime(field.value.type)) { return true; }
+ }
+
+ return false;
+ }
+
+ std::string EscapeKeyword(const std::string &name) const {
+ return keywords_.find(name) == keywords_.end() ? name : name + "_";
+ }
+ std::string NamespacedNativeName(const Definition &def) {
+ return WrapInNameSpace(def.defined_namespace, NativeName(def));
+ }
+
+ std::string NativeName(const Definition &def) {
+ return parser_.opts.object_prefix + Name(def) + parser_.opts.object_suffix;
+ }
+
+ std::string Name(const Definition &def) const {
+ return EscapeKeyword(def.name);
+ }
+
+ std::string Name(const EnumVal &ev) const { return EscapeKeyword(ev.name); }
+
+ std::string WrapInNameSpace(const Definition &def) const {
+ return WrapInNameSpace(def.defined_namespace, Name(def));
+ }
+ std::string WrapInNameSpace(const Namespace *ns,
+ const std::string &name) const {
+ if (CurrentNameSpace() == ns) return name;
+ std::string prefix = GetRelativeNamespaceTraversal(CurrentNameSpace(), ns);
+ return prefix + name;
+ }
+
+ // Determine the namespace traversal needed from the Rust crate root.
+ // This may be useful in the future for referring to included files, but is
+ // currently unused.
+ std::string GetAbsoluteNamespaceTraversal(const Namespace *dst) const {
+ std::stringstream stream;
+
+ stream << "::";
+ for (auto d = dst->components.begin(); d != dst->components.end(); ++d) {
+ stream << MakeSnakeCase(*d) + "::";
+ }
+ return stream.str();
+ }
+
+ // Determine the relative namespace traversal needed to reference one
+ // namespace from another namespace. This is useful because it does not force
+ // the user to have a particular file layout. (If we output absolute
+ // namespace paths, that may require users to organize their Rust crates in a
+ // particular way.)
+ std::string GetRelativeNamespaceTraversal(const Namespace *src,
+ const Namespace *dst) const {
+ // calculate the path needed to reference dst from src.
+ // example: f(A::B::C, A::B::C) -> (none)
+ // example: f(A::B::C, A::B) -> super::
+ // example: f(A::B::C, A::B::D) -> super::D
+ // example: f(A::B::C, A) -> super::super::
+ // example: f(A::B::C, D) -> super::super::super::D
+ // example: f(A::B::C, D::E) -> super::super::super::D::E
+ // example: f(A, D::E) -> super::D::E
+ // does not include leaf object (typically a struct type).
+
+ size_t i = 0;
+ std::stringstream stream;
+
+ auto s = src->components.begin();
+ auto d = dst->components.begin();
+ for (;;) {
+ if (s == src->components.end()) { break; }
+ if (d == dst->components.end()) { break; }
+ if (*s != *d) { break; }
+ ++s;
+ ++d;
+ ++i;
+ }
+
+ for (; s != src->components.end(); ++s) { stream << "super::"; }
+ for (; d != dst->components.end(); ++d) {
+ stream << MakeSnakeCase(*d) + "::";
+ }
+ return stream.str();
+ }
+
+ // Generate a comment from the schema.
+ void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
+ std::string text;
+ ::flatbuffers::GenComment(dc, &text, nullptr, prefix);
+ code_ += text + "\\";
+ }
+
+ // Return a Rust type from the table in idl.h.
+ std::string GetTypeBasic(const Type &type) const {
+ switch (GetFullType(type)) {
+ case ftInteger:
+ case ftFloat:
+ case ftBool:
+ case ftEnumKey:
+ case ftUnionKey: {
+ break;
+ }
+ default: {
+ FLATBUFFERS_ASSERT(false && "incorrect type given");
+ }
+ }
+
+ // clang-format off
+ static const char * const ctypename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
+ RTYPE, ...) \
+ #RTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+
+ if (type.enum_def) { return WrapInNameSpace(*type.enum_def); }
+ return ctypename[type.base_type];
+ }
+
+ // Look up the native type for an enum. This will always be an integer like
+ // u8, i32, etc.
+ std::string GetEnumTypeForDecl(const Type &type) {
+ const auto ft = GetFullType(type);
+ if (!(ft == ftEnumKey || ft == ftUnionKey)) {
+ FLATBUFFERS_ASSERT(false && "precondition failed in GetEnumTypeForDecl");
+ }
+
+ // clang-format off
+ static const char *ctypename[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
+ RTYPE, ...) \
+ #RTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+
+ // Enums can be bools, but their Rust representation must be a u8, as used
+ // in the repr attribute (#[repr(bool)] is an invalid attribute).
+ if (type.base_type == BASE_TYPE_BOOL) return "u8";
+ return ctypename[type.base_type];
+ }
+
+ // Return a Rust type for any type (scalar, table, struct) specifically for
+ // using a FlatBuffer.
+ std::string GetTypeGet(const Type &type) const {
+ switch (GetFullType(type)) {
+ case ftInteger:
+ case ftFloat:
+ case ftBool:
+ case ftEnumKey:
+ case ftUnionKey: {
+ return GetTypeBasic(type);
+ }
+ case ftArrayOfBuiltin:
+ case ftArrayOfEnum:
+ case ftArrayOfStruct: {
+ return "[" + GetTypeGet(type.VectorType()) + "; " +
+ NumToString(type.fixed_length) + "]";
+ }
+ case ftTable: {
+ return WrapInNameSpace(type.struct_def->defined_namespace,
+ type.struct_def->name) +
+ "<'a>";
+ }
+ default: {
+ return WrapInNameSpace(type.struct_def->defined_namespace,
+ type.struct_def->name);
+ }
+ }
+ }
+
+ std::string GetEnumValue(const EnumDef &enum_def,
+ const EnumVal &enum_val) const {
+ return Name(enum_def) + "::" + Name(enum_val);
+ }
+
+ // 1 suffix since old C++ can't figure out the overload.
+ void ForAllEnumValues1(const EnumDef &enum_def,
+ std::function<void(const EnumVal &)> cb) {
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ const auto &ev = **it;
+ code_.SetValue("VARIANT", Name(ev));
+ code_.SetValue("VALUE", enum_def.ToString(ev));
+ cb(ev);
+ }
+ }
+ void ForAllEnumValues(const EnumDef &enum_def, std::function<void()> cb) {
+ std::function<void(const EnumVal &)> wrapped = [&](const EnumVal &unused) {
+ (void)unused;
+ cb();
+ };
+ ForAllEnumValues1(enum_def, wrapped);
+ }
+ // Generate an enum declaration,
+ // an enum string lookup table,
+ // an enum match function,
+ // and an enum array of values
+ void GenEnum(const EnumDef &enum_def) {
+ code_.SetValue("ENUM_NAME", Name(enum_def));
+ code_.SetValue("BASE_TYPE", GetEnumTypeForDecl(enum_def.underlying_type));
+ code_.SetValue("ENUM_NAME_SNAKE", MakeSnakeCase(Name(enum_def)));
+ code_.SetValue("ENUM_NAME_CAPS", MakeUpper(MakeSnakeCase(Name(enum_def))));
+ const EnumVal *minv = enum_def.MinValue();
+ const EnumVal *maxv = enum_def.MaxValue();
+ FLATBUFFERS_ASSERT(minv && maxv);
+ code_.SetValue("ENUM_MIN_BASE_VALUE", enum_def.ToString(*minv));
+ code_.SetValue("ENUM_MAX_BASE_VALUE", enum_def.ToString(*maxv));
+
+ if (IsBitFlagsEnum(enum_def)) {
+ // Defer to the convenient and canonical bitflags crate. We declare it in
+ // a module to #allow camel case constants in a smaller scope. This
+ // matches Flatbuffers c-modeled enums where variants are associated
+ // constants but in camel case.
+ code_ += "#[allow(non_upper_case_globals)]";
+ code_ += "mod bitflags_{{ENUM_NAME_SNAKE}} {";
+ code_ += " flatbuffers::bitflags::bitflags! {";
+ GenComment(enum_def.doc_comment, " ");
+ code_ += " #[derive(Default)]";
+ code_ += " pub struct {{ENUM_NAME}}: {{BASE_TYPE}} {";
+ ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
+ this->GenComment(ev.doc_comment, " ");
+ code_ += " const {{VARIANT}} = {{VALUE}};";
+ });
+ code_ += " }";
+ code_ += " }";
+ code_ += "}";
+ code_ += "pub use self::bitflags_{{ENUM_NAME_SNAKE}}::{{ENUM_NAME}};";
+ code_ += "";
+
+ code_.SetValue("FROM_BASE", "unsafe { Self::from_bits_unchecked(b) }");
+ code_.SetValue("INTO_BASE", "self.bits()");
+ } else {
+ // Normal, c-modelled enums.
+ // Deprecated associated constants;
+ const std::string deprecation_warning =
+ "#[deprecated(since = \"2.0.0\", note = \"Use associated constants"
+ " instead. This will no longer be generated in 2021.\")]";
+ code_ += deprecation_warning;
+ code_ +=
+ "pub const ENUM_MIN_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
+ " = {{ENUM_MIN_BASE_VALUE}};";
+ code_ += deprecation_warning;
+ code_ +=
+ "pub const ENUM_MAX_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
+ " = {{ENUM_MAX_BASE_VALUE}};";
+ auto num_fields = NumToString(enum_def.size());
+ code_ += deprecation_warning;
+ code_ += "#[allow(non_camel_case_types)]";
+ code_ += "pub const ENUM_VALUES_{{ENUM_NAME_CAPS}}: [{{ENUM_NAME}}; " +
+ num_fields + "] = [";
+ ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
+ code_ += " " + GetEnumValue(enum_def, ev) + ",";
+ });
+ code_ += "];";
+ code_ += "";
+
+ GenComment(enum_def.doc_comment);
+ // Derive Default to be 0. flatc enforces this when the enum
+ // is put into a struct, though this isn't documented behavior, it is
+ // needed to derive defaults in struct objects.
+ code_ +=
+ "#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, "
+ "Default)]";
+ code_ += "#[repr(transparent)]";
+ code_ += "pub struct {{ENUM_NAME}}(pub {{BASE_TYPE}});";
+ code_ += "#[allow(non_upper_case_globals)]";
+ code_ += "impl {{ENUM_NAME}} {";
+ ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
+ this->GenComment(ev.doc_comment, " ");
+ code_ += " pub const {{VARIANT}}: Self = Self({{VALUE}});";
+ });
+ code_ += "";
+ // Generate Associated constants
+ code_ += " pub const ENUM_MIN: {{BASE_TYPE}} = {{ENUM_MIN_BASE_VALUE}};";
+ code_ += " pub const ENUM_MAX: {{BASE_TYPE}} = {{ENUM_MAX_BASE_VALUE}};";
+ code_ += " pub const ENUM_VALUES: &'static [Self] = &[";
+ ForAllEnumValues(enum_def, [&]() { code_ += " Self::{{VARIANT}},"; });
+ code_ += " ];";
+ code_ += " /// Returns the variant's name or \"\" if unknown.";
+ code_ += " pub fn variant_name(self) -> Option<&'static str> {";
+ code_ += " match self {";
+ ForAllEnumValues(enum_def, [&]() {
+ code_ += " Self::{{VARIANT}} => Some(\"{{VARIANT}}\"),";
+ });
+ code_ += " _ => None,";
+ code_ += " }";
+ code_ += " }";
+ code_ += "}";
+
+ // Generate Debug. Unknown variants are printed like "<UNKNOWN 42>".
+ code_ += "impl std::fmt::Debug for {{ENUM_NAME}} {";
+ code_ +=
+ " fn fmt(&self, f: &mut std::fmt::Formatter) ->"
+ " std::fmt::Result {";
+ code_ += " if let Some(name) = self.variant_name() {";
+ code_ += " f.write_str(name)";
+ code_ += " } else {";
+ code_ += " f.write_fmt(format_args!(\"<UNKNOWN {:?}>\", self.0))";
+ code_ += " }";
+ code_ += " }";
+ code_ += "}";
+
+ code_.SetValue("FROM_BASE", "Self(b)");
+ code_.SetValue("INTO_BASE", "self.0");
+ }
+
+ // Generate Follow and Push so we can serialize and stuff.
+ code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_NAME}} {";
+ code_ += " type Inner = Self;";
+ code_ += " #[inline]";
+ code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " let b = unsafe {";
+ code_ += " flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc)";
+ code_ += " };";
+ code_ += " {{FROM_BASE}}";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+ code_ += "impl flatbuffers::Push for {{ENUM_NAME}} {";
+ code_ += " type Output = {{ENUM_NAME}};";
+ code_ += " #[inline]";
+ code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
+ code_ +=
+ " unsafe { flatbuffers::emplace_scalar::<{{BASE_TYPE}}>"
+ "(dst, {{INTO_BASE}}); }";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+ code_ += "impl flatbuffers::EndianScalar for {{ENUM_NAME}} {";
+ code_ += " #[inline]";
+ code_ += " fn to_little_endian(self) -> Self {";
+ code_ += " let b = {{BASE_TYPE}}::to_le({{INTO_BASE}});";
+ code_ += " {{FROM_BASE}}";
+ code_ += " }";
+ code_ += " #[inline]";
+ code_ += " #[allow(clippy::wrong_self_convention)]";
+ code_ += " fn from_little_endian(self) -> Self {";
+ code_ += " let b = {{BASE_TYPE}}::from_le({{INTO_BASE}});";
+ code_ += " {{FROM_BASE}}";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+
+ // Generate verifier - deferring to the base type.
+ code_ += "impl<'a> flatbuffers::Verifiable for {{ENUM_NAME}} {";
+ code_ += " #[inline]";
+ code_ += " fn run_verifier(";
+ code_ += " v: &mut flatbuffers::Verifier, pos: usize";
+ code_ += " ) -> Result<(), flatbuffers::InvalidFlatbuffer> {";
+ code_ += " use self::flatbuffers::Verifiable;";
+ code_ += " {{BASE_TYPE}}::run_verifier(v, pos)";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+ // Enums are basically integers.
+ code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{ENUM_NAME}} {}";
+
+ if (enum_def.is_union) {
+ // Generate typesafe offset(s) for unions
+ code_.SetValue("NAME", Name(enum_def));
+ code_.SetValue("UNION_OFFSET_NAME", Name(enum_def) + "UnionTableOffset");
+ code_ += "pub struct {{UNION_OFFSET_NAME}} {}";
+ code_ += "";
+ if (parser_.opts.generate_object_based_api) { GenUnionObject(enum_def); }
+ }
+ }
+
+ // CASPER: dedup Object versions from non object versions.
+ void ForAllUnionObjectVariantsBesidesNone(const EnumDef &enum_def,
+ std::function<void()> cb) {
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &enum_val = **it;
+ if (enum_val.union_type.base_type == BASE_TYPE_NONE) continue;
+ code_.SetValue("VARIANT_NAME", Name(enum_val));
+ code_.SetValue("NATIVE_VARIANT", MakeCamel(Name(enum_val)));
+ code_.SetValue("U_ELEMENT_NAME", MakeSnakeCase(Name(enum_val)));
+ code_.SetValue("U_ELEMENT_TABLE_TYPE",
+ NamespacedNativeName(*enum_val.union_type.struct_def));
+ cb();
+ }
+ }
+ void GenUnionObject(const EnumDef &enum_def) {
+ code_.SetValue("ENUM_NAME", Name(enum_def));
+ code_.SetValue("ENUM_NAME_SNAKE", MakeSnakeCase(Name(enum_def)));
+ code_.SetValue("NATIVE_NAME", NativeName(enum_def));
+
+ // Generate native union.
+ code_ += "#[non_exhaustive]";
+ code_ += "#[derive(Debug, Clone, PartialEq)]";
+ code_ += "pub enum {{NATIVE_NAME}} {";
+ code_ += " NONE,";
+ ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+ code_ += " {{NATIVE_VARIANT}}(Box<{{U_ELEMENT_TABLE_TYPE}}>),";
+ });
+ code_ += "}";
+ // Generate Default (NONE).
+ code_ += "impl Default for {{NATIVE_NAME}} {";
+ code_ += " fn default() -> Self {";
+ code_ += " Self::NONE";
+ code_ += " }";
+ code_ += "}";
+
+ // Generate native union methods.
+ code_ += "impl {{NATIVE_NAME}} {";
+
+ // Get flatbuffers union key.
+ // CASPER: add docstrings?
+ code_ += " pub fn {{ENUM_NAME_SNAKE}}_type(&self) -> {{ENUM_NAME}} {";
+ code_ += " match self {";
+ code_ += " Self::NONE => {{ENUM_NAME}}::NONE,";
+ ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+ code_ +=
+ " Self::{{NATIVE_VARIANT}}(_) => {{ENUM_NAME}}::"
+ "{{VARIANT_NAME}},";
+ });
+ code_ += " }";
+ code_ += " }";
+ // Pack flatbuffers union value
+ code_ +=
+ " pub fn pack(&self, fbb: &mut flatbuffers::FlatBufferBuilder)"
+ " -> Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>>"
+ " {";
+ code_ += " match self {";
+ code_ += " Self::NONE => None,";
+ ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+ code_ +=
+ " Self::{{NATIVE_VARIANT}}(v) => "
+ "Some(v.pack(fbb).as_union_value()),";
+ });
+ code_ += " }";
+ code_ += " }";
+
+ // Generate some accessors;
+ ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+ // Move accessor.
+ code_ +=
+ " /// If the union variant matches, return the owned "
+ "{{U_ELEMENT_TABLE_TYPE}}, setting the union to NONE.";
+ code_ +=
+ " pub fn take_{{U_ELEMENT_NAME}}(&mut self) -> "
+ "Option<Box<{{U_ELEMENT_TABLE_TYPE}}>> {";
+ code_ += " if let Self::{{NATIVE_VARIANT}}(_) = self {";
+ code_ += " let v = std::mem::replace(self, Self::NONE);";
+ code_ += " if let Self::{{NATIVE_VARIANT}}(w) = v {";
+ code_ += " Some(w)";
+ code_ += " } else {";
+ code_ += " unreachable!()";
+ code_ += " }";
+ code_ += " } else {";
+ code_ += " None";
+ code_ += " }";
+ code_ += " }";
+ // Immutable reference accessor.
+ code_ +=
+ " /// If the union variant matches, return a reference to the "
+ "{{U_ELEMENT_TABLE_TYPE}}.";
+ code_ +=
+ " pub fn as_{{U_ELEMENT_NAME}}(&self) -> "
+ "Option<&{{U_ELEMENT_TABLE_TYPE}}> {";
+ code_ +=
+ " if let Self::{{NATIVE_VARIANT}}(v) = self "
+ "{ Some(v.as_ref()) } else { None }";
+ code_ += " }";
+ // Mutable reference accessor.
+ code_ +=
+ " /// If the union variant matches, return a mutable reference"
+ " to the {{U_ELEMENT_TABLE_TYPE}}.";
+ code_ +=
+ " pub fn as_{{U_ELEMENT_NAME}}_mut(&mut self) -> "
+ "Option<&mut {{U_ELEMENT_TABLE_TYPE}}> {";
+ code_ +=
+ " if let Self::{{NATIVE_VARIANT}}(v) = self "
+ "{ Some(v.as_mut()) } else { None }";
+ code_ += " }";
+ });
+ code_ += "}"; // End union methods impl.
+ }
+
+ std::string GetFieldOffsetName(const FieldDef &field) {
+ return "VT_" + MakeUpper(Name(field));
+ }
+
+ enum DefaultContext { kBuilder, kAccessor, kObject };
+ std::string GetDefaultValue(const FieldDef &field,
+ const DefaultContext context) {
+ if (context == kBuilder) {
+ // Builders and Args structs model nonscalars "optional" even if they're
+ // required or have defaults according to the schema. I guess its because
+ // WIPOffset is not nullable.
+ if (!IsScalar(field.value.type.base_type) || field.IsOptional()) {
+ return "None";
+ }
+ } else {
+ // This for defaults in objects.
+ // Unions have a NONE variant instead of using Rust's None.
+ if (field.IsOptional() && !IsUnion(field.value.type)) { return "None"; }
+ }
+ switch (GetFullType(field.value.type)) {
+ case ftInteger:
+ case ftFloat: {
+ return field.value.constant;
+ }
+ case ftBool: {
+ return field.value.constant == "0" ? "false" : "true";
+ }
+ case ftUnionKey:
+ case ftEnumKey: {
+ auto ev = field.value.type.enum_def->FindByValue(field.value.constant);
+ if (!ev) return "Default::default()"; // Bitflags enum.
+ return WrapInNameSpace(field.value.type.enum_def->defined_namespace,
+ GetEnumValue(*field.value.type.enum_def, *ev));
+ }
+ case ftUnionValue: {
+ return ObjectFieldType(field, true) + "::NONE";
+ }
+ case ftString: {
+ // Required fields do not have defaults defined by the schema, but we
+ // need one for Rust's Default trait so we use empty string. The usual
+ // value of field.value.constant is `0`, which is non-sensical except
+ // maybe to c++ (nullptr == 0).
+ // TODO: Escape strings?
+ const std::string defval =
+ field.IsRequired() ? "\"\"" : "\"" + field.value.constant + "\"";
+ if (context == kObject) return defval + ".to_string()";
+ if (context == kAccessor) return "&" + defval;
+ FLATBUFFERS_ASSERT("Unreachable.");
+ return "INVALID_CODE_GENERATION";
+ }
+
+ case ftArrayOfStruct:
+ case ftArrayOfEnum:
+ case ftArrayOfBuiltin:
+ case ftVectorOfBool:
+ case ftVectorOfFloat:
+ case ftVectorOfInteger:
+ case ftVectorOfString:
+ case ftVectorOfStruct:
+ case ftVectorOfTable:
+ case ftVectorOfEnumKey:
+ case ftVectorOfUnionValue:
+ case ftStruct:
+ case ftTable: {
+ // We only support empty vectors which matches the defaults for
+ // &[T] and Vec<T> anyway.
+ //
+ // For required structs and tables fields, we defer to their object API
+ // defaults. This works so long as there's nothing recursive happening,
+ // but `table Infinity { i: Infinity (required); }` does compile.
+ return "Default::default()";
+ }
+ }
+ FLATBUFFERS_ASSERT("Unreachable.");
+ return "INVALID_CODE_GENERATION";
+ }
+
+ // Create the return type for fields in the *BuilderArgs structs that are
+ // used to create Tables.
+ //
+ // Note: we could make all inputs to the BuilderArgs be an Option, as well
+ // as all outputs. But, the UX of Flatbuffers is that the user doesn't get to
+ // know if the value is default or not, because there are three ways to
+ // return a default value:
+ // 1) return a stored value that happens to be the default,
+ // 2) return a hardcoded value because the relevant vtable field is not in
+ // the vtable, or
+ // 3) return a hardcoded value because the vtable field value is set to zero.
+ std::string TableBuilderArgsDefnType(const FieldDef &field,
+ const std::string &lifetime) {
+ const Type &type = field.value.type;
+ auto WrapOption = [&](std::string s) {
+ return IsOptionalToBuilder(field) ? "Option<" + s + ">" : s;
+ };
+ auto WrapVector = [&](std::string ty) {
+ return WrapOption("flatbuffers::WIPOffset<flatbuffers::Vector<" +
+ lifetime + ", " + ty + ">>");
+ };
+ auto WrapUOffsetsVector = [&](std::string ty) {
+ return WrapVector("flatbuffers::ForwardsUOffset<" + ty + ">");
+ };
+
+ switch (GetFullType(type)) {
+ case ftInteger:
+ case ftFloat:
+ case ftBool: {
+ return WrapOption(GetTypeBasic(type));
+ }
+ case ftStruct: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapOption("&" + lifetime + " " + typname);
+ }
+ case ftTable: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapOption("flatbuffers::WIPOffset<" + typname + "<" + lifetime +
+ ">>");
+ }
+ case ftString: {
+ return WrapOption("flatbuffers::WIPOffset<&" + lifetime + " str>");
+ }
+ case ftEnumKey:
+ case ftUnionKey: {
+ return WrapOption(WrapInNameSpace(*type.enum_def));
+ }
+ case ftUnionValue: {
+ return "Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>>";
+ }
+
+ case ftVectorOfInteger:
+ case ftVectorOfBool:
+ case ftVectorOfFloat: {
+ const auto typname = GetTypeBasic(type.VectorType());
+ return WrapVector(typname);
+ }
+ case ftVectorOfEnumKey: {
+ const auto typname = WrapInNameSpace(*type.enum_def);
+ return WrapVector(typname);
+ }
+ case ftVectorOfStruct: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapVector(typname);
+ }
+ case ftVectorOfTable: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapUOffsetsVector(typname + "<" + lifetime + ">");
+ }
+ case ftVectorOfString: {
+ return WrapUOffsetsVector("&" + lifetime + " str");
+ }
+ case ftVectorOfUnionValue: {
+ return WrapUOffsetsVector("flatbuffers::Table<" + lifetime + ">");
+ }
+ case ftArrayOfEnum:
+ case ftArrayOfStruct:
+ case ftArrayOfBuiltin: {
+ FLATBUFFERS_ASSERT(false && "arrays are not supported within tables");
+ return "ARRAYS_NOT_SUPPORTED_IN_TABLES";
+ }
+ }
+ return "INVALID_CODE_GENERATION"; // for return analysis
+ }
+
+ std::string ObjectFieldType(const FieldDef &field, bool in_a_table) {
+ const Type &type = field.value.type;
+ std::string ty;
+ switch (GetFullType(type)) {
+ case ftInteger:
+ case ftBool:
+ case ftFloat: {
+ ty = GetTypeBasic(type);
+ break;
+ }
+ case ftString: {
+ ty = "String";
+ break;
+ }
+ case ftStruct: {
+ ty = NamespacedNativeName(*type.struct_def);
+ break;
+ }
+ case ftTable: {
+ // Since Tables can contain themselves, Box is required to avoid
+ // infinite types.
+ ty = "Box<" + NamespacedNativeName(*type.struct_def) + ">";
+ break;
+ }
+ case ftUnionKey: {
+ // There is no native "UnionKey", natively, unions are rust enums with
+ // newtype-struct-variants.
+ return "INVALID_CODE_GENERATION";
+ }
+ case ftUnionValue: {
+ ty = NamespacedNativeName(*type.enum_def);
+ break;
+ }
+ case ftEnumKey: {
+ ty = WrapInNameSpace(*type.enum_def);
+ break;
+ }
+ // Vectors are in tables and are optional
+ case ftVectorOfEnumKey: {
+ ty = "Vec<" + WrapInNameSpace(*type.VectorType().enum_def) + ">";
+ break;
+ }
+ case ftVectorOfInteger:
+ case ftVectorOfBool:
+ case ftVectorOfFloat: {
+ ty = "Vec<" + GetTypeBasic(type.VectorType()) + ">";
+ break;
+ }
+ case ftVectorOfString: {
+ ty = "Vec<String>";
+ break;
+ }
+ case ftVectorOfTable:
+ case ftVectorOfStruct: {
+ ty = NamespacedNativeName(*type.VectorType().struct_def);
+ ty = "Vec<" + ty + ">";
+ break;
+ }
+ case ftVectorOfUnionValue: {
+ FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported");
+ return "INVALID_CODE_GENERATION"; // OH NO!
+ }
+ case ftArrayOfEnum: {
+ ty = "[" + WrapInNameSpace(*type.VectorType().enum_def) + "; " +
+ NumToString(type.fixed_length) + "]";
+ break;
+ }
+ case ftArrayOfStruct: {
+ ty = "[" + NamespacedNativeName(*type.VectorType().struct_def) + "; " +
+ NumToString(type.fixed_length) + "]";
+ break;
+ }
+ case ftArrayOfBuiltin: {
+ ty = "[" + GetTypeBasic(type.VectorType()) + "; " +
+ NumToString(type.fixed_length) + "]";
+ break;
+ }
+ }
+ if (in_a_table && !IsUnion(type) && field.IsOptional()) {
+ return "Option<" + ty + ">";
+ } else {
+ return ty;
+ }
+ }
+
+ std::string TableBuilderArgsAddFuncType(const FieldDef &field,
+ const std::string &lifetime) {
+ const Type &type = field.value.type;
+
+ switch (GetFullType(field.value.type)) {
+ case ftVectorOfStruct: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + ", " +
+ typname + ">>";
+ }
+ case ftVectorOfTable: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime +
+ ", flatbuffers::ForwardsUOffset<" + typname + "<" + lifetime +
+ ">>>>";
+ }
+ case ftVectorOfInteger:
+ case ftVectorOfBool:
+ case ftVectorOfFloat: {
+ const auto typname = GetTypeBasic(type.VectorType());
+ return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + ", " +
+ typname + ">>";
+ }
+ case ftVectorOfString: {
+ return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime +
+ ", flatbuffers::ForwardsUOffset<&" + lifetime + " str>>>";
+ }
+ case ftVectorOfEnumKey: {
+ const auto typname = WrapInNameSpace(*type.enum_def);
+ return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + ", " +
+ typname + ">>";
+ }
+ case ftVectorOfUnionValue: {
+ return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime +
+ ", flatbuffers::ForwardsUOffset<flatbuffers::Table<" + lifetime +
+ ">>>";
+ }
+ case ftEnumKey:
+ case ftUnionKey: {
+ const auto typname = WrapInNameSpace(*type.enum_def);
+ return typname;
+ }
+ case ftStruct: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return "&" + typname + "";
+ }
+ case ftTable: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return "flatbuffers::WIPOffset<" + typname + "<" + lifetime + ">>";
+ }
+ case ftInteger:
+ case ftBool:
+ case ftFloat: {
+ return GetTypeBasic(type);
+ }
+ case ftString: {
+ return "flatbuffers::WIPOffset<&" + lifetime + " str>";
+ }
+ case ftUnionValue: {
+ return "flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>";
+ }
+ case ftArrayOfBuiltin: {
+ const auto typname = GetTypeBasic(type.VectorType());
+ return "flatbuffers::Array<" + lifetime + ", " + typname + ", " +
+ NumToString(type.fixed_length) + ">";
+ }
+ case ftArrayOfEnum: {
+ const auto typname = WrapInNameSpace(*type.enum_def);
+ return "flatbuffers::Array<" + lifetime + ", " + typname + ", " +
+ NumToString(type.fixed_length) + ">";
+ }
+ case ftArrayOfStruct: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return "flatbuffers::Array<" + lifetime + ", " + typname + ", " +
+ NumToString(type.fixed_length) + ">";
+ }
+ }
+
+ return "INVALID_CODE_GENERATION"; // for return analysis
+ }
+
+ std::string TableBuilderArgsAddFuncBody(const FieldDef &field) {
+ const Type &type = field.value.type;
+
+ switch (GetFullType(field.value.type)) {
+ case ftInteger:
+ case ftBool:
+ case ftFloat: {
+ const auto typname = GetTypeBasic(field.value.type);
+ return (field.IsOptional() ? "self.fbb_.push_slot_always::<"
+ : "self.fbb_.push_slot::<") +
+ typname + ">";
+ }
+ case ftEnumKey:
+ case ftUnionKey: {
+ const auto underlying_typname = GetTypeBasic(type);
+ return (field.IsOptional() ? "self.fbb_.push_slot_always::<"
+ : "self.fbb_.push_slot::<") +
+ underlying_typname + ">";
+ }
+
+ case ftStruct: {
+ const std::string typname = WrapInNameSpace(*type.struct_def);
+ return "self.fbb_.push_slot_always::<&" + typname + ">";
+ }
+ case ftTable: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return "self.fbb_.push_slot_always::<flatbuffers::WIPOffset<" +
+ typname + ">>";
+ }
+
+ case ftUnionValue:
+ case ftString:
+ case ftVectorOfInteger:
+ case ftVectorOfFloat:
+ case ftVectorOfBool:
+ case ftVectorOfEnumKey:
+ case ftVectorOfStruct:
+ case ftVectorOfTable:
+ case ftVectorOfString:
+ case ftVectorOfUnionValue: {
+ return "self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>";
+ }
+ case ftArrayOfEnum:
+ case ftArrayOfStruct:
+ case ftArrayOfBuiltin: {
+ FLATBUFFERS_ASSERT(false && "arrays are not supported within tables");
+ return "ARRAYS_NOT_SUPPORTED_IN_TABLES";
+ }
+ }
+ return "INVALID_CODE_GENERATION"; // for return analysis
+ }
+
+ std::string GenTableAccessorFuncReturnType(const FieldDef &field,
+ const std::string &lifetime) {
+ const Type &type = field.value.type;
+ const auto WrapOption = [&](std::string s) {
+ return field.IsOptional() ? "Option<" + s + ">" : s;
+ };
+
+ switch (GetFullType(field.value.type)) {
+ case ftInteger:
+ case ftFloat:
+ case ftBool: {
+ return WrapOption(GetTypeBasic(type));
+ }
+ case ftStruct: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapOption("&" + lifetime + " " + typname);
+ }
+ case ftTable: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapOption(typname + "<" + lifetime + ">");
+ }
+ case ftEnumKey:
+ case ftUnionKey: {
+ return WrapOption(WrapInNameSpace(*type.enum_def));
+ }
+
+ case ftUnionValue: {
+ return WrapOption("flatbuffers::Table<" + lifetime + ">");
+ }
+ case ftString: {
+ return WrapOption("&" + lifetime + " str");
+ }
+ case ftVectorOfInteger:
+ case ftVectorOfBool:
+ case ftVectorOfFloat: {
+ const auto typname = GetTypeBasic(type.VectorType());
+ const auto vector_type =
+ IsOneByte(type.VectorType().base_type)
+ ? "&" + lifetime + " [" + typname + "]"
+ : "flatbuffers::Vector<" + lifetime + ", " + typname + ">";
+ return WrapOption(vector_type);
+ }
+ case ftVectorOfEnumKey: {
+ const auto typname = WrapInNameSpace(*type.enum_def);
+ return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname +
+ ">");
+ }
+ case ftVectorOfStruct: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapOption("&" + lifetime + " [" + typname + "]");
+ }
+ case ftVectorOfTable: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapOption("flatbuffers::Vector<" + lifetime +
+ ", flatbuffers::ForwardsUOffset<" + typname + "<" +
+ lifetime + ">>>");
+ }
+ case ftVectorOfString: {
+ return WrapOption("flatbuffers::Vector<" + lifetime +
+ ", flatbuffers::ForwardsUOffset<&" + lifetime +
+ " str>>");
+ }
+ case ftVectorOfUnionValue: {
+ FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported");
+ // TODO(rw): when we do support these, we should consider using the
+ // Into trait to convert tables to typesafe union values.
+ return "INVALID_CODE_GENERATION"; // for return analysis
+ }
+ case ftArrayOfEnum:
+ case ftArrayOfStruct:
+ case ftArrayOfBuiltin: {
+ FLATBUFFERS_ASSERT(false && "arrays are not supported within tables");
+ return "ARRAYS_NOT_SUPPORTED_IN_TABLES";
+ }
+ }
+ return "INVALID_CODE_GENERATION"; // for return analysis
+ }
+
+ std::string FollowType(const Type &type, const std::string &lifetime) {
+ // IsVector... This can be made iterative?
+
+ const auto WrapForwardsUOffset = [](std::string ty) -> std::string {
+ return "flatbuffers::ForwardsUOffset<" + ty + ">";
+ };
+ const auto WrapVector = [&](std::string ty) -> std::string {
+ return "flatbuffers::Vector<" + lifetime + ", " + ty + ">";
+ };
+ const auto WrapArray = [&](std::string ty, uint16_t length) -> std::string {
+ return "flatbuffers::Array<" + lifetime + ", " + ty + ", " +
+ NumToString(length) + ">";
+ };
+ switch (GetFullType(type)) {
+ case ftInteger:
+ case ftFloat:
+ case ftBool: {
+ return GetTypeBasic(type);
+ }
+ case ftStruct: {
+ return WrapInNameSpace(*type.struct_def);
+ }
+ case ftUnionKey:
+ case ftEnumKey: {
+ return WrapInNameSpace(*type.enum_def);
+ }
+ case ftTable: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapForwardsUOffset(typname);
+ }
+ case ftUnionValue: {
+ return WrapForwardsUOffset("flatbuffers::Table<" + lifetime + ">");
+ }
+ case ftString: {
+ return WrapForwardsUOffset("&str");
+ }
+ case ftVectorOfInteger:
+ case ftVectorOfBool:
+ case ftVectorOfFloat: {
+ const auto typname = GetTypeBasic(type.VectorType());
+ return WrapForwardsUOffset(WrapVector(typname));
+ }
+ case ftVectorOfEnumKey: {
+ const auto typname = WrapInNameSpace(*type.VectorType().enum_def);
+ return WrapForwardsUOffset(WrapVector(typname));
+ }
+ case ftVectorOfStruct: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapForwardsUOffset(WrapVector(typname));
+ }
+ case ftVectorOfTable: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapForwardsUOffset(WrapVector(WrapForwardsUOffset(typname)));
+ }
+ case ftVectorOfString: {
+ return WrapForwardsUOffset(
+ WrapVector(WrapForwardsUOffset("&" + lifetime + " str")));
+ }
+ case ftVectorOfUnionValue: {
+ FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported");
+ return "INVALID_CODE_GENERATION"; // for return analysis
+ }
+ case ftArrayOfEnum: {
+ const auto typname = WrapInNameSpace(*type.VectorType().enum_def);
+ return WrapArray(typname, type.fixed_length);
+ }
+ case ftArrayOfStruct: {
+ const auto typname = WrapInNameSpace(*type.struct_def);
+ return WrapArray(typname, type.fixed_length);
+ }
+ case ftArrayOfBuiltin: {
+ const auto typname = GetTypeBasic(type.VectorType());
+ return WrapArray(typname, type.fixed_length);
+ }
+ }
+ return "INVALID_CODE_GENERATION"; // for return analysis
+ }
+
+ std::string GenTableAccessorFuncBody(const FieldDef &field,
+ const std::string &lifetime) {
+ const std::string vt_offset = GetFieldOffsetName(field);
+ const std::string typname = FollowType(field.value.type, lifetime);
+ // Default-y fields (scalars so far) are neither optional nor required.
+ const std::string default_value =
+ !(field.IsOptional() || field.IsRequired())
+ ? "Some(" + GetDefaultValue(field, kAccessor) + ")"
+ : "None";
+ const std::string unwrap = field.IsOptional() ? "" : ".unwrap()";
+
+ const auto t = GetFullType(field.value.type);
+
+ // TODO(caspern): Shouldn't 1byte VectorOfEnumKey be slice too?
+ const std::string safe_slice =
+ (t == ftVectorOfStruct ||
+ ((t == ftVectorOfBool || t == ftVectorOfFloat ||
+ t == ftVectorOfInteger) &&
+ IsOneByte(field.value.type.VectorType().base_type)))
+ ? ".map(|v| v.safe_slice())"
+ : "";
+
+ return "self._tab.get::<" + typname + ">({{STRUCT_NAME}}::" + vt_offset +
+ ", " + default_value + ")" + safe_slice + unwrap;
+ }
+
+ // Generates a fully-qualified name getter for use with --gen-name-strings
+ void GenFullyQualifiedNameGetter(const StructDef &struct_def,
+ const std::string &name) {
+ code_ += " pub const fn get_fully_qualified_name() -> &'static str {";
+ code_ += " \"" +
+ struct_def.defined_namespace->GetFullyQualifiedName(name) + "\"";
+ code_ += " }";
+ code_ += "";
+ }
+
+ void ForAllUnionVariantsBesidesNone(
+ const EnumDef &def, std::function<void(const EnumVal &ev)> cb) {
+ FLATBUFFERS_ASSERT(def.is_union);
+
+ for (auto it = def.Vals().begin(); it != def.Vals().end(); ++it) {
+ const EnumVal &ev = **it;
+ // TODO(cneo): Can variants be deprecated, should we skip them?
+ if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
+ code_.SetValue(
+ "U_ELEMENT_ENUM_TYPE",
+ WrapInNameSpace(def.defined_namespace, GetEnumValue(def, ev)));
+ code_.SetValue(
+ "U_ELEMENT_TABLE_TYPE",
+ WrapInNameSpace(ev.union_type.struct_def->defined_namespace,
+ ev.union_type.struct_def->name));
+ code_.SetValue("U_ELEMENT_NAME", MakeSnakeCase(Name(ev)));
+ cb(ev);
+ }
+ }
+
+ void ForAllTableFields(const StructDef &struct_def,
+ std::function<void(const FieldDef &)> cb,
+ bool reversed = false) {
+ // TODO(cneo): Remove `reversed` overload. It's only here to minimize the
+ // diff when refactoring to the `ForAllX` helper functions.
+ auto go = [&](const FieldDef &field) {
+ if (field.deprecated) return;
+ code_.SetValue("OFFSET_NAME", GetFieldOffsetName(field));
+ code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("BLDR_DEF_VAL", GetDefaultValue(field, kBuilder));
+ cb(field);
+ };
+ const auto &fields = struct_def.fields.vec;
+ if (reversed) {
+ for (auto it = fields.rbegin(); it != fields.rend(); ++it) go(**it);
+ } else {
+ for (auto it = fields.begin(); it != fields.end(); ++it) go(**it);
+ }
+ }
+ // Generate an accessor struct, builder struct, and create function for a
+ // table.
+ void GenTable(const StructDef &struct_def) {
+ code_.SetValue("STRUCT_NAME", Name(struct_def));
+ code_.SetValue("OFFSET_TYPELABEL", Name(struct_def) + "Offset");
+ code_.SetValue("STRUCT_NAME_SNAKECASE", MakeSnakeCase(Name(struct_def)));
+
+ // Generate an offset type, the base type, the Follow impl, and the
+ // init_from_table impl.
+ code_ += "pub enum {{OFFSET_TYPELABEL}} {}";
+ code_ += "#[derive(Copy, Clone, PartialEq)]";
+ code_ += "";
+
+ GenComment(struct_def.doc_comment);
+
+ code_ += "pub struct {{STRUCT_NAME}}<'a> {";
+ code_ += " pub _tab: flatbuffers::Table<'a>,";
+ code_ += "}";
+ code_ += "";
+ code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_NAME}}<'a> {";
+ code_ += " type Inner = {{STRUCT_NAME}}<'a>;";
+ code_ += " #[inline]";
+ code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " Self { _tab: flatbuffers::Table { buf, loc } }";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+ code_ += "impl<'a> {{STRUCT_NAME}}<'a> {";
+
+ if (parser_.opts.generate_name_strings) {
+ GenFullyQualifiedNameGetter(struct_def, struct_def.name);
+ }
+
+ code_ += " #[inline]";
+ code_ +=
+ " pub fn init_from_table(table: flatbuffers::Table<'a>) -> "
+ "Self {";
+ code_ += " {{STRUCT_NAME}} { _tab: table }";
+ code_ += " }";
+
+ // Generate a convenient create* function that uses the above builder
+ // to create a table in one function call.
+ code_.SetValue("MAYBE_US", struct_def.fields.vec.size() == 0 ? "_" : "");
+ 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_ +=
+ " {{MAYBE_US}}args: &'args {{STRUCT_NAME}}Args{{MAYBE_LT}})"
+ " -> flatbuffers::WIPOffset<{{STRUCT_NAME}}<'bldr>> {";
+
+ code_ += " let mut builder = {{STRUCT_NAME}}Builder::new(_fbb);";
+ for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
+ size; size /= 2) {
+ ForAllTableFields(
+ struct_def,
+ [&](const FieldDef &field) {
+ if (struct_def.sortbysize &&
+ size != SizeOf(field.value.type.base_type))
+ return;
+ if (IsOptionalToBuilder(field)) {
+ code_ +=
+ " if let Some(x) = args.{{FIELD_NAME}} "
+ "{ builder.add_{{FIELD_NAME}}(x); }";
+ } else {
+ code_ += " builder.add_{{FIELD_NAME}}(args.{{FIELD_NAME}});";
+ }
+ },
+ /*reverse=*/true);
+ }
+ code_ += " builder.finish()";
+ code_ += " }";
+ code_ += "";
+ // Generate Object API Packer function.
+ if (parser_.opts.generate_object_based_api) {
+ // TODO(cneo): Replace more for loops with ForAllX stuff.
+ // TODO(cneo): Manage indentation with IncrementIdentLevel?
+ code_.SetValue("OBJECT_NAME", NativeName(struct_def));
+ code_ += " pub fn unpack(&self) -> {{OBJECT_NAME}} {";
+ ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
+ const Type &type = field.value.type;
+ switch (GetFullType(type)) {
+ case ftInteger:
+ case ftBool:
+ case ftFloat:
+ case ftEnumKey: {
+ code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}();";
+ return;
+ }
+ case ftUnionKey: return;
+ case ftUnionValue: {
+ const auto &enum_def = *type.enum_def;
+ code_.SetValue("ENUM_NAME", WrapInNameSpace(enum_def));
+ code_.SetValue("NATIVE_ENUM_NAME", NamespacedNativeName(enum_def));
+ code_ +=
+ " let {{FIELD_NAME}} = match "
+ "self.{{FIELD_NAME}}_type() {";
+ code_ +=
+ " {{ENUM_NAME}}::NONE =>"
+ " {{NATIVE_ENUM_NAME}}::NONE,";
+ ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
+ code_ +=
+ " {{ENUM_NAME}}::{{VARIANT_NAME}} => "
+ "{{NATIVE_ENUM_NAME}}::{{NATIVE_VARIANT}}(Box::new(";
+ code_ +=
+ " self.{{FIELD_NAME}}_as_"
+ "{{U_ELEMENT_NAME}}()";
+ code_ +=
+ " .expect(\"Invalid union table, "
+ "expected `{{ENUM_NAME}}::{{VARIANT_NAME}}`.\")";
+ code_ += " .unpack()";
+ code_ += " )),";
+ });
+ // Maybe we shouldn't throw away unknown discriminants?
+ code_ += " _ => {{NATIVE_ENUM_NAME}}::NONE,";
+ code_ += " };";
+ return;
+ }
+ // The rest of the types need special handling based on if the field
+ // is optional or not.
+ case ftString: {
+ code_.SetValue("EXPR", "x.to_string()");
+ break;
+ }
+ case ftStruct: {
+ code_.SetValue("EXPR", "x.unpack()");
+ break;
+ }
+ case ftTable: {
+ code_.SetValue("EXPR", "Box::new(x.unpack())");
+ break;
+ }
+ case ftVectorOfInteger:
+ case ftVectorOfBool: {
+ if (IsOneByte(type.VectorType().base_type)) {
+ // 1 byte stuff is viewed w/ slice instead of flatbuffer::Vector
+ // and thus needs to be cloned out of the slice.
+ code_.SetValue("EXPR", "x.to_vec()");
+ break;
+ }
+ code_.SetValue("EXPR", "x.into_iter().collect()");
+ break;
+ }
+ case ftVectorOfFloat:
+ case ftVectorOfEnumKey: {
+ code_.SetValue("EXPR", "x.into_iter().collect()");
+ break;
+ }
+ case ftVectorOfString: {
+ code_.SetValue("EXPR", "x.iter().map(|s| s.to_string()).collect()");
+ break;
+ }
+ case ftVectorOfStruct:
+ case ftVectorOfTable: {
+ code_.SetValue("EXPR", "x.iter().map(|t| t.unpack()).collect()");
+ break;
+ }
+ case ftVectorOfUnionValue: {
+ FLATBUFFERS_ASSERT(false && "vectors of unions not yet supported");
+ return;
+ }
+ case ftArrayOfEnum:
+ case ftArrayOfStruct:
+ case ftArrayOfBuiltin: {
+ FLATBUFFERS_ASSERT(false &&
+ "arrays are not supported within tables");
+ return;
+ }
+ }
+ if (field.IsOptional()) {
+ code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}().map(|x| {";
+ code_ += " {{EXPR}}";
+ code_ += " });";
+ } else {
+ code_ += " let {{FIELD_NAME}} = {";
+ code_ += " let x = self.{{FIELD_NAME}}();";
+ code_ += " {{EXPR}}";
+ code_ += " };";
+ }
+ });
+ code_ += " {{OBJECT_NAME}} {";
+ ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
+ if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
+ code_ += " {{FIELD_NAME}},";
+ });
+ code_ += " }";
+ code_ += " }";
+ }
+
+ // Generate field id constants.
+ ForAllTableFields(struct_def, [&](const FieldDef &unused) {
+ (void)unused;
+ code_ +=
+ " pub const {{OFFSET_NAME}}: flatbuffers::VOffsetT = "
+ "{{OFFSET_VALUE}};";
+ });
+ if (struct_def.fields.vec.size() > 0) code_ += "";
+
+ // Generate the accessors. Each has one of two forms:
+ //
+ // If a value can be None:
+ // pub fn name(&'a self) -> Option<user_facing_type> {
+ // self._tab.get::<internal_type>(offset, defaultval)
+ // }
+ //
+ // If a value is always Some:
+ // pub fn name(&'a self) -> user_facing_type {
+ // self._tab.get::<internal_type>(offset, defaultval).unwrap()
+ // }
+ ForAllTableFields(struct_def, [&](const FieldDef &field) {
+ code_.SetValue("RETURN_TYPE",
+ GenTableAccessorFuncReturnType(field, "'a"));
+
+ this->GenComment(field.doc_comment, " ");
+ code_ += " #[inline]";
+ code_ += " pub fn {{FIELD_NAME}}(&self) -> {{RETURN_TYPE}} {";
+ code_ += " " + GenTableAccessorFuncBody(field, "'a");
+ code_ += " }";
+
+ // Generate a comparison function for this field if it is a key.
+ if (field.key) { GenKeyFieldMethods(field); }
+
+ // Generate a nested flatbuffer field, if applicable.
+ auto nested = field.attributes.Lookup("nested_flatbuffer");
+ if (nested) {
+ std::string qualified_name = nested->constant;
+ auto nested_root = parser_.LookupStruct(nested->constant);
+ if (nested_root == nullptr) {
+ qualified_name = parser_.current_namespace_->GetFullyQualifiedName(
+ nested->constant);
+ nested_root = parser_.LookupStruct(qualified_name);
+ }
+ FLATBUFFERS_ASSERT(nested_root); // Guaranteed to exist by parser.
+
+ code_.SetValue("NESTED", WrapInNameSpace(*nested_root));
+ code_ += " pub fn {{FIELD_NAME}}_nested_flatbuffer(&'a self) -> \\";
+ if (field.IsRequired()) {
+ code_ += "{{NESTED}}<'a> {";
+ code_ += " let data = self.{{FIELD_NAME}}();";
+ code_ += " use flatbuffers::Follow;";
+ code_ +=
+ " <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
+ "::follow(data, 0)";
+ } else {
+ code_ += "Option<{{NESTED}}<'a>> {";
+ code_ += " self.{{FIELD_NAME}}().map(|data| {";
+ code_ += " use flatbuffers::Follow;";
+ code_ +=
+ " <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
+ "::follow(data, 0)";
+ code_ += " })";
+ }
+ code_ += " }";
+ }
+ });
+
+ // Explicit specializations for union accessors
+ ForAllTableFields(struct_def, [&](const FieldDef &field) {
+ if (field.value.type.base_type != BASE_TYPE_UNION) return;
+ code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name);
+ ForAllUnionVariantsBesidesNone(
+ *field.value.type.enum_def, [&](const EnumVal &unused) {
+ (void)unused;
+ code_ += " #[inline]";
+ code_ += " #[allow(non_snake_case)]";
+ code_ +=
+ " pub fn {{FIELD_NAME}}_as_{{U_ELEMENT_NAME}}(&self) -> "
+ "Option<{{U_ELEMENT_TABLE_TYPE}}<'a>> {";
+ // If the user defined schemas name a field that clashes with a
+ // language reserved word, flatc will try to escape the field name
+ // by appending an underscore. This works well for most cases,
+ // except one. When generating union accessors (and referring to
+ // them internally within the code generated here), an extra
+ // underscore will be appended to the name, causing build failures.
+ //
+ // This only happens when unions have members that overlap with
+ // language reserved words.
+ //
+ // To avoid this problem the type field name is used unescaped here:
+ code_ +=
+ " if self.{{FIELD_TYPE_FIELD_NAME}}_type() == "
+ "{{U_ELEMENT_ENUM_TYPE}} {";
+
+ // The following logic is not tested in the integration test,
+ // as of April 10, 2020
+ if (field.IsRequired()) {
+ code_ += " let u = self.{{FIELD_NAME}}();";
+ code_ +=
+ " Some({{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))";
+ } else {
+ code_ +=
+ " self.{{FIELD_NAME}}().map("
+ "{{U_ELEMENT_TABLE_TYPE}}::init_from_table)";
+ }
+ code_ += " } else {";
+ code_ += " None";
+ code_ += " }";
+ code_ += " }";
+ code_ += "";
+ });
+ });
+ code_ += "}"; // End of table impl.
+ code_ += "";
+
+ // Generate Verifier;
+ code_ += "impl flatbuffers::Verifiable for {{STRUCT_NAME}}<'_> {";
+ code_ += " #[inline]";
+ code_ += " fn run_verifier(";
+ code_ += " v: &mut flatbuffers::Verifier, pos: usize";
+ code_ += " ) -> Result<(), flatbuffers::InvalidFlatbuffer> {";
+ code_ += " use self::flatbuffers::Verifiable;";
+ code_ += " v.visit_table(pos)?\\";
+ // Escape newline and insert it onthe next line so we can end the builder
+ // with a nice semicolon.
+ ForAllTableFields(struct_def, [&](const FieldDef &field) {
+ if (GetFullType(field.value.type) == ftUnionKey) return;
+
+ code_.SetValue("IS_REQ", field.IsRequired() ? "true" : "false");
+ if (GetFullType(field.value.type) != ftUnionValue) {
+ // All types besides unions.
+ code_.SetValue("TY", FollowType(field.value.type, "'_"));
+ code_ +=
+ "\n .visit_field::<{{TY}}>(&\"{{FIELD_NAME}}\", "
+ "Self::{{OFFSET_NAME}}, {{IS_REQ}})?\\";
+ return;
+ }
+ // Unions.
+ EnumDef &union_def = *field.value.type.enum_def;
+ code_.SetValue("UNION_TYPE", WrapInNameSpace(union_def));
+ code_ +=
+ "\n .visit_union::<{{UNION_TYPE}}, _>("
+ "&\"{{FIELD_NAME}}_type\", Self::{{OFFSET_NAME}}_TYPE, "
+ "&\"{{FIELD_NAME}}\", Self::{{OFFSET_NAME}}, {{IS_REQ}}, "
+ "|key, v, pos| {";
+ code_ += " match key {";
+ ForAllUnionVariantsBesidesNone(union_def, [&](const EnumVal &unused) {
+ (void)unused;
+ code_ +=
+ " {{U_ELEMENT_ENUM_TYPE}} => v.verify_union_variant::"
+ "<flatbuffers::ForwardsUOffset<{{U_ELEMENT_TABLE_TYPE}}>>("
+ "\"{{U_ELEMENT_ENUM_TYPE}}\", pos),";
+ });
+ code_ += " _ => Ok(()),";
+ code_ += " }";
+ code_ += " })?\\";
+ });
+ code_ += "\n .finish();";
+ code_ += " Ok(())";
+ code_ += " }";
+ code_ += "}";
+
+ // Generate an args struct:
+ code_.SetValue("MAYBE_LT",
+ TableBuilderArgsNeedsLifetime(struct_def) ? "<'a>" : "");
+ code_ += "pub struct {{STRUCT_NAME}}Args{{MAYBE_LT}} {";
+ ForAllTableFields(struct_def, [&](const FieldDef &field) {
+ code_.SetValue("PARAM_TYPE", TableBuilderArgsDefnType(field, "'a"));
+ code_ += " pub {{FIELD_NAME}}: {{PARAM_TYPE}},";
+ });
+ code_ += "}";
+
+ // Generate an impl of Default for the *Args type:
+ code_ += "impl<'a> Default for {{STRUCT_NAME}}Args{{MAYBE_LT}} {";
+ code_ += " #[inline]";
+ code_ += " fn default() -> Self {";
+ code_ += " {{STRUCT_NAME}}Args {";
+ ForAllTableFields(struct_def, [&](const FieldDef &field) {
+ code_ += " {{FIELD_NAME}}: {{BLDR_DEF_VAL}},\\";
+ code_ += field.IsRequired() ? " // required field" : "";
+ });
+ code_ += " }";
+ code_ += " }";
+ code_ += "}";
+
+ // Generate a builder struct:
+ code_ += "pub struct {{STRUCT_NAME}}Builder<'a: 'b, 'b> {";
+ code_ += " fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,";
+ code_ +=
+ " start_: flatbuffers::WIPOffset<"
+ "flatbuffers::TableUnfinishedWIPOffset>,";
+ code_ += "}";
+
+ // Generate builder functions:
+ code_ += "impl<'a: 'b, 'b> {{STRUCT_NAME}}Builder<'a, 'b> {";
+ ForAllTableFields(struct_def, [&](const FieldDef &field) {
+ const bool is_scalar = IsScalar(field.value.type.base_type);
+ std::string offset = GetFieldOffsetName(field);
+ // Generate functions to add data, which take one of two forms.
+ //
+ // If a value has a default:
+ // fn add_x(x_: type) {
+ // fbb_.push_slot::<type>(offset, x_, Some(default));
+ // }
+ //
+ // If a value does not have a default:
+ // fn add_x(x_: type) {
+ // fbb_.push_slot_always::<type>(offset, x_);
+ // }
+ code_.SetValue("FIELD_OFFSET", Name(struct_def) + "::" + offset);
+ code_.SetValue("FIELD_TYPE", TableBuilderArgsAddFuncType(field, "'b "));
+ code_.SetValue("FUNC_BODY", TableBuilderArgsAddFuncBody(field));
+ code_ += " #[inline]";
+ code_ +=
+ " pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: "
+ "{{FIELD_TYPE}}) {";
+ if (is_scalar && !field.IsOptional()) {
+ code_ +=
+ " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}}, "
+ "{{BLDR_DEF_VAL}});";
+ } else {
+ code_ += " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}});";
+ }
+ code_ += " }";
+ });
+
+ // Struct initializer (all fields required);
+ code_ += " #[inline]";
+ code_ +=
+ " pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> "
+ "{{STRUCT_NAME}}Builder<'a, 'b> {";
+ code_.SetValue("NUM_FIELDS", NumToString(struct_def.fields.vec.size()));
+ code_ += " let start = _fbb.start_table();";
+ code_ += " {{STRUCT_NAME}}Builder {";
+ code_ += " fbb_: _fbb,";
+ code_ += " start_: start,";
+ code_ += " }";
+ code_ += " }";
+
+ // finish() function.
+ code_ += " #[inline]";
+ code_ +=
+ " pub fn finish(self) -> "
+ "flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>> {";
+ code_ += " let o = self.fbb_.end_table(self.start_);";
+
+ ForAllTableFields(struct_def, [&](const FieldDef &field) {
+ if (!field.IsRequired()) return;
+ code_ +=
+ " self.fbb_.required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}},"
+ "\"{{FIELD_NAME}}\");";
+ });
+ code_ += " flatbuffers::WIPOffset::new(o.value())";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+
+ code_ += "impl std::fmt::Debug for {{STRUCT_NAME}}<'_> {";
+ code_ +=
+ " fn fmt(&self, f: &mut std::fmt::Formatter<'_>"
+ ") -> std::fmt::Result {";
+ code_ += " let mut ds = f.debug_struct(\"{{STRUCT_NAME}}\");";
+ ForAllTableFields(struct_def, [&](const FieldDef &field) {
+ if (GetFullType(field.value.type) == ftUnionValue) {
+ // Generate a match statement to handle unions properly.
+ code_.SetValue("KEY_TYPE", GenTableAccessorFuncReturnType(field, ""));
+ code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name);
+ code_.SetValue("UNION_ERR",
+ "&\"InvalidFlatbuffer: Union discriminant"
+ " does not match value.\"");
+
+ code_ += " match self.{{FIELD_NAME}}_type() {";
+ ForAllUnionVariantsBesidesNone(
+ *field.value.type.enum_def, [&](const EnumVal &unused) {
+ (void)unused;
+ code_ += " {{U_ELEMENT_ENUM_TYPE}} => {";
+ code_ +=
+ " if let Some(x) = "
+ "self.{{FIELD_TYPE_FIELD_NAME}}_as_"
+ "{{U_ELEMENT_NAME}}() {";
+ code_ += " ds.field(\"{{FIELD_NAME}}\", &x)";
+ code_ += " } else {";
+ code_ +=
+ " ds.field(\"{{FIELD_NAME}}\", {{UNION_ERR}})";
+ code_ += " }";
+ code_ += " },";
+ });
+ code_ += " _ => {";
+ code_ += " let x: Option<()> = None;";
+ code_ += " ds.field(\"{{FIELD_NAME}}\", &x)";
+ code_ += " },";
+ code_ += " };";
+ } else {
+ // Most fields.
+ code_ += " ds.field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}());";
+ }
+ });
+ code_ += " ds.finish()";
+ code_ += " }";
+ code_ += "}";
+ }
+
+ void GenTableObject(const StructDef &table) {
+ code_.SetValue("OBJECT_NAME", NativeName(table));
+ code_.SetValue("STRUCT_NAME", Name(table));
+
+ // Generate the native object.
+ code_ += "#[non_exhaustive]";
+ code_ += "#[derive(Debug, Clone, PartialEq)]";
+ code_ += "pub struct {{OBJECT_NAME}} {";
+ ForAllObjectTableFields(table, [&](const FieldDef &field) {
+ // Union objects combine both the union discriminant and value, so we
+ // skip making a field for the discriminant.
+ if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
+ code_ += " pub {{FIELD_NAME}}: {{FIELD_OBJECT_TYPE}},";
+ });
+ code_ += "}";
+
+ code_ += "impl Default for {{OBJECT_NAME}} {";
+ code_ += " fn default() -> Self {";
+ code_ += " Self {";
+ ForAllObjectTableFields(table, [&](const FieldDef &field) {
+ if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
+ std::string default_value = GetDefaultValue(field, kObject);
+ code_ += " {{FIELD_NAME}}: " + default_value + ",";
+ });
+ code_ += " }";
+ code_ += " }";
+ code_ += "}";
+
+ // TODO(cneo): Generate defaults for Native tables. However, since structs
+ // may be required, they, and therefore enums need defaults.
+
+ // Generate pack function.
+ code_ += "impl {{OBJECT_NAME}} {";
+ code_ += " pub fn pack<'b>(";
+ code_ += " &self,";
+ code_ += " _fbb: &mut flatbuffers::FlatBufferBuilder<'b>";
+ code_ += " ) -> flatbuffers::WIPOffset<{{STRUCT_NAME}}<'b>> {";
+ // First we generate variables for each field and then later assemble them
+ // using "StructArgs" to more easily manage ownership of the builder.
+ ForAllObjectTableFields(table, [&](const FieldDef &field) {
+ const Type &type = field.value.type;
+ switch (GetFullType(type)) {
+ case ftInteger:
+ case ftBool:
+ case ftFloat:
+ case ftEnumKey: {
+ code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}};";
+ return;
+ }
+ case ftUnionKey: return; // Generate union type with union value.
+ case ftUnionValue: {
+ code_.SetValue("SNAKE_CASE_ENUM_NAME",
+ MakeSnakeCase(Name(*field.value.type.enum_def)));
+ code_ +=
+ " let {{FIELD_NAME}}_type = "
+ "self.{{FIELD_NAME}}.{{SNAKE_CASE_ENUM_NAME}}_type();";
+ code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}.pack(_fbb);";
+ return;
+ }
+ // The rest of the types require special casing around optionalness
+ // due to "required" annotation.
+ case ftString: {
+ MapNativeTableField(field, "_fbb.create_string(x)");
+ return;
+ }
+ case ftStruct: {
+ // Hold the struct in a variable so we can reference it.
+ if (field.IsRequired()) {
+ code_ +=
+ " let {{FIELD_NAME}}_tmp = "
+ "Some(self.{{FIELD_NAME}}.pack());";
+ } else {
+ code_ +=
+ " let {{FIELD_NAME}}_tmp = self.{{FIELD_NAME}}"
+ ".as_ref().map(|x| x.pack());";
+ }
+ code_ += " let {{FIELD_NAME}} = {{FIELD_NAME}}_tmp.as_ref();";
+
+ return;
+ }
+ case ftTable: {
+ MapNativeTableField(field, "x.pack(_fbb)");
+ return;
+ }
+ case ftVectorOfEnumKey:
+ case ftVectorOfInteger:
+ case ftVectorOfBool:
+ case ftVectorOfFloat: {
+ MapNativeTableField(field, "_fbb.create_vector(x)");
+ return;
+ }
+ case ftVectorOfStruct: {
+ MapNativeTableField(
+ field,
+ "let w: Vec<_> = x.iter().map(|t| t.pack()).collect();"
+ "_fbb.create_vector(&w)");
+ return;
+ }
+ case ftVectorOfString: {
+ // TODO(cneo): create_vector* should be more generic to avoid
+ // allocations.
+
+ MapNativeTableField(
+ field,
+ "let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();"
+ "_fbb.create_vector_of_strings(&w)");
+ return;
+ }
+ case ftVectorOfTable: {
+ MapNativeTableField(
+ field,
+ "let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();"
+ "_fbb.create_vector(&w)");
+ return;
+ }
+ case ftVectorOfUnionValue: {
+ FLATBUFFERS_ASSERT(false && "vectors of unions not yet supported");
+ return;
+ }
+ case ftArrayOfEnum:
+ case ftArrayOfStruct:
+ case ftArrayOfBuiltin: {
+ FLATBUFFERS_ASSERT(false && "arrays are not supported within tables");
+ return;
+ }
+ }
+ });
+ code_ += " {{STRUCT_NAME}}::create(_fbb, &{{STRUCT_NAME}}Args{";
+ ForAllObjectTableFields(table, [&](const FieldDef &field) {
+ (void)field; // Unused.
+ code_ += " {{FIELD_NAME}},";
+ });
+ code_ += " })";
+ code_ += " }";
+ code_ += "}";
+ }
+ void ForAllObjectTableFields(const StructDef &table,
+ std::function<void(const FieldDef &)> cb) {
+ const std::vector<FieldDef *> &v = table.fields.vec;
+ for (auto it = v.begin(); it != v.end(); it++) {
+ const FieldDef &field = **it;
+ if (field.deprecated) continue;
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("FIELD_OBJECT_TYPE", ObjectFieldType(field, true));
+ cb(field);
+ }
+ }
+ void MapNativeTableField(const FieldDef &field, const std::string &expr) {
+ if (field.IsOptional()) {
+ code_ += " let {{FIELD_NAME}} = self.{{FIELD_NAME}}.as_ref().map(|x|{";
+ code_ += " " + expr;
+ code_ += " });";
+ } else {
+ // For some reason Args has optional types for required fields.
+ // TODO(cneo): Fix this... but its a breaking change?
+ code_ += " let {{FIELD_NAME}} = Some({";
+ code_ += " let x = &self.{{FIELD_NAME}};";
+ code_ += " " + expr;
+ code_ += " });";
+ }
+ }
+
+ // Generate functions to compare tables and structs by key. This function
+ // must only be called if the field key is defined.
+ void GenKeyFieldMethods(const FieldDef &field) {
+ FLATBUFFERS_ASSERT(field.key);
+
+ code_.SetValue("KEY_TYPE", GenTableAccessorFuncReturnType(field, ""));
+
+ code_ += " #[inline]";
+ code_ +=
+ " pub fn key_compare_less_than(&self, o: &{{STRUCT_NAME}}) -> "
+ " bool {";
+ code_ += " self.{{FIELD_NAME}}() < o.{{FIELD_NAME}}()";
+ code_ += " }";
+ code_ += "";
+ code_ += " #[inline]";
+ code_ +=
+ " pub fn key_compare_with_value(&self, val: {{KEY_TYPE}}) -> "
+ " ::std::cmp::Ordering {";
+ code_ += " let key = self.{{FIELD_NAME}}();";
+ code_ += " key.cmp(&val)";
+ code_ += " }";
+ }
+
+ // Generate functions for accessing the root table object. This function
+ // must only be called if the root table is defined.
+ void GenRootTableFuncs(const StructDef &struct_def) {
+ FLATBUFFERS_ASSERT(parser_.root_struct_def_ && "root table not defined");
+ auto name = Name(struct_def);
+
+ code_.SetValue("STRUCT_NAME", name);
+ code_.SetValue("STRUCT_NAME_SNAKECASE", MakeSnakeCase(name));
+ code_.SetValue("STRUCT_NAME_CAPS", MakeUpper(MakeSnakeCase(name)));
+
+ // The root datatype accessors:
+ code_ += "#[inline]";
+ code_ +=
+ "#[deprecated(since=\"2.0.0\", "
+ "note=\"Deprecated in favor of `root_as...` methods.\")]";
+ code_ +=
+ "pub fn get_root_as_{{STRUCT_NAME_SNAKECASE}}<'a>(buf: &'a [u8])"
+ " -> {{STRUCT_NAME}}<'a> {";
+ code_ +=
+ " unsafe { flatbuffers::root_unchecked::<{{STRUCT_NAME}}"
+ "<'a>>(buf) }";
+ code_ += "}";
+ code_ += "";
+
+ code_ += "#[inline]";
+ code_ +=
+ "#[deprecated(since=\"2.0.0\", "
+ "note=\"Deprecated in favor of `root_as...` methods.\")]";
+ code_ +=
+ "pub fn get_size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
+ "<'a>(buf: &'a [u8]) -> {{STRUCT_NAME}}<'a> {";
+ code_ +=
+ " unsafe { flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_NAME}}"
+ "<'a>>(buf) }";
+ code_ += "}";
+ code_ += "";
+ // Default verifier root fns.
+ code_ += "#[inline]";
+ code_ += "/// Verifies that a buffer of bytes contains a `{{STRUCT_NAME}}`";
+ code_ += "/// and returns it.";
+ code_ += "/// Note that verification is still experimental and may not";
+ code_ += "/// catch every error, or be maximally performant. For the";
+ code_ += "/// previous, unchecked, behavior use";
+ code_ += "/// `root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
+ code_ +=
+ "pub fn root_as_{{STRUCT_NAME_SNAKECASE}}(buf: &[u8]) "
+ "-> Result<{{STRUCT_NAME}}, flatbuffers::InvalidFlatbuffer> {";
+ code_ += " flatbuffers::root::<{{STRUCT_NAME}}>(buf)";
+ code_ += "}";
+ code_ += "#[inline]";
+ code_ += "/// Verifies that a buffer of bytes contains a size prefixed";
+ code_ += "/// `{{STRUCT_NAME}}` and returns it.";
+ code_ += "/// Note that verification is still experimental and may not";
+ code_ += "/// catch every error, or be maximally performant. For the";
+ code_ += "/// previous, unchecked, behavior use";
+ code_ += "/// `size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
+ code_ +=
+ "pub fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
+ "(buf: &[u8]) -> Result<{{STRUCT_NAME}}, "
+ "flatbuffers::InvalidFlatbuffer> {";
+ code_ += " flatbuffers::size_prefixed_root::<{{STRUCT_NAME}}>(buf)";
+ code_ += "}";
+ // Verifier with options root fns.
+ code_ += "#[inline]";
+ code_ += "/// Verifies, with the given options, that a buffer of bytes";
+ code_ += "/// contains a `{{STRUCT_NAME}}` and returns it.";
+ code_ += "/// Note that verification is still experimental and may not";
+ code_ += "/// catch every error, or be maximally performant. For the";
+ code_ += "/// previous, unchecked, behavior use";
+ code_ += "/// `root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
+ code_ += "pub fn root_as_{{STRUCT_NAME_SNAKECASE}}_with_opts<'b, 'o>(";
+ code_ += " opts: &'o flatbuffers::VerifierOptions,";
+ code_ += " buf: &'b [u8],";
+ code_ +=
+ ") -> Result<{{STRUCT_NAME}}<'b>, flatbuffers::InvalidFlatbuffer>"
+ " {";
+ code_ += " flatbuffers::root_with_opts::<{{STRUCT_NAME}}<'b>>(opts, buf)";
+ code_ += "}";
+ code_ += "#[inline]";
+ code_ += "/// Verifies, with the given verifier options, that a buffer of";
+ code_ += "/// bytes contains a size prefixed `{{STRUCT_NAME}}` and returns";
+ code_ += "/// it. Note that verification is still experimental and may not";
+ code_ += "/// catch every error, or be maximally performant. For the";
+ code_ += "/// previous, unchecked, behavior use";
+ code_ += "/// `root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
+ code_ +=
+ "pub fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}_with_opts"
+ "<'b, 'o>(";
+ code_ += " opts: &'o flatbuffers::VerifierOptions,";
+ code_ += " buf: &'b [u8],";
+ code_ +=
+ ") -> Result<{{STRUCT_NAME}}<'b>, flatbuffers::InvalidFlatbuffer>"
+ " {";
+ code_ +=
+ " flatbuffers::size_prefixed_root_with_opts::<{{STRUCT_NAME}}"
+ "<'b>>(opts, buf)";
+ code_ += "}";
+ // Unchecked root fns.
+ code_ += "#[inline]";
+ code_ +=
+ "/// Assumes, without verification, that a buffer of bytes "
+ "contains a {{STRUCT_NAME}} and returns it.";
+ code_ += "/// # Safety";
+ code_ +=
+ "/// Callers must trust the given bytes do indeed contain a valid"
+ " `{{STRUCT_NAME}}`.";
+ code_ +=
+ "pub unsafe fn root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked"
+ "(buf: &[u8]) -> {{STRUCT_NAME}} {";
+ code_ += " flatbuffers::root_unchecked::<{{STRUCT_NAME}}>(buf)";
+ code_ += "}";
+ code_ += "#[inline]";
+ code_ +=
+ "/// Assumes, without verification, that a buffer of bytes "
+ "contains a size prefixed {{STRUCT_NAME}} and returns it.";
+ code_ += "/// # Safety";
+ code_ +=
+ "/// Callers must trust the given bytes do indeed contain a valid"
+ " size prefixed `{{STRUCT_NAME}}`.";
+ code_ +=
+ "pub unsafe fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
+ "_unchecked(buf: &[u8]) -> {{STRUCT_NAME}} {";
+ code_ +=
+ " flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_NAME}}>"
+ "(buf)";
+ code_ += "}";
+
+ if (parser_.file_identifier_.length()) {
+ // Declare the identifier
+ // (no lifetime needed as constants have static lifetimes by default)
+ code_ += "pub const {{STRUCT_NAME_CAPS}}_IDENTIFIER: &str\\";
+ code_ += " = \"" + parser_.file_identifier_ + "\";";
+ code_ += "";
+
+ // Check if a buffer has the identifier.
+ code_ += "#[inline]";
+ code_ += "pub fn {{STRUCT_NAME_SNAKECASE}}_buffer_has_identifier\\";
+ code_ += "(buf: &[u8]) -> bool {";
+ code_ += " flatbuffers::buffer_has_identifier(buf, \\";
+ code_ += "{{STRUCT_NAME_CAPS}}_IDENTIFIER, false)";
+ code_ += "}";
+ code_ += "";
+ code_ += "#[inline]";
+ code_ += "pub fn {{STRUCT_NAME_SNAKECASE}}_size_prefixed\\";
+ code_ += "_buffer_has_identifier(buf: &[u8]) -> bool {";
+ code_ += " flatbuffers::buffer_has_identifier(buf, \\";
+ code_ += "{{STRUCT_NAME_CAPS}}_IDENTIFIER, true)";
+ code_ += "}";
+ code_ += "";
+ }
+
+ if (parser_.file_extension_.length()) {
+ // Return the extension
+ code_ += "pub const {{STRUCT_NAME_CAPS}}_EXTENSION: &str = \\";
+ code_ += "\"" + parser_.file_extension_ + "\";";
+ code_ += "";
+ }
+
+ // Finish a buffer with a given root object:
+ code_.SetValue("OFFSET_TYPELABEL", Name(struct_def) + "Offset");
+ code_ += "#[inline]";
+ code_ += "pub fn finish_{{STRUCT_NAME_SNAKECASE}}_buffer<'a, 'b>(";
+ code_ += " fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,";
+ code_ += " root: flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>>) {";
+ if (parser_.file_identifier_.length()) {
+ code_ += " fbb.finish(root, Some({{STRUCT_NAME_CAPS}}_IDENTIFIER));";
+ } else {
+ code_ += " fbb.finish(root, None);";
+ }
+ code_ += "}";
+ code_ += "";
+ code_ += "#[inline]";
+ code_ +=
+ "pub fn finish_size_prefixed_{{STRUCT_NAME_SNAKECASE}}_buffer"
+ "<'a, 'b>("
+ "fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, "
+ "root: flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>>) {";
+ if (parser_.file_identifier_.length()) {
+ code_ +=
+ " fbb.finish_size_prefixed(root, "
+ "Some({{STRUCT_NAME_CAPS}}_IDENTIFIER));";
+ } else {
+ code_ += " fbb.finish_size_prefixed(root, None);";
+ }
+ code_ += "}";
+ }
+
+ static void GenPadding(
+ const FieldDef &field, std::string *code_ptr, int *id,
+ const std::function<void(int bits, std::string *code_ptr, int *id)> &f) {
+ if (field.padding) {
+ for (int i = 0; i < 4; i++) {
+ if (static_cast<int>(field.padding) & (1 << i)) {
+ f((1 << i) * 8, code_ptr, id);
+ }
+ }
+ assert(!(field.padding & ~0xF));
+ }
+ }
+
+ static void PaddingDefinition(int bits, std::string *code_ptr, int *id) {
+ *code_ptr +=
+ " padding" + NumToString((*id)++) + "__: u" + NumToString(bits) + ",";
+ }
+
+ static void PaddingInitializer(int bits, std::string *code_ptr, int *id) {
+ (void)bits;
+ *code_ptr += "padding" + NumToString((*id)++) + "__: 0,";
+ }
+
+ void ForAllStructFields(const StructDef &struct_def,
+ std::function<void(const FieldDef &field)> cb) {
+ size_t offset_to_field = 0;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ code_.SetValue("FIELD_TYPE", GetTypeGet(field.value.type));
+ code_.SetValue("FIELD_OBJECT_TYPE", ObjectFieldType(field, false));
+ code_.SetValue("FIELD_NAME", Name(field));
+ code_.SetValue("FIELD_OFFSET", NumToString(offset_to_field));
+ code_.SetValue(
+ "REF",
+ IsStruct(field.value.type) || IsArray(field.value.type) ? "&" : "");
+ cb(field);
+ const size_t size = InlineSize(field.value.type);
+ offset_to_field += size + field.padding;
+ }
+ }
+ // Generate an accessor struct with constructor for a flatbuffers struct.
+ void GenStruct(const StructDef &struct_def) {
+ // Generates manual padding and alignment.
+ // Variables are private because they contain little endian data on all
+ // platforms.
+ GenComment(struct_def.doc_comment);
+ code_.SetValue("ALIGN", NumToString(struct_def.minalign));
+ code_.SetValue("STRUCT_NAME", Name(struct_def));
+ code_.SetValue("STRUCT_SIZE", NumToString(struct_def.bytesize));
+
+ // We represent Flatbuffers-structs in Rust-u8-arrays since the data may be
+ // of the wrong endianness and alignment 1.
+ //
+ // PartialEq is useful to derive because we can correctly compare structs
+ // for equality by just comparing their underlying byte data. This doesn't
+ // hold for PartialOrd/Ord.
+ code_ += "// struct {{STRUCT_NAME}}, aligned to {{ALIGN}}";
+ code_ += "#[repr(transparent)]";
+ code_ += "#[derive(Clone, Copy, PartialEq)]";
+ code_ += "pub struct {{STRUCT_NAME}}(pub [u8; {{STRUCT_SIZE}}]);";
+ code_ += "impl Default for {{STRUCT_NAME}} { ";
+ code_ += " fn default() -> Self { ";
+ code_ += " Self([0; {{STRUCT_SIZE}}])";
+ code_ += " }";
+ code_ += "}";
+
+ // Debug for structs.
+ code_ += "impl std::fmt::Debug for {{STRUCT_NAME}} {";
+ code_ +=
+ " fn fmt(&self, f: &mut std::fmt::Formatter"
+ ") -> std::fmt::Result {";
+ code_ += " f.debug_struct(\"{{STRUCT_NAME}}\")";
+ ForAllStructFields(struct_def, [&](const FieldDef &unused) {
+ (void)unused;
+ code_ += " .field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}())";
+ });
+ code_ += " .finish()";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+
+ // Generate impls for SafeSliceAccess (because all structs are endian-safe),
+ // Follow for the value type, Follow for the reference type, Push for the
+ // value type, and Push for the reference type.
+ code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{STRUCT_NAME}} {}";
+ code_ += "impl flatbuffers::SafeSliceAccess for {{STRUCT_NAME}} {}";
+ code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_NAME}} {";
+ code_ += " type Inner = &'a {{STRUCT_NAME}};";
+ code_ += " #[inline]";
+ code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " <&'a {{STRUCT_NAME}}>::follow(buf, loc)";
+ code_ += " }";
+ code_ += "}";
+ code_ += "impl<'a> flatbuffers::Follow<'a> for &'a {{STRUCT_NAME}} {";
+ code_ += " type Inner = &'a {{STRUCT_NAME}};";
+ code_ += " #[inline]";
+ code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
+ code_ += " flatbuffers::follow_cast_ref::<{{STRUCT_NAME}}>(buf, loc)";
+ code_ += " }";
+ code_ += "}";
+ code_ += "impl<'b> flatbuffers::Push for {{STRUCT_NAME}} {";
+ code_ += " type Output = {{STRUCT_NAME}};";
+ code_ += " #[inline]";
+ code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
+ code_ += " let src = unsafe {";
+ code_ +=
+ " ::std::slice::from_raw_parts("
+ "self as *const {{STRUCT_NAME}} as *const u8, Self::size())";
+ code_ += " };";
+ code_ += " dst.copy_from_slice(src);";
+ code_ += " }";
+ code_ += "}";
+ code_ += "impl<'b> flatbuffers::Push for &'b {{STRUCT_NAME}} {";
+ code_ += " type Output = {{STRUCT_NAME}};";
+ code_ += "";
+ code_ += " #[inline]";
+ code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
+ code_ += " let src = unsafe {";
+ code_ +=
+ " ::std::slice::from_raw_parts("
+ "*self as *const {{STRUCT_NAME}} as *const u8, Self::size())";
+ code_ += " };";
+ code_ += " dst.copy_from_slice(src);";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+
+ // Generate verifier: Structs are simple so presence and alignment are
+ // all that need to be checked.
+ code_ += "impl<'a> flatbuffers::Verifiable for {{STRUCT_NAME}} {";
+ code_ += " #[inline]";
+ code_ += " fn run_verifier(";
+ code_ += " v: &mut flatbuffers::Verifier, pos: usize";
+ code_ += " ) -> Result<(), flatbuffers::InvalidFlatbuffer> {";
+ code_ += " use self::flatbuffers::Verifiable;";
+ code_ += " v.in_buffer::<Self>(pos)";
+ code_ += " }";
+ code_ += "}";
+
+ // Generate a constructor that takes all fields as arguments.
+ code_ += "impl<'a> {{STRUCT_NAME}} {";
+ code_ += " #[allow(clippy::too_many_arguments)]";
+ code_ += " pub fn new(";
+ ForAllStructFields(struct_def, [&](const FieldDef &unused) {
+ (void)unused;
+ code_ += " {{FIELD_NAME}}: {{REF}}{{FIELD_TYPE}},";
+ });
+ code_ += " ) -> Self {";
+ code_ += " let mut s = Self([0; {{STRUCT_SIZE}}]);";
+ ForAllStructFields(struct_def, [&](const FieldDef &unused) {
+ (void)unused;
+ code_ += " s.set_{{FIELD_NAME}}({{REF}}{{FIELD_NAME}});";
+ });
+ code_ += " s";
+ code_ += " }";
+ code_ += "";
+
+ if (parser_.opts.generate_name_strings) {
+ GenFullyQualifiedNameGetter(struct_def, struct_def.name);
+ }
+
+ // Generate accessor methods for the struct.
+ ForAllStructFields(struct_def, [&](const FieldDef &field) {
+ this->GenComment(field.doc_comment, " ");
+ // Getter.
+ if (IsStruct(field.value.type)) {
+ code_ += " pub fn {{FIELD_NAME}}(&self) -> &{{FIELD_TYPE}} {";
+ code_ +=
+ " unsafe {"
+ " &*(self.0[{{FIELD_OFFSET}}..].as_ptr() as *const"
+ " {{FIELD_TYPE}}) }";
+ } else if (IsArray(field.value.type)) {
+ code_.SetValue("ARRAY_SIZE",
+ NumToString(field.value.type.fixed_length));
+ code_.SetValue("ARRAY_ITEM", GetTypeGet(field.value.type.VectorType()));
+ code_ +=
+ " pub fn {{FIELD_NAME}}(&'a self) -> "
+ "flatbuffers::Array<'a, {{ARRAY_ITEM}}, {{ARRAY_SIZE}}> {";
+ code_ += " flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}})";
+ } else {
+ code_ += " pub fn {{FIELD_NAME}}(&self) -> {{FIELD_TYPE}} {";
+ code_ +=
+ " let mut mem = core::mem::MaybeUninit::"
+ "<{{FIELD_TYPE}}>::uninit();";
+ code_ += " unsafe {";
+ code_ += " core::ptr::copy_nonoverlapping(";
+ code_ += " self.0[{{FIELD_OFFSET}}..].as_ptr(),";
+ code_ += " mem.as_mut_ptr() as *mut u8,";
+ code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),";
+ code_ += " );";
+ code_ += " mem.assume_init()";
+ code_ += " }.from_little_endian()";
+ }
+ code_ += " }\n";
+ // Setter.
+ if (IsStruct(field.value.type)) {
+ code_.SetValue("FIELD_SIZE", NumToString(InlineSize(field.value.type)));
+ code_ += " pub fn set_{{FIELD_NAME}}(&mut self, x: &{{FIELD_TYPE}}) {";
+ code_ +=
+ " self.0[{{FIELD_OFFSET}}..{{FIELD_OFFSET}}+{{FIELD_SIZE}}]"
+ ".copy_from_slice(&x.0)";
+ } else if (IsArray(field.value.type)) {
+ if (GetFullType(field.value.type) == ftArrayOfBuiltin) {
+ code_.SetValue("ARRAY_ITEM",
+ GetTypeGet(field.value.type.VectorType()));
+ code_.SetValue(
+ "ARRAY_ITEM_SIZE",
+ NumToString(InlineSize(field.value.type.VectorType())));
+ code_ +=
+ " pub fn set_{{FIELD_NAME}}(&mut self, items: &{{FIELD_TYPE}}) "
+ "{";
+ code_ +=
+ " flatbuffers::emplace_scalar_array(&mut self.0, "
+ "{{FIELD_OFFSET}}, items);";
+ } else {
+ code_.SetValue("FIELD_SIZE",
+ NumToString(InlineSize(field.value.type)));
+ code_ +=
+ " pub fn set_{{FIELD_NAME}}(&mut self, x: &{{FIELD_TYPE}}) {";
+ code_ += " unsafe {";
+ code_ += " std::ptr::copy(";
+ code_ += " x.as_ptr() as *const u8,";
+ code_ += " self.0.as_mut_ptr().add({{FIELD_OFFSET}}),";
+ code_ += " {{FIELD_SIZE}},";
+ code_ += " );";
+ code_ += " }";
+ }
+ } else {
+ code_ += " pub fn set_{{FIELD_NAME}}(&mut self, x: {{FIELD_TYPE}}) {";
+ code_ += " let x_le = x.to_little_endian();";
+ code_ += " unsafe {";
+ code_ += " core::ptr::copy_nonoverlapping(";
+ code_ += " &x_le as *const {{FIELD_TYPE}} as *const u8,";
+ code_ += " self.0[{{FIELD_OFFSET}}..].as_mut_ptr(),";
+ code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),";
+ code_ += " );";
+ code_ += " }";
+ }
+ code_ += " }\n";
+
+ // Generate a comparison function for this field if it is a key.
+ if (field.key) { GenKeyFieldMethods(field); }
+ });
+
+ // Generate Object API unpack method.
+ if (parser_.opts.generate_object_based_api) {
+ code_.SetValue("NATIVE_STRUCT_NAME", NativeName(struct_def));
+ code_ += " pub fn unpack(&self) -> {{NATIVE_STRUCT_NAME}} {";
+ code_ += " {{NATIVE_STRUCT_NAME}} {";
+ ForAllStructFields(struct_def, [&](const FieldDef &field) {
+ if (IsArray(field.value.type)) {
+ if (GetFullType(field.value.type) == ftArrayOfStruct) {
+ code_ +=
+ " {{FIELD_NAME}}: { let {{FIELD_NAME}} = "
+ "self.{{FIELD_NAME}}(); flatbuffers::array_init(|i| "
+ "{{FIELD_NAME}}.get(i).unpack()) },";
+ } else {
+ code_ += " {{FIELD_NAME}}: self.{{FIELD_NAME}}().into(),";
+ }
+ } else {
+ std::string unpack = IsStruct(field.value.type) ? ".unpack()" : "";
+ code_ += " {{FIELD_NAME}}: self.{{FIELD_NAME}}()" + unpack + ",";
+ }
+ });
+ code_ += " }";
+ code_ += " }";
+ }
+
+ code_ += "}"; // End impl Struct methods.
+ code_ += "";
+
+ // Generate Struct Object.
+ if (parser_.opts.generate_object_based_api) {
+ // Struct declaration
+ code_ += "#[derive(Debug, Clone, PartialEq, Default)]";
+ code_ += "pub struct {{NATIVE_STRUCT_NAME}} {";
+ ForAllStructFields(struct_def, [&](const FieldDef &field) {
+ (void)field; // unused.
+ code_ += " pub {{FIELD_NAME}}: {{FIELD_OBJECT_TYPE}},";
+ });
+ code_ += "}";
+ // The `pack` method that turns the native struct into its Flatbuffers
+ // counterpart.
+ code_ += "impl {{NATIVE_STRUCT_NAME}} {";
+ code_ += " pub fn pack(&self) -> {{STRUCT_NAME}} {";
+ code_ += " {{STRUCT_NAME}}::new(";
+ ForAllStructFields(struct_def, [&](const FieldDef &field) {
+ if (IsStruct(field.value.type)) {
+ code_ += " &self.{{FIELD_NAME}}.pack(),";
+ } else if (IsArray(field.value.type)) {
+ if (GetFullType(field.value.type) == ftArrayOfStruct) {
+ code_ +=
+ " &flatbuffers::array_init(|i| "
+ "self.{{FIELD_NAME}}[i].pack()),";
+ } else {
+ code_ += " &self.{{FIELD_NAME}},";
+ }
+ } else {
+ code_ += " self.{{FIELD_NAME}},";
+ }
+ });
+ code_ += " )";
+ code_ += " }";
+ code_ += "}";
+ code_ += "";
+ }
+ }
+
+ void GenNamespaceImports(const int white_spaces) {
+ // DO not use global attributes (i.e. #![...]) since it interferes
+ // with users who include! generated files.
+ // See: https://github.com/google/flatbuffers/issues/6261
+ std::string indent = std::string(white_spaces, ' ');
+ code_ += "";
+ if (!parser_.opts.generate_all) {
+ for (auto it = parser_.included_files_.begin();
+ it != parser_.included_files_.end(); ++it) {
+ if (it->second.empty()) continue;
+ auto noext = flatbuffers::StripExtension(it->second);
+ auto basename = flatbuffers::StripPath(noext);
+
+ if (parser_.opts.include_prefix.empty()) {
+ code_ += indent + "use crate::" + basename +
+ parser_.opts.filename_suffix + "::*;";
+ } else {
+ auto prefix = parser_.opts.include_prefix;
+ prefix.pop_back();
+
+ code_ += indent + "use crate::" + prefix + "::" + basename +
+ parser_.opts.filename_suffix + "::*;";
+ }
+ }
+ }
+ code_ += indent + "use std::mem;";
+ code_ += indent + "use std::cmp::Ordering;";
+ code_ += "";
+ code_ += indent + "extern crate flatbuffers;";
+ code_ += indent + "use self::flatbuffers::{EndianScalar, Follow};";
+ }
+
+ // Set up the correct namespace. This opens a namespace if the current
+ // namespace is different from the target namespace. This function
+ // closes and opens the namespaces only as necessary.
+ //
+ // The file must start and end with an empty (or null) namespace so that
+ // namespaces are properly opened and closed.
+ void SetNameSpace(const Namespace *ns) {
+ if (cur_name_space_ == ns) { return; }
+
+ // Compute the size of the longest common namespace prefix.
+ // If cur_name_space is A::B::C::D and ns is A::B::E::F::G,
+ // the common prefix is A::B:: and we have old_size = 4, new_size = 5
+ // and common_prefix_size = 2
+ size_t old_size = cur_name_space_ ? cur_name_space_->components.size() : 0;
+ size_t new_size = ns ? ns->components.size() : 0;
+
+ size_t common_prefix_size = 0;
+ while (common_prefix_size < old_size && common_prefix_size < new_size &&
+ ns->components[common_prefix_size] ==
+ cur_name_space_->components[common_prefix_size]) {
+ common_prefix_size++;
+ }
+
+ // Close cur_name_space in reverse order to reach the common prefix.
+ // In the previous example, D then C are closed.
+ for (size_t j = old_size; j > common_prefix_size; --j) {
+ code_ += "} // pub mod " + cur_name_space_->components[j - 1];
+ }
+ if (old_size != common_prefix_size) { code_ += ""; }
+
+ // open namespace parts to reach the ns namespace
+ // in the previous example, E, then F, then G are opened
+ for (auto j = common_prefix_size; j != new_size; ++j) {
+ code_ += "#[allow(unused_imports, dead_code)]";
+ code_ += "pub mod " + MakeSnakeCase(ns->components[j]) + " {";
+ // Generate local namespace imports.
+ GenNamespaceImports(2);
+ }
+ if (new_size != common_prefix_size) { code_ += ""; }
+
+ cur_name_space_ = ns;
+ }
+};
+
+} // namespace rust
+
+bool GenerateRust(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ rust::RustGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+
+std::string RustMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ std::string filebase =
+ flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
+ rust::RustGenerator generator(parser, path, file_name);
+ std::string make_rule =
+ generator.GeneratedFileName(path, filebase, parser.opts) + ": ";
+
+ auto included_files = parser.GetIncludedFilesRecursive(file_name);
+ for (auto it = included_files.begin(); it != included_files.end(); ++it) {
+ make_rule += " " + *it;
+ }
+ return make_rule;
+}
+
+} // namespace flatbuffers
+
+// TODO(rw): Generated code should import other generated files.
+// TODO(rw): Generated code should refer to namespaces in included files in a
+// way that makes them referrable.
+// TODO(rw): Generated code should indent according to nesting level.
+// TODO(rw): Generated code should generate endian-safe Debug impls.
+// TODO(rw): Generated code could use a Rust-only enum type to access unions,
+// instead of making the user use _type() to manually switch.
+// TODO(maxburke): There should be test schemas added that use language
+// keywords as fields of structs, tables, unions, enums, to make sure
+// that internal code generated references escaped names correctly.
+// TODO(maxburke): We should see if there is a more flexible way of resolving
+// module paths for use declarations. Right now if schemas refer to
+// other flatbuffer files, the include paths in emitted Rust bindings
+// are crate-relative which may undesirable.
diff --git a/contrib/libs/flatbuffers/src/idl_gen_swift.cpp b/contrib/libs/flatbuffers/src/idl_gen_swift.cpp
new file mode 100644
index 0000000000..3fffd39455
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_swift.cpp
@@ -0,0 +1,1575 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#include <cctype>
+#include <unordered_set>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+namespace swift {
+
+inline std::string GenIndirect(const std::string &reading) {
+ return "{{ACCESS}}.indirect(" + reading + ")";
+}
+
+inline std::string GenArrayMainBody(const std::string &optional) {
+ return "{{ACCESS_TYPE}} func {{VALUENAME}}(at index: Int32) -> "
+ "{{VALUETYPE}}" +
+ optional + " { ";
+}
+
+class SwiftGenerator : public BaseGenerator {
+ private:
+ CodeWriter code_;
+ std::unordered_set<std::string> keywords_;
+ int namespace_depth;
+
+ public:
+ SwiftGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", "_", "swift") {
+ namespace_depth = 0;
+ code_.SetPadding(" ");
+ static const char *const keywords[] = {
+ "associatedtype",
+ "class",
+ "deinit",
+ "enum",
+ "extension",
+ "fileprivate",
+ "func",
+ "import",
+ "init",
+ "inout",
+ "internal",
+ "let",
+ "open",
+ "operator",
+ "private",
+ "protocol",
+ "public",
+ "rethrows",
+ "static",
+ "struct",
+ "subscript",
+ "typealias",
+ "var",
+ "break",
+ "case",
+ "continue",
+ "default",
+ "defer",
+ "do",
+ "else",
+ "fallthrough",
+ "for",
+ "guard",
+ "if",
+ "in",
+ "repeat",
+ "return",
+ "switch",
+ "where",
+ "while",
+ "Any",
+ "catch",
+ "false",
+ "is",
+ "nil",
+ "super",
+ "self",
+ "Self",
+ "throw",
+ "throws",
+ "true",
+ "try",
+ "associativity",
+ "convenience",
+ "dynamic",
+ "didSet",
+ "final",
+ "get",
+ "infix",
+ "indirect",
+ "lazy",
+ "left",
+ "mutating",
+ "none",
+ "nonmutating",
+ "optional",
+ "override",
+ "postfix",
+ "precedence",
+ "prefix",
+ "Protocol",
+ "required",
+ "right",
+ "set",
+ "Type",
+ "unowned",
+ "weak",
+ "willSet",
+ "Void",
+ nullptr,
+ };
+ for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
+ }
+
+ bool generate() {
+ code_.Clear();
+ code_.SetValue("ACCESS", "_accessor");
+ code_.SetValue("TABLEOFFSET", "VTOFFSET");
+ code_ += "// " + std::string(FlatBuffersGeneratedWarning());
+ code_ += "// swiftlint:disable all";
+ code_ += "// swiftformat:disable all\n";
+ code_ += "import FlatBuffers\n";
+ // Generate code for all the enum declarations.
+
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ const auto &enum_def = **it;
+ if (!enum_def.generated) { GenEnum(enum_def); }
+ }
+
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (struct_def.fixed && !struct_def.generated) {
+ GenStructReader(struct_def);
+ GenMutableStructReader(struct_def);
+ }
+ }
+
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ const auto &struct_def = **it;
+ if (!struct_def.fixed && !struct_def.generated) {
+ GenTable(struct_def);
+ if (parser_.opts.generate_object_based_api) {
+ GenObjectAPI(struct_def);
+ }
+ }
+ }
+
+ const auto filename = GeneratedFileName(path_, file_name_, parser_.opts);
+ const auto final_code = code_.ToString();
+ return SaveFile(filename.c_str(), final_code, false);
+ }
+
+ void mark(const std::string &str) {
+ code_.SetValue("MARKVALUE", str);
+ code_ += "\n// MARK: - {{MARKVALUE}}\n";
+ }
+
+ // MARK: - Generating structs
+
+ // Generates the reader for swift
+ void GenStructReader(const StructDef &struct_def) {
+ auto is_private_access = struct_def.attributes.Lookup("private");
+ code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
+ GenComment(struct_def.doc_comment);
+ code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
+ code_ += "{{ACCESS_TYPE}} struct {{STRUCTNAME}}: NativeStruct\\";
+ if (parser_.opts.generate_object_based_api) code_ += ", NativeObject\\";
+ code_ += " {";
+ code_ += "";
+ Indent();
+ code_ += ValidateFunc();
+ code_ += "";
+ int padding_id = 0;
+ std::string constructor = "";
+ std::vector<std::string> base_constructor;
+ std::vector<std::string> main_constructor;
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ if (!constructor.empty()) constructor += ", ";
+
+ auto name = Name(field);
+ auto type = GenType(field.value.type);
+ code_.SetValue("VALUENAME", name);
+ if (IsEnum(field.value.type)) {
+ code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
+ }
+ code_.SetValue("VALUETYPE", type);
+ GenComment(field.doc_comment);
+ std::string valueType =
+ IsEnum(field.value.type) ? "{{BASEVALUE}}" : "{{VALUETYPE}}";
+ code_ += "private var _{{VALUENAME}}: " + valueType;
+ auto accessing_value = IsEnum(field.value.type) ? ".value" : "";
+ auto base_value =
+ IsStruct(field.value.type) ? (type + "()") : field.value.constant;
+
+ main_constructor.push_back("_" + name + " = " + name + accessing_value);
+ base_constructor.push_back("_" + name + " = " + base_value);
+
+ if (field.padding) { GenPadding(field, &padding_id); }
+ constructor += name + ": " + type;
+ }
+ code_ += "";
+ BuildObjectConstructor(main_constructor, constructor);
+ BuildObjectConstructor(base_constructor, "");
+
+ if (parser_.opts.generate_object_based_api)
+ GenerateObjectAPIStructConstructor(struct_def);
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto name = Name(field);
+ auto type = GenType(field.value.type);
+ code_.SetValue("VALUENAME", name);
+ code_.SetValue("VALUETYPE", type);
+ GenComment(field.doc_comment);
+ if (!IsEnum(field.value.type)) {
+ code_ += GenReaderMainBody() + "_{{VALUENAME}} }";
+ } else if (IsEnum(field.value.type)) {
+ code_ +=
+ GenReaderMainBody() + "{{VALUETYPE}}(rawValue: _{{VALUENAME}})! }";
+ }
+ }
+ Outdent();
+ code_ += "}\n";
+ }
+
+ void GenMutableStructReader(const StructDef &struct_def) {
+ GenObjectHeader(struct_def);
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto offset = NumToString(field.value.offset);
+ auto name = Name(field);
+ auto type = GenType(field.value.type);
+ code_.SetValue("VALUENAME", name);
+ if (IsEnum(field.value.type)) {
+ code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
+ }
+ code_.SetValue("VALUETYPE", type);
+ code_.SetValue("OFFSET", offset);
+ if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type)) {
+ code_ +=
+ GenReaderMainBody() + "return " + GenReader("VALUETYPE") + " }";
+ } else if (IsEnum(field.value.type)) {
+ code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
+ code_ += GenReaderMainBody() + "return " +
+ GenEnumConstructor("{{OFFSET}}") + "?? " +
+ GenEnumDefaultValue(field) + " }";
+ } else if (IsStruct(field.value.type)) {
+ code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
+ code_ += GenReaderMainBody() + "return " +
+ GenConstructor("{{ACCESS}}.postion + {{OFFSET}}");
+ }
+ if (parser_.opts.mutable_buffer && !IsStruct(field.value.type))
+ code_ += GenMutate("{{OFFSET}}", "", IsEnum(field.value.type));
+ }
+
+ if (parser_.opts.generate_object_based_api) {
+ GenerateObjectAPIExtensionHeader(NameWrappedInNameSpace(struct_def));
+ code_ += "return builder.create(struct: obj)";
+ Outdent();
+ code_ += "}";
+ }
+ Outdent();
+ code_ += "}\n";
+ }
+
+ // Generates the create function for swift
+ void GenStructWriter(const StructDef &struct_def) {
+ auto is_private_access = struct_def.attributes.Lookup("private");
+ code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
+ code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
+ code_.SetValue("SHORT_STRUCTNAME", Name(struct_def));
+ code_ += "extension {{STRUCTNAME}} {";
+ Indent();
+ code_ += "@discardableResult";
+ code_ +=
+ "{{ACCESS_TYPE}} static func create{{SHORT_STRUCTNAME}}(builder: inout "
+ "FlatBufferBuilder, \\";
+ std::string func_header = "";
+ GenerateStructArgs(struct_def, &func_header, "", "");
+ code_ += func_header.substr(0, func_header.size() - 2) + "\\";
+ code_ += ") -> Offset {";
+ Indent();
+ code_ +=
+ "builder.createStructOf(size: {{STRUCTNAME}}.size, alignment: "
+ "{{STRUCTNAME}}.alignment)";
+ code_ += "return builder.endStruct()";
+ Outdent();
+ code_ += "}\n";
+ Outdent();
+ code_ += "}\n";
+ }
+
+ void GenerateStructArgs(const StructDef &struct_def, std::string *code_ptr,
+ const std::string &nameprefix,
+ const std::string &object_name,
+ const std::string &obj_api_named = "",
+ bool is_obj_api = false) {
+ auto &code = *code_ptr;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ const auto &field_type = field.value.type;
+ if (IsStruct(field.value.type)) {
+ GenerateStructArgs(
+ *field_type.struct_def, code_ptr, (nameprefix + field.name),
+ (object_name + "." + field.name), obj_api_named, is_obj_api);
+ } else {
+ auto name = Name(field);
+ auto type = GenType(field.value.type);
+ if (!is_obj_api) {
+ code += nameprefix + name + ": " + type;
+ if (!IsEnum(field.value.type)) {
+ code += " = ";
+ auto is_bool = IsBool(field.value.type.base_type);
+ auto constant =
+ is_bool ? ("0" == field.value.constant ? "false" : "true")
+ : field.value.constant;
+ code += constant;
+ }
+ code += ", ";
+ continue;
+ }
+ code +=
+ nameprefix + name + ": " + obj_api_named + object_name + "." + name;
+ code += ", ";
+ }
+ }
+ }
+
+ // MARK: - Table Generator
+
+ // Generates the reader for swift
+ void GenTable(const StructDef &struct_def) {
+ auto is_private_access = struct_def.attributes.Lookup("private");
+ code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
+
+ GenObjectHeader(struct_def);
+ GenTableAccessors(struct_def);
+ GenTableReader(struct_def);
+ GenTableWriter(struct_def);
+ if (parser_.opts.generate_object_based_api)
+ GenerateObjectAPITableExtension(struct_def);
+ Outdent();
+ code_ += "}\n";
+ }
+
+ // Generates the reader for swift
+ void GenTableAccessors(const StructDef &struct_def) {
+ // Generate field id constants.
+ if (struct_def.fields.vec.size() > 0) {
+ code_ += "private enum {{TABLEOFFSET}}: VOffset {";
+ Indent();
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) { continue; }
+ code_.SetValue("OFFSET_NAME", Name(field));
+ code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
+ code_ += "case {{OFFSET_NAME}} = {{OFFSET_VALUE}}";
+ }
+ code_ += "var v: Int32 { Int32(self.rawValue) }";
+ code_ += "var p: VOffset { self.rawValue }";
+ Outdent();
+ code_ += "}";
+ code_ += "";
+ }
+ }
+
+ void GenObjectHeader(const StructDef &struct_def) {
+ GenComment(struct_def.doc_comment);
+
+ code_.SetValue("SHORT_STRUCTNAME", Name(struct_def));
+ code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
+ code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table");
+ code_.SetValue("MUTABLE", struct_def.fixed ? Mutable() : "");
+ code_ +=
+ "{{ACCESS_TYPE}} struct {{STRUCTNAME}}{{MUTABLE}}: FlatBufferObject\\";
+ if (!struct_def.fixed && parser_.opts.generate_object_based_api)
+ code_ += ", ObjectAPIPacker\\";
+ code_ += " {\n";
+ Indent();
+ code_ += ValidateFunc();
+ code_ +=
+ "{{ACCESS_TYPE}} var __buffer: ByteBuffer! { return {{ACCESS}}.bb }";
+ code_ += "private var {{ACCESS}}: {{OBJECTTYPE}}\n";
+ if (!struct_def.fixed) {
+ if (parser_.file_identifier_.length()) {
+ code_.SetValue("FILENAME", parser_.file_identifier_);
+ code_ +=
+ "{{ACCESS_TYPE}} static func finish(_ fbb: inout "
+ "FlatBufferBuilder, end: "
+ "Offset, prefix: Bool = false) { fbb.finish(offset: end, "
+ "fileId: "
+ "\"{{FILENAME}}\", addPrefix: prefix) }";
+ }
+ code_ +=
+ "{{ACCESS_TYPE}} static func getRootAs{{SHORT_STRUCTNAME}}(bb: "
+ "ByteBuffer) -> "
+ "{{STRUCTNAME}} { return {{STRUCTNAME}}(Table(bb: bb, position: "
+ "Int32(bb.read(def: UOffset.self, position: bb.reader)) + "
+ "Int32(bb.reader))) }\n";
+ code_ += "private init(_ t: Table) { {{ACCESS}} = t }";
+ }
+ code_ +=
+ "{{ACCESS_TYPE}} init(_ bb: ByteBuffer, o: Int32) { {{ACCESS}} = "
+ "{{OBJECTTYPE}}(bb: "
+ "bb, position: o) }";
+ code_ += "";
+ }
+
+ void GenTableWriter(const StructDef &struct_def) {
+ flatbuffers::FieldDef *key_field = nullptr;
+ std::vector<std::string> require_fields;
+ std::vector<std::string> create_func_body;
+ std::vector<std::string> create_func_header;
+ auto should_generate_create = struct_def.fields.vec.size() != 0;
+
+ code_.SetValue("NUMBEROFFIELDS", NumToString(struct_def.fields.vec.size()));
+ code_ +=
+ "{{ACCESS_TYPE}} static func start{{SHORT_STRUCTNAME}}(_ fbb: inout "
+ "FlatBufferBuilder) -> "
+ "UOffset { fbb.startTable(with: {{NUMBEROFFIELDS}}) }";
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ if (field.key) key_field = &field;
+ if (field.IsRequired())
+ require_fields.push_back(NumToString(field.value.offset));
+
+ GenTableWriterFields(field, &create_func_body, &create_func_header);
+ }
+ code_ +=
+ "{{ACCESS_TYPE}} static func end{{SHORT_STRUCTNAME}}(_ fbb: inout "
+ "FlatBufferBuilder, "
+ "start: "
+ "UOffset) -> Offset { let end = Offset(offset: "
+ "fbb.endTable(at: start))\\";
+ if (require_fields.capacity() != 0) {
+ std::string fields = "";
+ for (auto it = require_fields.begin(); it != require_fields.end(); ++it)
+ fields += *it + ", ";
+ code_.SetValue("FIELDS", fields.substr(0, fields.size() - 2));
+ code_ += "; fbb.require(table: end, fields: [{{FIELDS}}])\\";
+ }
+ code_ += "; return end }";
+
+ if (should_generate_create) {
+ code_ += "{{ACCESS_TYPE}} static func create{{SHORT_STRUCTNAME}}(";
+ Indent();
+ code_ += "_ fbb: inout FlatBufferBuilder,";
+ for (auto it = create_func_header.begin(); it < create_func_header.end();
+ ++it) {
+ code_ += *it + "\\";
+ if (it < create_func_header.end() - 1) code_ += ",";
+ }
+ code_ += "";
+ Outdent();
+ code_ += ") -> Offset {";
+ Indent();
+ code_ += "let __start = {{STRUCTNAME}}.start{{SHORT_STRUCTNAME}}(&fbb)";
+ for (auto it = create_func_body.begin(); it < create_func_body.end();
+ ++it) {
+ code_ += *it;
+ }
+ code_ +=
+ "return {{STRUCTNAME}}.end{{SHORT_STRUCTNAME}}(&fbb, start: __start)";
+ Outdent();
+ code_ += "}";
+ }
+
+ std::string spacing = "";
+
+ if (key_field != nullptr && !struct_def.fixed && struct_def.has_key) {
+ code_.SetValue("VALUENAME", NameWrappedInNameSpace(struct_def));
+ code_.SetValue("SHORT_VALUENAME", Name(struct_def));
+ code_.SetValue("VOFFSET", NumToString(key_field->value.offset));
+
+ code_ +=
+ "{{ACCESS_TYPE}} static func "
+ "sortVectorOf{{SHORT_VALUENAME}}(offsets:[Offset], "
+ "_ fbb: inout FlatBufferBuilder) -> Offset {";
+ Indent();
+ code_ += spacing + "var off = offsets";
+ code_ +=
+ spacing +
+ "off.sort { Table.compare(Table.offset(Int32($1.o), vOffset: "
+ "{{VOFFSET}}, fbb: fbb.buffer), Table.offset(Int32($0.o), vOffset: "
+ "{{VOFFSET}}, fbb: fbb.buffer), fbb: fbb.buffer) < 0 } ";
+ code_ += spacing + "return fbb.createVector(ofOffsets: off)";
+ Outdent();
+ code_ += "}";
+ GenLookup(*key_field);
+ }
+ }
+
+ void GenTableWriterFields(const FieldDef &field,
+ std::vector<std::string> *create_body,
+ std::vector<std::string> *create_header) {
+ std::string builder_string = ", _ fbb: inout FlatBufferBuilder) { ";
+ auto &create_func_body = *create_body;
+ auto &create_func_header = *create_header;
+ auto name = Name(field);
+ auto type = GenType(field.value.type);
+ auto opt_scalar =
+ field.IsOptional() && IsScalar(field.value.type.base_type);
+ auto nullable_type = opt_scalar ? type + "?" : type;
+ code_.SetValue("VALUENAME", name);
+ code_.SetValue("VALUETYPE", nullable_type);
+ code_.SetValue("OFFSET", name);
+ code_.SetValue("CONSTANT", field.value.constant);
+ std::string check_if_vector =
+ (IsVector(field.value.type) || IsArray(field.value.type)) ? "VectorOf("
+ : "(";
+ auto body = "add" + check_if_vector + name + ": ";
+ code_ += "{{ACCESS_TYPE}} static func " + body + "\\";
+
+ create_func_body.push_back("{{STRUCTNAME}}." + body + name + ", &fbb)");
+
+ if (IsScalar(field.value.type.base_type) &&
+ !IsBool(field.value.type.base_type)) {
+ std::string is_enum = IsEnum(field.value.type) ? ".rawValue" : "";
+ std::string optional_enum =
+ IsEnum(field.value.type) ? ("?" + is_enum) : "";
+ code_ +=
+ "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{VALUENAME}}\\";
+
+ code_ += field.IsOptional() ? (optional_enum + "\\")
+ : (is_enum + ", def: {{CONSTANT}}\\");
+
+ code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
+
+ auto default_value =
+ IsEnum(field.value.type)
+ ? (field.IsOptional() ? "nil" : GenEnumDefaultValue(field))
+ : field.value.constant;
+ create_func_header.push_back(
+ "" + name + ": " + nullable_type + " = " +
+ (field.IsOptional() ? "nil" : default_value));
+ return;
+ }
+
+ if (IsBool(field.value.type.base_type)) {
+ std::string default_value =
+ "0" == field.value.constant ? "false" : "true";
+
+ code_.SetValue("CONSTANT", default_value);
+ code_.SetValue("VALUETYPE", field.IsOptional() ? "Bool?" : "Bool");
+ code_ += "{{VALUETYPE}}" + builder_string +
+ "fbb.add(element: {{VALUENAME}},\\";
+ code_ += field.IsOptional() ? "\\" : " def: {{CONSTANT}},";
+ code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
+ create_func_header.push_back(
+ name + ": " + nullable_type + " = " +
+ (field.IsOptional() ? "nil" : default_value));
+ return;
+ }
+
+ if (IsStruct(field.value.type)) {
+ auto create_struct =
+ "guard let {{VALUENAME}} = {{VALUENAME}} else { return };"
+ " fbb.create(struct: {{VALUENAME}}, position: "
+ "{{TABLEOFFSET}}.{{OFFSET}}.p) }";
+ code_ += type + "?" + builder_string + create_struct;
+ /// Optional hard coded since structs are always optional
+ create_func_header.push_back(name + ": " + type + "? = nil");
+ return;
+ }
+
+ auto camel_case_name =
+ MakeCamel(name, false) +
+ (IsVector(field.value.type) || IsArray(field.value.type)
+ ? "VectorOffset"
+ : "Offset");
+ create_func_header.push_back(camel_case_name + " " + name + ": " +
+ "Offset = Offset()");
+ auto reader_type =
+ IsStruct(field.value.type) && field.value.type.struct_def->fixed
+ ? "structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"
+ : "offset: {{VALUENAME}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
+ code_ += "Offset" + builder_string + "fbb.add(" + reader_type;
+
+ auto vectortype = field.value.type.VectorType();
+
+ if ((vectortype.base_type == BASE_TYPE_STRUCT &&
+ field.value.type.struct_def->fixed) &&
+ (IsVector(field.value.type) || IsArray(field.value.type))) {
+ auto field_name = NameWrappedInNameSpace(*vectortype.struct_def);
+ code_ += "public static func startVectorOf" + MakeCamel(name, true) +
+ "(_ size: Int, in builder: inout "
+ "FlatBufferBuilder) {";
+ Indent();
+ code_ += "builder.startVector(size * MemoryLayout<" + field_name +
+ ">.size, elementSize: MemoryLayout<" + field_name +
+ ">.alignment)";
+ Outdent();
+ code_ += "}";
+ }
+ }
+
+ void GenTableReader(const StructDef &struct_def) {
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ GenTableReaderFields(field);
+ }
+ }
+
+ void GenTableReaderFields(const FieldDef &field) {
+ auto offset = NumToString(field.value.offset);
+ auto name = Name(field);
+ auto type = GenType(field.value.type);
+ code_.SetValue("VALUENAME", name);
+ code_.SetValue("VALUETYPE", type);
+ code_.SetValue("OFFSET", name);
+ code_.SetValue("CONSTANT", field.value.constant);
+ std::string def_Val = field.IsDefault() ? "{{CONSTANT}}" : "nil";
+ std::string optional = field.IsOptional() ? "?" : "";
+ auto const_string = "return o == 0 ? " + def_Val + " : ";
+ GenComment(field.doc_comment);
+ if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type) &&
+ !IsBool(field.value.type.base_type)) {
+ code_ += GenReaderMainBody(optional) + GenOffset() + const_string +
+ GenReader("VALUETYPE", "o") + " }";
+ if (parser_.opts.mutable_buffer) code_ += GenMutate("o", GenOffset());
+ return;
+ }
+
+ if (IsBool(field.value.type.base_type)) {
+ std::string default_value =
+ "0" == field.value.constant ? "false" : "true";
+ code_.SetValue("CONSTANT", default_value);
+ code_.SetValue("VALUETYPE", "Bool");
+ code_ += GenReaderMainBody(optional) + "\\";
+ code_.SetValue("VALUETYPE", "Byte");
+ code_ += GenOffset() + "return o == 0 ? {{CONSTANT}} : 0 != " +
+ GenReader("VALUETYPE", "o") + " }";
+ if (parser_.opts.mutable_buffer) code_ += GenMutate("o", GenOffset());
+ return;
+ }
+
+ if (IsEnum(field.value.type)) {
+ auto default_value =
+ field.IsOptional() ? "nil" : GenEnumDefaultValue(field);
+ code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
+ code_ += GenReaderMainBody(optional) + "\\";
+ code_ += GenOffset() + "return o == 0 ? " + default_value + " : " +
+ GenEnumConstructor("o") + "?? " + default_value + " }";
+ if (parser_.opts.mutable_buffer && !IsUnion(field.value.type))
+ code_ += GenMutate("o", GenOffset(), true);
+ return;
+ }
+
+ std::string is_required = field.IsRequired() ? "!" : "?";
+ auto required_reader = field.IsRequired() ? "return " : const_string;
+
+ if (IsStruct(field.value.type) && field.value.type.struct_def->fixed) {
+ code_.SetValue("VALUETYPE", GenType(field.value.type));
+ code_.SetValue("CONSTANT", "nil");
+ code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader +
+ "{{ACCESS}}.readBuffer(of: {{VALUETYPE}}.self, at: o) }";
+ code_.SetValue("VALUENAME", "mutable" + MakeCamel(name));
+ code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
+ code_.SetValue("CONSTANT", "nil");
+ code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader +
+ GenConstructor("o + {{ACCESS}}.postion");
+ return;
+ }
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT:
+ code_.SetValue("VALUETYPE", GenType(field.value.type));
+ code_.SetValue("CONSTANT", "nil");
+ code_ += GenReaderMainBody(is_required) + GenOffset() +
+ required_reader +
+ GenConstructor(GenIndirect("o + {{ACCESS}}.postion"));
+ break;
+
+ case BASE_TYPE_STRING: {
+ auto default_string = "\"" + field.value.constant + "\"";
+ code_.SetValue("VALUETYPE", GenType(field.value.type));
+ code_.SetValue("CONSTANT", field.IsDefault() ? default_string : "nil");
+ code_ += GenReaderMainBody(is_required) + GenOffset() +
+ required_reader + "{{ACCESS}}.string(at: o) }";
+ code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}SegmentArray: [UInt8]" +
+ is_required +
+ " { return "
+ "{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) }";
+ break;
+ }
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case BASE_TYPE_VECTOR: GenTableReaderVectorFields(field); break;
+ case BASE_TYPE_UNION:
+ code_.SetValue("CONSTANT", "nil");
+ code_ +=
+ "{{ACCESS_TYPE}} func {{VALUENAME}}<T: "
+ "FlatbuffersInitializable>(type: "
+ "T.Type) -> T" +
+ is_required + " { " + GenOffset() + required_reader +
+ "{{ACCESS}}.union(o) }";
+ break;
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+
+ void GenTableReaderVectorFields(const FieldDef &field) {
+ std::string const_string = "return o == 0 ? {{CONSTANT}} : ";
+ auto vectortype = field.value.type.VectorType();
+ code_.SetValue("SIZE", NumToString(InlineSize(vectortype)));
+ code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}Count: Int32 { " + GenOffset() +
+ "return o == 0 ? 0 : {{ACCESS}}.vector(count: o) }";
+ code_.SetValue("CONSTANT",
+ IsScalar(vectortype.base_type) == true ? "0" : "nil");
+ auto nullable = IsScalar(vectortype.base_type) == true ? "" : "?";
+ nullable = IsEnum(vectortype) == true ? "?" : nullable;
+
+ if (vectortype.base_type != BASE_TYPE_UNION) {
+ code_ += GenArrayMainBody(nullable) + GenOffset() + "\\";
+ } else {
+ code_ +=
+ "{{ACCESS_TYPE}} func {{VALUENAME}}<T: FlatbuffersInitializable>(at "
+ "index: "
+ "Int32, type: T.Type) -> T? { " +
+ GenOffset() + "\\";
+ }
+
+ if (IsBool(vectortype.base_type)) {
+ code_.SetValue("CONSTANT", field.value.offset == 0 ? "false" : "true");
+ code_.SetValue("VALUETYPE", "Bool");
+ }
+
+ if (!IsEnum(vectortype)) code_ += const_string + "\\";
+
+ if (IsScalar(vectortype.base_type) && !IsEnum(vectortype) &&
+ !IsBool(field.value.type.base_type)) {
+ code_ +=
+ "{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
+ "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
+ code_ +=
+ "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}] { return "
+ "{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) ?? [] }";
+ if (parser_.opts.mutable_buffer) code_ += GenMutateArray();
+ return;
+ }
+
+ if (vectortype.base_type == BASE_TYPE_STRUCT &&
+ field.value.type.struct_def->fixed) {
+ code_ +=
+ "{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
+ "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
+ code_.SetValue("VALUENAME", "mutable" + MakeCamel(Name(field)));
+ code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
+ code_ += GenArrayMainBody(nullable) + GenOffset() + const_string +
+ GenConstructor("{{ACCESS}}.vector(at: o) + index * {{SIZE}}");
+
+ return;
+ }
+
+ if (IsString(vectortype)) {
+ code_ +=
+ "{{ACCESS}}.directString(at: {{ACCESS}}.vector(at: o) + "
+ "index * {{SIZE}}) }";
+ return;
+ }
+
+ if (IsEnum(vectortype)) {
+ code_.SetValue("BASEVALUE", GenTypeBasic(vectortype, false));
+ code_ += "return o == 0 ? {{VALUETYPE}}" + GenEnumDefaultValue(field) +
+ " : {{VALUETYPE}}(rawValue: {{ACCESS}}.directRead(of: "
+ "{{BASEVALUE}}.self, offset: {{ACCESS}}.vector(at: o) + "
+ "index * {{SIZE}})) }";
+ return;
+ }
+ if (vectortype.base_type == BASE_TYPE_UNION) {
+ code_ +=
+ "{{ACCESS}}.directUnion({{ACCESS}}.vector(at: o) + "
+ "index * {{SIZE}}) }";
+ return;
+ }
+
+ if (vectortype.base_type == BASE_TYPE_STRUCT &&
+ !field.value.type.struct_def->fixed) {
+ code_ += GenConstructor(
+ "{{ACCESS}}.indirect({{ACCESS}}.vector(at: o) + index * "
+ "{{SIZE}})");
+ auto &sd = *field.value.type.struct_def;
+ auto &fields = sd.fields.vec;
+ for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
+ auto &key_field = **kit;
+ if (key_field.key) {
+ GenByKeyFunctions(key_field);
+ break;
+ }
+ }
+ }
+ }
+
+ void GenByKeyFunctions(const FieldDef &key_field) {
+ code_.SetValue("TYPE", GenType(key_field.value.type));
+ code_ +=
+ "{{ACCESS_TYPE}} func {{VALUENAME}}By(key: {{TYPE}}) -> {{VALUETYPE}}? "
+ "{ \\";
+ code_ += GenOffset() +
+ "return o == 0 ? nil : {{VALUETYPE}}.lookupByKey(vector: "
+ "{{ACCESS}}.vector(at: o), key: key, fbb: {{ACCESS}}.bb) }";
+ }
+
+ void GenEnum(const EnumDef &enum_def) {
+ if (enum_def.generated) return;
+ auto is_private_access = enum_def.attributes.Lookup("private");
+ code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
+ code_.SetValue("ENUM_NAME", NameWrappedInNameSpace(enum_def));
+ code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
+ GenComment(enum_def.doc_comment);
+ code_ += "{{ACCESS_TYPE}} enum {{ENUM_NAME}}: {{BASE_TYPE}}, Enum {";
+ Indent();
+ code_ += "{{ACCESS_TYPE}} typealias T = {{BASE_TYPE}}";
+ code_ +=
+ "{{ACCESS_TYPE}} static var byteSize: Int { return "
+ "MemoryLayout<{{BASE_TYPE}}>.size "
+ "}";
+ code_ +=
+ "{{ACCESS_TYPE}} var value: {{BASE_TYPE}} { return self.rawValue }";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ const auto &ev = **it;
+ auto name = Name(ev);
+ code_.SetValue("KEY", name);
+ code_.SetValue("VALUE", enum_def.ToString(ev));
+ GenComment(ev.doc_comment);
+ code_ += "case {{KEY}} = {{VALUE}}";
+ }
+ code_ += "\n";
+ AddMinOrMaxEnumValue(Name(*enum_def.MaxValue()), "max");
+ AddMinOrMaxEnumValue(Name(*enum_def.MinValue()), "min");
+ Outdent();
+ code_ += "}\n";
+ if (parser_.opts.generate_object_based_api && enum_def.is_union) {
+ code_ += "{{ACCESS_TYPE}} struct {{ENUM_NAME}}Union {";
+ Indent();
+ code_ += "{{ACCESS_TYPE}} var type: {{ENUM_NAME}}";
+ code_ += "{{ACCESS_TYPE}} var value: NativeObject?";
+ code_ +=
+ "{{ACCESS_TYPE}} init(_ v: NativeObject?, type: {{ENUM_NAME}}) {";
+ Indent();
+ code_ += "self.type = type";
+ code_ += "self.value = v";
+ Outdent();
+ code_ += "}";
+ code_ +=
+ "{{ACCESS_TYPE}} func pack(builder: inout FlatBufferBuilder) -> "
+ "Offset {";
+ Indent();
+ BuildUnionEnumSwitchCaseWritter(enum_def);
+ Outdent();
+ code_ += "}";
+ Outdent();
+ code_ += "}";
+ }
+ }
+
+ // MARK: - Object API
+
+ void GenerateObjectAPIExtensionHeader(std::string name) {
+ code_ += "\n";
+ code_ += "{{ACCESS_TYPE}} mutating func unpack() -> " + name + " {";
+ Indent();
+ code_ += "return " + name + "(&self)";
+ Outdent();
+ code_ += "}";
+ code_ +=
+ "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
+ "obj: "
+ "inout " +
+ name + "?) -> Offset {";
+ Indent();
+ code_ += "guard var obj = obj else { return Offset() }";
+ code_ += "return pack(&builder, obj: &obj)";
+ Outdent();
+ code_ += "}";
+ code_ += "";
+ code_ +=
+ "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
+ "obj: "
+ "inout " +
+ name + ") -> Offset {";
+ Indent();
+ }
+
+ void GenerateObjectAPIStructConstructor(const StructDef &struct_def) {
+ code_ +=
+ "{{ACCESS_TYPE}} init(_ _t: inout {{STRUCTNAME}}" + Mutable() + ") {";
+ Indent();
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ auto name = Name(field);
+ auto type = GenType(field.value.type);
+ code_.SetValue("VALUENAME", name);
+ if (IsStruct(field.value.type)) {
+ code_ += "var _v{{VALUENAME}} = _t.{{VALUENAME}}";
+ code_ += "_{{VALUENAME}} = _v{{VALUENAME}}.unpack()";
+ continue;
+ }
+ std::string is_enum = IsEnum(field.value.type) ? ".value" : "";
+ code_ += "_{{VALUENAME}} = _t.{{VALUENAME}}" + is_enum;
+ }
+ Outdent();
+ code_ += "}\n";
+ }
+
+ void GenObjectAPI(const StructDef &struct_def) {
+ code_ += "{{ACCESS_TYPE}} class " + ObjectAPIName("{{STRUCTNAME}}") +
+ ": NativeObject {\n";
+ std::vector<std::string> buffer_constructor;
+ std::vector<std::string> base_constructor;
+ Indent();
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ BuildObjectAPIConstructorBody(field, struct_def.fixed, buffer_constructor,
+ base_constructor);
+ }
+ code_ += "";
+ BuildObjectConstructor(buffer_constructor,
+ "_ _t: inout " + NameWrappedInNameSpace(struct_def));
+ BuildObjectConstructor(base_constructor);
+ if (!struct_def.fixed)
+ code_ +=
+ "{{ACCESS_TYPE}} func serialize() -> ByteBuffer { return "
+ "serialize(type: "
+ "{{STRUCTNAME}}.self) }\n";
+ Outdent();
+ code_ += "}";
+ }
+
+ void GenerateObjectAPITableExtension(const StructDef &struct_def) {
+ GenerateObjectAPIExtensionHeader(ObjectAPIName("{{STRUCTNAME}}"));
+ std::vector<std::string> unpack_body;
+ std::string builder = ", &builder)";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto name = Name(field);
+ auto type = GenType(field.value.type);
+ std::string check_if_vector =
+ (IsVector(field.value.type) || IsArray(field.value.type))
+ ? "VectorOf("
+ : "(";
+ std::string body = "add" + check_if_vector + name + ": ";
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
+ case BASE_TYPE_VECTOR: {
+ GenerateVectorObjectAPITableExtension(field, name, type);
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
+ builder);
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ code_ += "let __" + name + " = obj." + name +
+ "?.pack(builder: &builder) ?? Offset()";
+ unpack_body.push_back("if let o = obj." + name + "?.type {");
+ unpack_body.push_back(" {{STRUCTNAME}}.add(" + name + "Type: o" +
+ builder);
+ unpack_body.push_back(" {{STRUCTNAME}}." + body + "__" + name +
+ builder);
+ unpack_body.push_back("}\n");
+ break;
+ }
+ case BASE_TYPE_STRUCT: {
+ if (field.value.type.struct_def &&
+ field.value.type.struct_def->fixed) {
+ // This is a Struct (IsStruct), not a table. We create
+ // a native swift object in this case.
+ std::string code;
+ GenerateStructArgs(*field.value.type.struct_def, &code, "", "",
+ "$0", true);
+ code = code.substr(0, code.size() - 2);
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." + name +
+ builder);
+ } else {
+ code_ += "let __" + name + " = " + type +
+ ".pack(&builder, obj: &obj." + name + ")";
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
+ builder);
+ }
+ break;
+ }
+ case BASE_TYPE_STRING: {
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
+ builder);
+ if (field.IsRequired()) {
+ code_ +=
+ "let __" + name + " = builder.create(string: obj." + name + ")";
+ } else {
+ BuildingOptionalObjects(name, "builder.create(string: s)");
+ }
+ break;
+ }
+ case BASE_TYPE_UTYPE: break;
+ default:
+ unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." + name +
+ builder);
+ }
+ }
+ code_ += "let __root = {{STRUCTNAME}}.start{{SHORT_STRUCTNAME}}(&builder)";
+ for (auto it = unpack_body.begin(); it < unpack_body.end(); it++)
+ code_ += *it;
+ code_ +=
+ "return {{STRUCTNAME}}.end{{SHORT_STRUCTNAME}}(&builder, start: "
+ "__root)";
+ Outdent();
+ code_ += "}";
+ }
+
+ void GenerateVectorObjectAPITableExtension(const FieldDef &field,
+ const std::string &name,
+ const std::string &type) {
+ auto vectortype = field.value.type.VectorType();
+ switch (vectortype.base_type) {
+ case BASE_TYPE_UNION: {
+ code_ += "var __" + name + "__: [Offset] = []";
+ code_ += "for i in obj." + name + " {";
+ Indent();
+ code_ += "guard let off = i?.pack(builder: &builder) else { continue }";
+ code_ += "__" + name + "__.append(off)";
+ Outdent();
+ code_ += "}";
+ code_ += "let __" + name + " = builder.createVector(ofOffsets: __" +
+ name + "__)";
+ code_ += "let __" + name + "Type = builder.createVector(obj." + name +
+ ".compactMap { $0?.type })";
+ break;
+ }
+ case BASE_TYPE_UTYPE: break;
+ case BASE_TYPE_STRUCT: {
+ if (field.value.type.struct_def &&
+ !field.value.type.struct_def->fixed) {
+ code_ += "var __" + name + "__: [Offset] = []";
+ code_ += "for var i in obj." + name + " {";
+ Indent();
+ code_ +=
+ "__" + name + "__.append(" + type + ".pack(&builder, obj: &i))";
+ Outdent();
+ code_ += "}";
+ code_ += "let __" + name + " = builder.createVector(ofOffsets: __" +
+ name + "__)";
+ } else {
+ code_ += "{{STRUCTNAME}}.startVectorOf" + MakeCamel(name, true) +
+ "(obj." + name + ".count, in: &builder)";
+ std::string code;
+ GenerateStructArgs(*field.value.type.struct_def, &code, "", "", "_o",
+ true);
+ code = code.substr(0, code.size() - 2);
+ code_ += "for i in obj." + name + " {";
+ Indent();
+ code_ += "guard let _o = i else { continue }";
+ code_ += "builder.create(struct: _o)";
+ Outdent();
+ code_ += "}";
+ code_ += "let __" + name + " = builder.endVector(len: obj." + name +
+ ".count)";
+ }
+ break;
+ }
+ case BASE_TYPE_STRING: {
+ code_ += "let __" + name + " = builder.createVector(ofStrings: obj." +
+ name + ".compactMap({ $0 }) )";
+ break;
+ }
+ default: {
+ code_ += "let __" + name + " = builder.createVector(obj." + name + ")";
+ break;
+ }
+ }
+ }
+
+ void BuildingOptionalObjects(const std::string &name,
+ const std::string &body_front) {
+ code_ += "let __" + name + ": Offset";
+ code_ += "if let s = obj." + name + " {";
+ Indent();
+ code_ += "__" + name + " = " + body_front;
+ Outdent();
+ code_ += "} else {";
+ Indent();
+ code_ += "__" + name + " = Offset()";
+ Outdent();
+ code_ += "}";
+ code_ += "";
+ }
+
+ void BuildObjectConstructor(const std::vector<std::string> &body,
+ const std::string &header = "") {
+ code_.SetValue("HEADER", header);
+ code_ += "{{ACCESS_TYPE}} init({{HEADER}}) {";
+ Indent();
+ for (auto it = body.begin(); it < body.end(); ++it) code_ += *it;
+ Outdent();
+ code_ += "}\n";
+ }
+
+ void BuildObjectAPIConstructorBody(
+ const FieldDef &field, bool is_fixed,
+ std::vector<std::string> &buffer_constructor,
+ std::vector<std::string> &base_constructor) {
+ auto name = Name(field);
+ auto type = GenType(field.value.type);
+ code_.SetValue("VALUENAME", name);
+ code_.SetValue("VALUETYPE", type);
+ std::string is_required = field.IsRequired() ? "" : "?";
+
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ type = GenType(field.value.type, true);
+ code_.SetValue("VALUETYPE", type);
+ auto optional =
+ (field.value.type.struct_def && field.value.type.struct_def->fixed);
+ std::string question_mark =
+ (field.IsRequired() || (optional && is_fixed) ? "" : "?");
+
+ code_ +=
+ "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + question_mark;
+ base_constructor.push_back("" + name + " = " + type + "()");
+
+ if (field.value.type.struct_def->fixed) {
+ buffer_constructor.push_back("" + name + " = _t." + name);
+ } else {
+ buffer_constructor.push_back("var __" + name + " = _t." + name);
+ buffer_constructor.push_back(
+ "" + name + " = __" + name +
+ (field.IsRequired() ? "!" : question_mark) + ".unpack()");
+ }
+ break;
+ }
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
+ case BASE_TYPE_VECTOR: {
+ BuildObjectAPIConstructorBodyVectors(field, name, buffer_constructor,
+ base_constructor, " ");
+ break;
+ }
+ case BASE_TYPE_STRING: {
+ code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: String" + is_required;
+ buffer_constructor.push_back(name + " = _t." + name);
+
+ if (field.IsRequired()) {
+ std::string default_value =
+ field.IsDefault() ? field.value.constant : "";
+ base_constructor.push_back(name + " = \"" + default_value + "\"");
+ break;
+ }
+ if (field.IsDefault() && !field.IsRequired()) {
+ std::string value = field.IsDefault() ? field.value.constant : "nil";
+ base_constructor.push_back(name + " = \"" + value + "\"");
+ }
+ break;
+ }
+ case BASE_TYPE_UTYPE: break;
+ case BASE_TYPE_UNION: {
+ BuildUnionEnumSwitchCase(*field.value.type.enum_def, name,
+ buffer_constructor);
+ break;
+ }
+ default: {
+ buffer_constructor.push_back(name + " = _t." + name);
+ std::string nullable = field.IsOptional() ? "?" : "";
+ if (IsScalar(field.value.type.base_type) &&
+ !IsBool(field.value.type.base_type) && !IsEnum(field.value.type)) {
+ code_ +=
+ "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + nullable;
+ if (!field.IsOptional())
+ base_constructor.push_back(name + " = " + field.value.constant);
+ break;
+ }
+
+ if (IsEnum(field.value.type)) {
+ auto default_value = IsEnum(field.value.type)
+ ? GenEnumDefaultValue(field)
+ : field.value.constant;
+ code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}";
+ base_constructor.push_back(name + " = " + default_value);
+ break;
+ }
+
+ if (IsBool(field.value.type.base_type)) {
+ code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: Bool" + nullable;
+ std::string default_value =
+ "0" == field.value.constant ? "false" : "true";
+ if (!field.IsOptional())
+ base_constructor.push_back(name + " = " + default_value);
+ }
+ }
+ }
+ }
+
+ void BuildObjectAPIConstructorBodyVectors(
+ const FieldDef &field, const std::string &name,
+ std::vector<std::string> &buffer_constructor,
+ std::vector<std::string> &base_constructor,
+ const std::string &indentation) {
+ auto vectortype = field.value.type.VectorType();
+
+ if (vectortype.base_type != BASE_TYPE_UTYPE) {
+ buffer_constructor.push_back(name + " = []");
+ buffer_constructor.push_back("for index in 0..<_t." + name + "Count {");
+ base_constructor.push_back(name + " = []");
+ }
+
+ switch (vectortype.base_type) {
+ case BASE_TYPE_STRUCT: {
+ code_.SetValue("VALUETYPE", GenType(vectortype, true));
+ code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}?]";
+ if (!vectortype.struct_def->fixed) {
+ buffer_constructor.push_back(indentation + "var __v_ = _t." + name +
+ "(at: index)");
+ buffer_constructor.push_back(indentation + name +
+ ".append(__v_?.unpack())");
+ } else {
+ buffer_constructor.push_back(indentation + name + ".append(_t." +
+ name + "(at: index))");
+ }
+ break;
+ }
+ case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
+ case BASE_TYPE_VECTOR: {
+ break;
+ }
+ case BASE_TYPE_UNION: {
+ BuildUnionEnumSwitchCase(*field.value.type.enum_def, name,
+ buffer_constructor, indentation, true);
+ break;
+ }
+ case BASE_TYPE_UTYPE: break;
+ default: {
+ code_.SetValue(
+ "VALUETYPE",
+ (IsString(vectortype) ? "String?" : GenType(vectortype)));
+ code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}]";
+
+ if (IsEnum(vectortype) && vectortype.base_type != BASE_TYPE_UNION) {
+ auto default_value = IsEnum(field.value.type)
+ ? GenEnumDefaultValue(field)
+ : field.value.constant;
+ buffer_constructor.push_back(indentation + name + ".append(_t." +
+ name + "(at: index)!)");
+ break;
+ }
+ buffer_constructor.push_back(indentation + name + ".append(_t." + name +
+ "(at: index))");
+ break;
+ }
+ }
+ if (vectortype.base_type != BASE_TYPE_UTYPE)
+ buffer_constructor.push_back("}");
+ }
+
+ void BuildUnionEnumSwitchCaseWritter(const EnumDef &ev) {
+ auto field_name = Name(ev);
+ code_.SetValue("VALUETYPE", field_name);
+ code_ += "switch type {";
+ for (auto it = ev.Vals().begin(); it < ev.Vals().end(); ++it) {
+ auto field = **it;
+ auto ev_name = Name(field);
+ auto type = GenType(field.union_type);
+ auto is_struct = IsStruct(field.union_type) ? type + Mutable() : type;
+ if (field.union_type.base_type == BASE_TYPE_NONE) { continue; }
+ code_ += "case ." + ev_name + ":";
+ Indent();
+ code_ += "var __obj = value as? " + GenType(field.union_type, true);
+ code_ += "return " + is_struct + ".pack(&builder, obj: &__obj)";
+ Outdent();
+ }
+ code_ += "default: return Offset()";
+ code_ += "}";
+ }
+
+ void BuildUnionEnumSwitchCase(const EnumDef &ev, const std::string &name,
+ std::vector<std::string> &buffer_constructor,
+ const std::string &indentation = "",
+ const bool is_vector = false) {
+ auto field_name = NameWrappedInNameSpace(ev);
+ code_.SetValue("VALUETYPE", field_name);
+ code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: \\";
+ code_ += is_vector ? "[{{VALUETYPE}}Union?]" : "{{VALUETYPE}}Union?";
+
+ auto vector_reader = is_vector ? "(at: index" : "";
+ buffer_constructor.push_back(indentation + "switch _t." + name + "Type" +
+ vector_reader + (is_vector ? ")" : "") + " {");
+
+ for (auto it = ev.Vals().begin(); it < ev.Vals().end(); ++it) {
+ auto field = **it;
+ auto ev_name = Name(field);
+ if (field.union_type.base_type == BASE_TYPE_NONE) { continue; }
+ auto type = IsStruct(field.union_type)
+ ? GenType(field.union_type) + Mutable()
+ : GenType(field.union_type);
+ buffer_constructor.push_back(indentation + "case ." + ev_name + ":");
+ buffer_constructor.push_back(
+ indentation + " var _v = _t." + name + (is_vector ? "" : "(") +
+ vector_reader + (is_vector ? ", " : "") + "type: " + type + ".self)");
+ auto constructor =
+ field_name + "Union(_v?.unpack(), type: ." + ev_name + ")";
+ buffer_constructor.push_back(
+ indentation + " " + name +
+ (is_vector ? ".append(" + constructor + ")" : " = " + constructor));
+ }
+ buffer_constructor.push_back(indentation + "default: break");
+ buffer_constructor.push_back(indentation + "}");
+ }
+
+ void AddMinOrMaxEnumValue(const std::string &str, const std::string &type) {
+ auto current_value = str;
+ code_.SetValue(type, current_value);
+ code_ += "{{ACCESS_TYPE}} static var " + type +
+ ": {{ENUM_NAME}} { return .{{" + type + "}} }";
+ }
+
+ void GenLookup(const FieldDef &key_field) {
+ code_.SetValue("OFFSET", NumToString(key_field.value.offset));
+ std::string offset_reader =
+ "Table.offset(Int32(fbb.capacity) - tableOffset, vOffset: {{OFFSET}}, "
+ "fbb: fbb)";
+
+ code_.SetValue("TYPE", GenType(key_field.value.type));
+ code_ +=
+ "fileprivate static func lookupByKey(vector: Int32, key: {{TYPE}}, "
+ "fbb: "
+ "ByteBuffer) -> {{VALUENAME}}? {";
+ Indent();
+ if (IsString(key_field.value.type))
+ code_ += "let key = key.utf8.map { $0 }";
+ code_ += "var span = fbb.read(def: Int32.self, position: Int(vector - 4))";
+ code_ += "var start: Int32 = 0";
+ code_ += "while span != 0 {";
+ Indent();
+ code_ += "var middle = span / 2";
+ code_ +=
+ "let tableOffset = Table.indirect(vector + 4 * (start + middle), fbb)";
+ if (IsString(key_field.value.type)) {
+ code_ += "let comp = Table.compare(" + offset_reader + ", key, fbb: fbb)";
+ } else {
+ code_ += "let comp = fbb.read(def: {{TYPE}}.self, position: Int(" +
+ offset_reader + "))";
+ }
+
+ code_ += "if comp > 0 {";
+ Indent();
+ code_ += "span = middle";
+ Outdent();
+ code_ += "} else if comp < 0 {";
+ Indent();
+ code_ += "middle += 1";
+ code_ += "start += middle";
+ code_ += "span -= middle";
+ Outdent();
+ code_ += "} else {";
+ Indent();
+ code_ += "return {{VALUENAME}}(fbb, o: tableOffset)";
+ Outdent();
+ code_ += "}";
+ Outdent();
+ code_ += "}";
+ code_ += "return nil";
+ Outdent();
+ code_ += "}";
+ }
+
+ inline void GenPadding(const FieldDef &field, int *id) {
+ if (field.padding) {
+ for (int i = 0; i < 4; i++) {
+ if (static_cast<int>(field.padding) & (1 << i)) {
+ auto bits = (1 << i) * 8;
+ code_ += "private let padding" + NumToString((*id)++) + "__: UInt" +
+ NumToString(bits) + " = 0";
+ }
+ }
+ FLATBUFFERS_ASSERT(!(field.padding & ~0xF));
+ }
+ }
+
+ void GenComment(const std::vector<std::string> &dc) {
+ if (dc.begin() == dc.end()) {
+ // Don't output empty comment blocks with 0 lines of comment content.
+ return;
+ }
+ for (auto it = dc.begin(); it != dc.end(); ++it) { code_ += "/// " + *it; }
+ }
+
+ std::string GenOffset() {
+ return "let o = {{ACCESS}}.offset({{TABLEOFFSET}}.{{OFFSET}}.v); ";
+ }
+
+ std::string GenReaderMainBody(const std::string &optional = "") {
+ return "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + optional +
+ " { ";
+ }
+
+ std::string GenReader(const std::string &type,
+ const std::string &at = "{{OFFSET}}") {
+ return "{{ACCESS}}.readBuffer(of: {{" + type + "}}.self, at: " + at + ")";
+ }
+
+ std::string GenConstructor(const std::string &offset) {
+ return "{{VALUETYPE}}({{ACCESS}}.bb, o: " + offset + ") }";
+ }
+
+ std::string GenMutate(const std::string &offset,
+ const std::string &get_offset, bool isRaw = false) {
+ return "@discardableResult {{ACCESS_TYPE}} func mutate({{VALUENAME}}: "
+ "{{VALUETYPE}}) -> Bool {" +
+ get_offset + " return {{ACCESS}}.mutate({{VALUENAME}}" +
+ (isRaw ? ".rawValue" : "") + ", index: " + offset + ") }";
+ }
+
+ std::string GenMutateArray() {
+ return "{{ACCESS_TYPE}} func mutate({{VALUENAME}}: {{VALUETYPE}}, at "
+ "index: "
+ "Int32) -> Bool { " +
+ GenOffset() +
+ "return {{ACCESS}}.directMutate({{VALUENAME}}, index: "
+ "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
+ }
+
+ std::string GenEnumDefaultValue(const FieldDef &field) {
+ auto &value = field.value;
+ FLATBUFFERS_ASSERT(value.type.enum_def);
+ auto &enum_def = *value.type.enum_def;
+ // Vector of enum defaults are always "[]" which never works.
+ const std::string constant = IsVector(value.type) ? "0" : value.constant;
+ auto enum_val = enum_def.FindByValue(constant);
+ std::string name;
+ if (enum_val) {
+ name = Name(*enum_val);
+ } else {
+ const auto &ev = **enum_def.Vals().begin();
+ name = Name(ev);
+ }
+ return "." + name;
+ }
+
+ std::string GenEnumConstructor(const std::string &at) {
+ return "{{VALUETYPE}}(rawValue: " + GenReader("BASEVALUE", at) + ") ";
+ }
+
+ std::string ValidateFunc() {
+ return "static func validateVersion() { FlatBuffersVersion_2_0_0() }";
+ }
+
+ std::string GenType(const Type &type,
+ const bool should_consider_suffix = false) const {
+ return IsScalar(type.base_type)
+ ? GenTypeBasic(type)
+ : (IsArray(type) ? GenType(type.VectorType())
+ : GenTypePointer(type, should_consider_suffix));
+ }
+
+ std::string GenTypePointer(const Type &type,
+ const bool should_consider_suffix) const {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return "String";
+ case BASE_TYPE_VECTOR: return GenType(type.VectorType());
+ case BASE_TYPE_STRUCT: {
+ auto &struct_ = *type.struct_def;
+ if (should_consider_suffix && !struct_.fixed) {
+ return WrapInNameSpace(struct_.defined_namespace,
+ ObjectAPIName(Name(struct_)));
+ }
+ return WrapInNameSpace(struct_.defined_namespace, Name(struct_));
+ }
+ case BASE_TYPE_UNION:
+ default: return "FlatbuffersInitializable";
+ }
+ }
+
+ std::string GenTypeBasic(const Type &type) const {
+ return GenTypeBasic(type, true);
+ }
+
+ std::string ObjectAPIName(const std::string &name) const {
+ return parser_.opts.object_prefix + name + parser_.opts.object_suffix;
+ }
+
+ void Indent() { code_.IncrementIdentLevel(); }
+
+ void Outdent() { code_.DecrementIdentLevel(); }
+
+ std::string NameWrappedInNameSpace(const EnumDef &enum_def) const {
+ return WrapInNameSpace(enum_def.defined_namespace, Name(enum_def));
+ }
+
+ std::string NameWrappedInNameSpace(const StructDef &struct_def) const {
+ return WrapInNameSpace(struct_def.defined_namespace, Name(struct_def));
+ }
+
+ std::string GenTypeBasic(const Type &type, bool can_override) const {
+ // clang-format off
+ static const char * const swift_type[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
+ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE, STYPE) \
+ #STYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ // clang-format on
+ if (can_override) {
+ if (type.enum_def) return NameWrappedInNameSpace(*type.enum_def);
+ if (type.base_type == BASE_TYPE_BOOL) return "Bool";
+ }
+ return swift_type[static_cast<int>(type.base_type)];
+ }
+
+ std::string EscapeKeyword(const std::string &name) const {
+ return keywords_.find(name) == keywords_.end() ? name : name + "_";
+ }
+
+ std::string Mutable() const { return "_Mutable"; }
+
+ std::string Name(const EnumVal &ev) const {
+ auto name = ev.name;
+ if (isupper(name.front())) {
+ std::transform(name.begin(), name.end(), name.begin(), CharToLower);
+ }
+ return EscapeKeyword(MakeCamel(name, false));
+ }
+
+ std::string Name(const Definition &def) const {
+ return EscapeKeyword(MakeCamel(def.name, false));
+ }
+};
+} // namespace swift
+bool GenerateSwift(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ swift::SwiftGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_text.cpp b/contrib/libs/flatbuffers/src/idl_gen_text.cpp
new file mode 100644
index 0000000000..903c41ecdb
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_text.cpp
@@ -0,0 +1,414 @@
+/*
+ * 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 "flatbuffers/flatbuffers.h"
+#include "flatbuffers/flexbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+struct PrintScalarTag {};
+struct PrintPointerTag {};
+template<typename T> struct PrintTag { typedef PrintScalarTag type; };
+template<> struct PrintTag<const void *> { typedef PrintPointerTag type; };
+
+struct JsonPrinter {
+ // If indentation is less than 0, that indicates we don't want any newlines
+ // either.
+ void AddNewLine() {
+ if (opts.indent_step >= 0) text += '\n';
+ }
+
+ void AddIndent(int ident) { text.append(ident, ' '); }
+
+ int Indent() const { return std::max(opts.indent_step, 0); }
+
+ // Output an identifier with or without quotes depending on strictness.
+ void OutputIdentifier(const std::string &name) {
+ if (opts.strict_json) text += '\"';
+ text += name;
+ if (opts.strict_json) text += '\"';
+ }
+
+ // Print (and its template specialization below for pointers) generate text
+ // for a single FlatBuffer value into JSON format.
+ // The general case for scalars:
+ template<typename T>
+ bool PrintScalar(T val, const Type &type, int /*indent*/) {
+ if (IsBool(type.base_type)) {
+ text += val != 0 ? "true" : "false";
+ return true; // done
+ }
+
+ if (opts.output_enum_identifiers && type.enum_def) {
+ const auto &enum_def = *type.enum_def;
+ if (auto ev = enum_def.ReverseLookup(static_cast<int64_t>(val))) {
+ text += '\"';
+ text += ev->name;
+ text += '\"';
+ return true; // done
+ } else if (val && enum_def.attributes.Lookup("bit_flags")) {
+ const auto entry_len = text.length();
+ const auto u64 = static_cast<uint64_t>(val);
+ uint64_t mask = 0;
+ text += '\"';
+ for (auto it = enum_def.Vals().begin(), e = enum_def.Vals().end();
+ it != e; ++it) {
+ auto f = (*it)->GetAsUInt64();
+ if (f & u64) {
+ mask |= f;
+ text += (*it)->name;
+ text += ' ';
+ }
+ }
+ // Don't slice if (u64 != mask)
+ if (mask && (u64 == mask)) {
+ text[text.length() - 1] = '\"';
+ return true; // done
+ }
+ text.resize(entry_len); // restore
+ }
+ // print as numeric value
+ }
+
+ text += NumToString(val);
+ return true;
+ }
+
+ void AddComma() {
+ if (!opts.protobuf_ascii_alike) text += ',';
+ }
+
+ // Print a vector or an array of JSON values, comma seperated, wrapped in
+ // "[]".
+ template<typename Container>
+ bool PrintContainer(PrintScalarTag, const Container &c, size_t size,
+ const Type &type, int indent, const uint8_t *) {
+ const auto elem_indent = indent + Indent();
+ text += '[';
+ AddNewLine();
+ for (uoffset_t i = 0; i < size; i++) {
+ if (i) {
+ AddComma();
+ AddNewLine();
+ }
+ AddIndent(elem_indent);
+ if (!PrintScalar(c[i], type, elem_indent)) { return false; }
+ }
+ AddNewLine();
+ AddIndent(indent);
+ text += ']';
+ return true;
+ }
+
+ // Print a vector or an array of JSON values, comma seperated, wrapped in
+ // "[]".
+ template<typename Container>
+ bool PrintContainer(PrintPointerTag, const Container &c, size_t size,
+ const Type &type, int indent, const uint8_t *prev_val) {
+ const auto is_struct = IsStruct(type);
+ const auto elem_indent = indent + Indent();
+ text += '[';
+ AddNewLine();
+ for (uoffset_t i = 0; i < size; i++) {
+ if (i) {
+ AddComma();
+ AddNewLine();
+ }
+ AddIndent(elem_indent);
+ auto ptr = is_struct ? reinterpret_cast<const void *>(
+ c.Data() + type.struct_def->bytesize * i)
+ : c[i];
+ if (!PrintOffset(ptr, type, elem_indent, prev_val,
+ static_cast<soffset_t>(i))) {
+ return false;
+ }
+ }
+ AddNewLine();
+ AddIndent(indent);
+ text += ']';
+ return true;
+ }
+
+ template<typename T>
+ bool PrintVector(const void *val, const Type &type, int indent,
+ const uint8_t *prev_val) {
+ typedef Vector<T> Container;
+ typedef typename PrintTag<typename Container::return_type>::type tag;
+ auto &vec = *reinterpret_cast<const Container *>(val);
+ return PrintContainer<Container>(tag(), vec, vec.size(), type, indent,
+ prev_val);
+ }
+
+ // Print an array a sequence of JSON values, comma separated, wrapped in "[]".
+ template<typename T>
+ bool PrintArray(const void *val, size_t size, const Type &type, int indent) {
+ typedef Array<T, 0xFFFF> Container;
+ typedef typename PrintTag<typename Container::return_type>::type tag;
+ auto &arr = *reinterpret_cast<const Container *>(val);
+ return PrintContainer<Container>(tag(), arr, size, type, indent, nullptr);
+ }
+
+ bool PrintOffset(const void *val, const Type &type, int indent,
+ const uint8_t *prev_val, soffset_t vector_index) {
+ switch (type.base_type) {
+ case BASE_TYPE_UNION: {
+ // If this assert hits, you have an corrupt buffer, a union type field
+ // was not present or was out of range.
+ FLATBUFFERS_ASSERT(prev_val);
+ auto union_type_byte = *prev_val; // Always a uint8_t.
+ if (vector_index >= 0) {
+ auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(
+ prev_val + ReadScalar<uoffset_t>(prev_val));
+ union_type_byte = type_vec->Get(static_cast<uoffset_t>(vector_index));
+ }
+ auto enum_val = type.enum_def->ReverseLookup(union_type_byte, true);
+ if (enum_val) {
+ return PrintOffset(val, enum_val->union_type, indent, nullptr, -1);
+ } else {
+ return false;
+ }
+ }
+ case BASE_TYPE_STRUCT:
+ return GenStruct(*type.struct_def, reinterpret_cast<const Table *>(val),
+ indent);
+ case BASE_TYPE_STRING: {
+ auto s = reinterpret_cast<const String *>(val);
+ return EscapeString(s->c_str(), s->size(), &text, opts.allow_non_utf8,
+ opts.natural_utf8);
+ }
+ case BASE_TYPE_VECTOR: {
+ const auto vec_type = type.VectorType();
+ // Call PrintVector above specifically for each element type:
+ // clang-format off
+ switch (vec_type.base_type) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_ ## ENUM: \
+ if (!PrintVector<CTYPE>( \
+ val, vec_type, indent, prev_val)) { \
+ return false; \
+ } \
+ break;
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ }
+ // clang-format on
+ return true;
+ }
+ case BASE_TYPE_ARRAY: {
+ const auto vec_type = type.VectorType();
+ // Call PrintArray above specifically for each element type:
+ // clang-format off
+ switch (vec_type.base_type) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_ ## ENUM: \
+ if (!PrintArray<CTYPE>( \
+ val, type.fixed_length, vec_type, indent)) { \
+ return false; \
+ } \
+ break;
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
+ // Arrays of scalars or structs are only possible.
+ FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ case BASE_TYPE_ARRAY: FLATBUFFERS_ASSERT(0);
+ }
+ // clang-format on
+ return true;
+ }
+ default: FLATBUFFERS_ASSERT(0); return false;
+ }
+ }
+
+ template<typename T> static T GetFieldDefault(const FieldDef &fd) {
+ T val;
+ auto check = StringToNumber(fd.value.constant.c_str(), &val);
+ (void)check;
+ FLATBUFFERS_ASSERT(check);
+ return val;
+ }
+
+ // Generate text for a scalar field.
+ template<typename T>
+ bool GenField(const FieldDef &fd, const Table *table, bool fixed,
+ int indent) {
+ return PrintScalar(
+ fixed ? reinterpret_cast<const Struct *>(table)->GetField<T>(
+ fd.value.offset)
+ : table->GetField<T>(fd.value.offset, GetFieldDefault<T>(fd)),
+ fd.value.type, indent);
+ }
+
+ // Generate text for non-scalar field.
+ bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
+ int indent, const uint8_t *prev_val) {
+ const void *val = nullptr;
+ if (fixed) {
+ // The only non-scalar fields in structs are structs or arrays.
+ FLATBUFFERS_ASSERT(IsStruct(fd.value.type) || IsArray(fd.value.type));
+ val = reinterpret_cast<const Struct *>(table)->GetStruct<const void *>(
+ fd.value.offset);
+ } else if (fd.flexbuffer) {
+ auto vec = table->GetPointer<const Vector<uint8_t> *>(fd.value.offset);
+ auto root = flexbuffers::GetRoot(vec->data(), vec->size());
+ root.ToString(true, opts.strict_json, text);
+ return true;
+ } else if (fd.nested_flatbuffer) {
+ auto vec = table->GetPointer<const Vector<uint8_t> *>(fd.value.offset);
+ auto root = GetRoot<Table>(vec->data());
+ return GenStruct(*fd.nested_flatbuffer, root, indent);
+ } else {
+ val = IsStruct(fd.value.type)
+ ? table->GetStruct<const void *>(fd.value.offset)
+ : table->GetPointer<const void *>(fd.value.offset);
+ }
+ return PrintOffset(val, fd.value.type, indent, prev_val, -1);
+ }
+
+ // Generate text for a struct or table, values separated by commas, indented,
+ // and bracketed by "{}"
+ bool GenStruct(const StructDef &struct_def, const Table *table, int indent) {
+ text += '{';
+ int fieldout = 0;
+ const uint8_t *prev_val = nullptr;
+ const auto elem_indent = indent + Indent();
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ FieldDef &fd = **it;
+ auto is_present = struct_def.fixed || table->CheckField(fd.value.offset);
+ auto output_anyway = (opts.output_default_scalars_in_json || fd.key) &&
+ IsScalar(fd.value.type.base_type) && !fd.deprecated;
+ if (is_present || output_anyway) {
+ if (fieldout++) { AddComma(); }
+ AddNewLine();
+ AddIndent(elem_indent);
+ OutputIdentifier(fd.name);
+ if (!opts.protobuf_ascii_alike ||
+ (fd.value.type.base_type != BASE_TYPE_STRUCT &&
+ fd.value.type.base_type != BASE_TYPE_VECTOR))
+ text += ':';
+ text += ' ';
+ // clang-format off
+ switch (fd.value.type.base_type) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_ ## ENUM: \
+ if (!GenField<CTYPE>(fd, table, struct_def.fixed, elem_indent)) { \
+ return false; \
+ } \
+ break;
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ // Generate drop-thru case statements for all pointer types:
+ #define FLATBUFFERS_TD(ENUM, ...) \
+ case BASE_TYPE_ ## ENUM:
+ FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
+ FLATBUFFERS_GEN_TYPE_ARRAY(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ if (!GenFieldOffset(fd, table, struct_def.fixed, elem_indent, prev_val)) {
+ return false;
+ }
+ break;
+ }
+ // clang-format on
+ // Track prev val for use with union types.
+ if (struct_def.fixed) {
+ prev_val = reinterpret_cast<const uint8_t *>(table) + fd.value.offset;
+ } else {
+ prev_val = table->GetAddressOf(fd.value.offset);
+ }
+ }
+ }
+ AddNewLine();
+ AddIndent(indent);
+ text += '}';
+ return true;
+ }
+
+ JsonPrinter(const Parser &parser, std::string &dest)
+ : opts(parser.opts), text(dest) {
+ text.reserve(1024); // Reduce amount of inevitable reallocs.
+ }
+
+ const IDLOptions &opts;
+ std::string &text;
+};
+
+static bool GenerateTextImpl(const Parser &parser, const Table *table,
+ const StructDef &struct_def, std::string *_text) {
+ JsonPrinter printer(parser, *_text);
+ if (!printer.GenStruct(struct_def, table, 0)) { return false; }
+ printer.AddNewLine();
+ return true;
+}
+
+// Generate a text representation of a flatbuffer in JSON format.
+bool GenerateTextFromTable(const Parser &parser, const void *table,
+ const std::string &table_name, std::string *_text) {
+ auto struct_def = parser.LookupStruct(table_name);
+ if (struct_def == nullptr) { return false; }
+ auto root = static_cast<const Table *>(table);
+ return GenerateTextImpl(parser, root, *struct_def, _text);
+}
+
+// Generate a text representation of a flatbuffer in JSON format.
+bool GenerateText(const Parser &parser, const void *flatbuffer,
+ std::string *_text) {
+ FLATBUFFERS_ASSERT(parser.root_struct_def_); // call SetRootType()
+ auto root = parser.opts.size_prefixed ? GetSizePrefixedRoot<Table>(flatbuffer)
+ : GetRoot<Table>(flatbuffer);
+ return GenerateTextImpl(parser, root, *parser.root_struct_def_, _text);
+}
+
+static std::string TextFileName(const std::string &path,
+ const std::string &file_name) {
+ return path + file_name + ".json";
+}
+
+bool GenerateTextFile(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ if (parser.opts.use_flexbuffers) {
+ std::string json;
+ parser.flex_root_.ToString(true, parser.opts.strict_json, json);
+ return flatbuffers::SaveFile(TextFileName(path, file_name).c_str(),
+ json.c_str(), json.size(), true);
+ }
+ if (!parser.builder_.GetSize() || !parser.root_struct_def_) return true;
+ std::string text;
+ if (!GenerateText(parser, parser.builder_.GetBufferPointer(), &text)) {
+ return false;
+ }
+ return flatbuffers::SaveFile(TextFileName(path, file_name).c_str(), text,
+ false);
+}
+
+std::string TextMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ if (!parser.builder_.GetSize() || !parser.root_struct_def_) return "";
+ std::string filebase =
+ flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
+ std::string make_rule = TextFileName(path, filebase) + ": " + file_name;
+ auto included_files =
+ parser.GetIncludedFilesRecursive(parser.root_struct_def_->file);
+ for (auto it = included_files.begin(); it != included_files.end(); ++it) {
+ make_rule += " " + *it;
+ }
+ return make_rule;
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_gen_ts.cpp b/contrib/libs/flatbuffers/src/idl_gen_ts.cpp
new file mode 100644
index 0000000000..53e088fe13
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_gen_ts.cpp
@@ -0,0 +1,1583 @@
+/*
+ * 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 <algorithm>
+#include <cassert>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+struct ImportDefinition {
+ std::string name;
+ std::string statement;
+ const Definition *dependent;
+ const Definition *dependency;
+};
+
+enum AnnotationType { kParam = 0, kType = 1, kReturns = 2 };
+
+namespace ts {
+// Iterate through all definitions we haven't generate code for (enums, structs,
+// and tables) and output them to a single file.
+class TsGenerator : public BaseGenerator {
+ public:
+ typedef std::map<std::string, ImportDefinition> import_set;
+
+ TsGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "", ".", "ts") {}
+ bool generate() {
+ generateEnums();
+ generateStructs();
+ return true;
+ }
+
+ // Save out the generated code for a single class while adding
+ // declaration boilerplate.
+ bool SaveType(const Definition &definition, const std::string &classcode,
+ import_set &imports, import_set &bare_imports) const {
+ if (!classcode.length()) return true;
+
+ std::string code =
+ "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
+
+ for (auto it = bare_imports.begin(); it != bare_imports.end(); it++)
+ code += it->second.statement + "\n";
+ if (!bare_imports.empty()) code += "\n";
+
+ for (auto it = imports.begin(); it != imports.end(); it++)
+ if (it->second.dependency != &definition) // do not import itself
+ code += it->second.statement + "\n";
+ if (!imports.empty()) code += "\n\n";
+
+ code += classcode;
+ auto filename = NamespaceDir(*definition.defined_namespace, true) +
+ ToDasherizedCase(definition.name) + ".ts";
+ return SaveFile(filename.c_str(), code, false);
+ }
+
+ private:
+ // Generate code for all enums.
+ void generateEnums() {
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ import_set bare_imports;
+ import_set imports;
+ std::string enumcode;
+ auto &enum_def = **it;
+ GenEnum(enum_def, &enumcode, imports, false);
+ GenEnum(enum_def, &enumcode, imports, true);
+ SaveType(enum_def, enumcode, imports, bare_imports);
+ }
+ }
+
+ // Generate code for all structs.
+ void generateStructs() {
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ import_set bare_imports;
+ import_set imports;
+ AddImport(bare_imports, "* as flatbuffers", "flatbuffers");
+ auto &struct_def = **it;
+ std::string declcode;
+ GenStruct(parser_, struct_def, &declcode, imports);
+ SaveType(struct_def, declcode, imports, bare_imports);
+ }
+ }
+
+ // Generate a documentation comment, if available.
+ static void GenDocComment(const std::vector<std::string> &dc,
+ std::string *code_ptr,
+ const char *indent = nullptr) {
+ if (dc.empty()) {
+ // Don't output empty comment blocks with 0 lines of comment content.
+ return;
+ }
+
+ std::string &code = *code_ptr;
+ if (indent) code += indent;
+ code += "/**\n";
+ for (auto it = dc.begin(); it != dc.end(); ++it) {
+ if (indent) code += indent;
+ code += " *" + *it + "\n";
+ }
+ if (indent) code += indent;
+ code += " */\n";
+ }
+
+ static void GenDocComment(std::string *code_ptr) {
+ GenDocComment(std::vector<std::string>(), code_ptr);
+ }
+
+ // Generate an enum declaration and an enum string lookup table.
+ void GenEnum(EnumDef &enum_def, std::string *code_ptr, import_set &imports,
+ bool reverse) {
+ if (enum_def.generated) return;
+ if (reverse) return; // FIXME.
+ std::string &code = *code_ptr;
+ GenDocComment(enum_def.doc_comment, code_ptr);
+ std::string ns = GetNameSpace(enum_def);
+ std::string enum_def_name = enum_def.name + (reverse ? "Name" : "");
+ code += "export enum " + enum_def.name + "{\n";
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
+ auto &ev = **it;
+ if (!ev.doc_comment.empty()) {
+ if (it != enum_def.Vals().begin()) { code += '\n'; }
+ GenDocComment(ev.doc_comment, code_ptr, " ");
+ }
+
+ // Generate mapping between EnumName: EnumValue(int)
+ if (reverse) {
+ code += " '" + enum_def.ToString(ev) + "'";
+ code += " = ";
+ code += "'" + ev.name + "'";
+ } else {
+ code += " " + ev.name;
+ code += " = ";
+ code += enum_def.ToString(ev);
+ }
+
+ code += (it + 1) != enum_def.Vals().end() ? ",\n" : "\n";
+ }
+ code += "}";
+
+ if (enum_def.is_union) {
+ code += GenUnionConvFunc(enum_def.underlying_type, imports);
+ }
+
+ code += "\n\n";
+ }
+
+ static std::string GenType(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_BOOL:
+ case BASE_TYPE_CHAR: return "Int8";
+ case BASE_TYPE_UTYPE:
+ case BASE_TYPE_UCHAR: return "Uint8";
+ case BASE_TYPE_SHORT: return "Int16";
+ case BASE_TYPE_USHORT: return "Uint16";
+ case BASE_TYPE_INT: return "Int32";
+ case BASE_TYPE_UINT: return "Uint32";
+ case BASE_TYPE_LONG: return "Int64";
+ case BASE_TYPE_ULONG: return "Uint64";
+ case BASE_TYPE_FLOAT: return "Float32";
+ case BASE_TYPE_DOUBLE: return "Float64";
+ case BASE_TYPE_STRING: return "String";
+ case BASE_TYPE_VECTOR: return GenType(type.VectorType());
+ case BASE_TYPE_STRUCT: return type.struct_def->name;
+ default: return "flatbuffers.Table";
+ }
+ }
+
+ std::string GenGetter(const Type &type, const std::string &arguments) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return GenBBAccess() + ".__string" + arguments;
+ case BASE_TYPE_STRUCT: return GenBBAccess() + ".__struct" + arguments;
+ case BASE_TYPE_UNION:
+ if (!UnionHasStringType(*type.enum_def)) {
+ return GenBBAccess() + ".__union" + arguments;
+ }
+ return GenBBAccess() + ".__union_with_string" + arguments;
+ case BASE_TYPE_VECTOR: return GenGetter(type.VectorType(), arguments);
+ default: {
+ auto getter =
+ GenBBAccess() + ".read" + MakeCamel(GenType(type)) + arguments;
+ if (type.base_type == BASE_TYPE_BOOL) { getter = "!!" + getter; }
+ return getter;
+ }
+ }
+ }
+
+ std::string GenBBAccess() const { return "this.bb!"; }
+
+ std::string GenDefaultValue(const FieldDef &field, const std::string &context,
+ import_set &imports) {
+ if (field.IsScalarOptional()) { return "null"; }
+
+ const auto &value = field.value;
+ if (value.type.enum_def && value.type.base_type != BASE_TYPE_UNION &&
+ value.type.base_type != BASE_TYPE_VECTOR) {
+ if (auto val = value.type.enum_def->FindByValue(value.constant)) {
+ return AddImport(imports, *value.type.enum_def, *value.type.enum_def) +
+ "." + val->name;
+ } else {
+ return value.constant;
+ }
+ }
+
+ switch (value.type.base_type) {
+ case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true";
+
+ case BASE_TYPE_STRING:
+ case BASE_TYPE_UNION:
+ case BASE_TYPE_STRUCT: {
+ return "null";
+ }
+
+ case BASE_TYPE_VECTOR: return "[]";
+
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG: {
+ int64_t constant = StringToInt(value.constant.c_str());
+ std::string createLong = context + ".createLong";
+ return createLong + "(" + NumToString(static_cast<int32_t>(constant)) +
+ ", " + NumToString(static_cast<int32_t>(constant >> 32)) + ")";
+ }
+
+ default: return value.constant;
+ }
+ }
+
+ std::string GenTypeName(import_set &imports, const Definition &owner,
+ const Type &type, bool input,
+ bool allowNull = false) {
+ if (!input) {
+ if (IsString(type) || type.base_type == BASE_TYPE_STRUCT) {
+ std::string name;
+ if (IsString(type)) {
+ name = "string|Uint8Array";
+ } else {
+ name = AddImport(imports, owner, *type.struct_def);
+ }
+ return allowNull ? (name + "|null") : name;
+ }
+ }
+
+ switch (type.base_type) {
+ case BASE_TYPE_BOOL: return allowNull ? "boolean|null" : "boolean";
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG:
+ return allowNull ? "flatbuffers.Long|null" : "flatbuffers.Long";
+ default:
+ if (IsScalar(type.base_type)) {
+ if (type.enum_def) {
+ const auto enum_name = AddImport(imports, owner, *type.enum_def);
+ return allowNull ? (enum_name + "|null") : enum_name;
+ }
+ return allowNull ? "number|null" : "number";
+ }
+ return "flatbuffers.Offset";
+ }
+ }
+
+ // Returns the method name for use with add/put calls.
+ static std::string GenWriteMethod(const Type &type) {
+ // Forward to signed versions since unsigned versions don't exist
+ switch (type.base_type) {
+ case BASE_TYPE_UTYPE:
+ case BASE_TYPE_UCHAR: return GenWriteMethod(Type(BASE_TYPE_CHAR));
+ case BASE_TYPE_USHORT: return GenWriteMethod(Type(BASE_TYPE_SHORT));
+ case BASE_TYPE_UINT: return GenWriteMethod(Type(BASE_TYPE_INT));
+ case BASE_TYPE_ULONG: return GenWriteMethod(Type(BASE_TYPE_LONG));
+ default: break;
+ }
+
+ return IsScalar(type.base_type) ? MakeCamel(GenType(type))
+ : (IsStruct(type) ? "Struct" : "Offset");
+ }
+
+ template<typename T> static std::string MaybeAdd(T value) {
+ return value != 0 ? " + " + NumToString(value) : "";
+ }
+
+ template<typename T> static std::string MaybeScale(T value) {
+ return value != 1 ? " * " + NumToString(value) : "";
+ }
+
+ void GenStructArgs(import_set &imports, const StructDef &struct_def,
+ std::string *arguments, const std::string &nameprefix) {
+ 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(imports, *field.value.type.struct_def, arguments,
+ nameprefix + field.name + "_");
+ } else {
+ *arguments +=
+ ", " + nameprefix + field.name + ": " +
+ GenTypeName(imports, field, field.value.type, true, field.IsOptional());
+ }
+ }
+ }
+
+ static void GenStructBody(const StructDef &struct_def, std::string *body,
+ const std::string &nameprefix) {
+ *body += " builder.prep(";
+ *body += NumToString(struct_def.minalign) + ", ";
+ *body += NumToString(struct_def.bytesize) + ");\n";
+
+ for (auto it = struct_def.fields.vec.rbegin();
+ it != struct_def.fields.vec.rend(); ++it) {
+ auto &field = **it;
+ if (field.padding) {
+ *body += " builder.pad(" + NumToString(field.padding) + ");\n";
+ }
+ 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.
+ GenStructBody(*field.value.type.struct_def, body,
+ nameprefix + field.name + "_");
+ } else {
+ *body += " builder.write" + GenWriteMethod(field.value.type) + "(";
+ if (field.value.type.base_type == BASE_TYPE_BOOL) { *body += "+"; }
+ *body += nameprefix + field.name + ");\n";
+ }
+ }
+ }
+
+ std::string GenerateNewExpression(const std::string &object_name) {
+ return "new " + object_name + "()";
+ }
+
+ void GenerateRootAccessor(StructDef &struct_def, std::string *code_ptr,
+ std::string &code, const std::string &object_name,
+ bool size_prefixed) {
+ if (!struct_def.fixed) {
+ GenDocComment(code_ptr);
+ std::string sizePrefixed("SizePrefixed");
+ code += "static get" + (size_prefixed ? sizePrefixed : "") + "Root" +
+ GetPrefixedName(struct_def, "As");
+ code += "(bb:flatbuffers.ByteBuffer, obj?:" + object_name +
+ "):" + object_name + " {\n";
+ if (size_prefixed) {
+ code +=
+ " bb.setPosition(bb.position() + "
+ "flatbuffers.SIZE_PREFIX_LENGTH);\n";
+ }
+ code += " return (obj || " + GenerateNewExpression(object_name);
+ code += ").__init(bb.readInt32(bb.position()) + bb.position(), bb);\n";
+ code += "}\n\n";
+ }
+ }
+
+ void GenerateFinisher(StructDef &struct_def, std::string *code_ptr,
+ std::string &code, bool size_prefixed) {
+ if (parser_.root_struct_def_ == &struct_def) {
+ std::string sizePrefixed("SizePrefixed");
+ GenDocComment(code_ptr);
+
+ code += "static finish" + (size_prefixed ? sizePrefixed : "") +
+ GetPrefixedName(struct_def) + "Buffer";
+ code += "(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {\n";
+ code += " builder.finish(offset";
+ if (!parser_.file_identifier_.empty()) {
+ code += ", '" + parser_.file_identifier_ + "'";
+ }
+ if (size_prefixed) {
+ if (parser_.file_identifier_.empty()) { code += ", undefined"; }
+ code += ", true";
+ }
+ code += ");\n";
+ code += "}\n\n";
+ }
+ }
+
+ static std::string GetObjApiClassName(const StructDef &sd,
+ const IDLOptions &opts) {
+ return GetObjApiClassName(sd.name, opts);
+ }
+
+ static std::string GetObjApiClassName(const std::string &name,
+ const IDLOptions &opts) {
+ return opts.object_prefix + name + opts.object_suffix;
+ }
+
+ bool UnionHasStringType(const EnumDef &union_enum) {
+ return std::any_of(union_enum.Vals().begin(), union_enum.Vals().end(),
+ [](const EnumVal *ev) {
+ return !ev->IsZero() && IsString(ev->union_type);
+ });
+ }
+
+ std::string GenUnionGenericTypeTS(const EnumDef &union_enum) {
+ // TODO: make it work without any
+ // return std::string("T") + (UnionHasStringType(union_enum) ? "|string" :
+ // "");
+ return std::string("any") +
+ (UnionHasStringType(union_enum) ? "|string" : "");
+ }
+
+ std::string GenUnionTypeTS(const EnumDef &union_enum, import_set &imports) {
+ std::string ret;
+ std::set<std::string> type_list;
+
+ for (auto it = union_enum.Vals().begin(); it != union_enum.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ if (ev.IsZero()) { continue; }
+
+ std::string type = "";
+ if (IsString(ev.union_type)) {
+ type = "string"; // no need to wrap string type in namespace
+ } else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
+ type = AddImport(imports, union_enum, *ev.union_type.struct_def);
+ } else {
+ FLATBUFFERS_ASSERT(false);
+ }
+ type_list.insert(type);
+ }
+
+ for (auto it = type_list.begin(); it != type_list.end(); ++it) {
+ ret += *it + ((std::next(it) == type_list.end()) ? "" : "|");
+ }
+
+ return ret;
+ }
+
+ std::string AddImport(import_set &imports, const Definition &dependent,
+ const StructDef &dependency) {
+ std::string ns;
+ const auto &depc_comps = dependency.defined_namespace->components;
+ for (auto it = depc_comps.begin(); it != depc_comps.end(); it++) ns += *it;
+ std::string unique_name = ns + dependency.name;
+ std::string import_name = dependency.name;
+ std::string long_import_name;
+ if (imports.find(unique_name) != imports.end())
+ return imports.find(unique_name)->second.name;
+ for (auto it = imports.begin(); it != imports.end(); it++) {
+ if (it->second.name == import_name) {
+ long_import_name = ns + import_name;
+ break;
+ }
+ }
+ std::string import_statement;
+ import_statement += "import { ";
+ if (long_import_name.empty()) {
+ import_statement += import_name;
+ if (parser_.opts.generate_object_based_api)
+ import_statement += ", " + import_name + "T";
+ } else {
+ import_statement += dependency.name + " as " + long_import_name;
+ if (parser_.opts.generate_object_based_api)
+ import_statement +=
+ ", " + dependency.name + "T as " + long_import_name + "T";
+ }
+ import_statement += " } from '";
+ std::string file_name;
+ const auto &dep_comps = dependent.defined_namespace->components;
+ for (size_t i = 0; i < dep_comps.size(); i++)
+ file_name += i == 0 ? ".." : (kPathSeparator + std::string(".."));
+ if (dep_comps.size() == 0) file_name += ".";
+ for (auto it = depc_comps.begin(); it != depc_comps.end(); it++)
+ file_name += kPathSeparator + ToDasherizedCase(*it);
+ file_name += kPathSeparator + ToDasherizedCase(dependency.name);
+ import_statement += file_name + "';";
+ ImportDefinition import;
+ import.name = long_import_name.empty() ? import_name : long_import_name;
+ import.statement = import_statement;
+ import.dependency = &dependency;
+ import.dependent = &dependent;
+ imports.insert(std::make_pair(unique_name, import));
+ return import.name;
+ }
+
+ // TODO: largely (but not identical) duplicated code from above couln't find a
+ // good way to refactor
+ std::string AddImport(import_set &imports, const Definition &dependent,
+ const EnumDef &dependency) {
+ std::string ns;
+ const auto &depc_comps = dependency.defined_namespace->components;
+ for (auto it = depc_comps.begin(); it != depc_comps.end(); it++) ns += *it;
+ std::string unique_name = ns + dependency.name;
+ std::string import_name = dependency.name;
+ std::string long_import_name;
+ if (imports.find(unique_name) != imports.end())
+ return imports.find(unique_name)->second.name;
+ for (auto it = imports.begin(); it != imports.end(); it++) {
+ if (it->second.name == import_name) {
+ long_import_name = ns + import_name;
+ break;
+ }
+ }
+ std::string import_statement;
+ import_statement += "import { ";
+ if (long_import_name.empty())
+ import_statement += import_name;
+ else
+ import_statement += dependency.name + " as " + long_import_name;
+ if (dependency.is_union) {
+ import_statement += ", unionTo" + import_name;
+ import_statement += ", unionListTo" + import_name;
+ }
+ import_statement += " } from '";
+ std::string file_name;
+ const auto &dep_comps = dependent.defined_namespace->components;
+ for (size_t i = 0; i < dep_comps.size(); i++)
+ file_name += i == 0 ? ".." : (kPathSeparator + std::string(".."));
+ if (dep_comps.size() == 0) file_name += ".";
+ for (auto it = depc_comps.begin(); it != depc_comps.end(); it++)
+ file_name += kPathSeparator + ToDasherizedCase(*it);
+ file_name += kPathSeparator + ToDasherizedCase(dependency.name);
+ import_statement += file_name + "';";
+ ImportDefinition import;
+ import.name = long_import_name.empty() ? import_name : long_import_name;
+ import.statement = import_statement;
+ import.dependency = &dependency;
+ import.dependent = &dependent;
+ imports.insert(std::make_pair(unique_name, import));
+ return import.name;
+ }
+
+ void AddImport(import_set &imports, std::string import_name,
+ std::string fileName) {
+ ImportDefinition import;
+ import.name = import_name;
+ import.statement = "import " + import_name + " from '" + fileName + "';";
+ imports.insert(std::make_pair(import_name, import));
+ }
+
+ // Generate a TS union type based on a union's enum
+ std::string GenObjApiUnionTypeTS(import_set &imports, const IDLOptions &opts,
+ const EnumDef &union_enum) {
+ std::string ret = "";
+ std::set<std::string> type_list;
+
+ for (auto it = union_enum.Vals().begin(); it != union_enum.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ if (ev.IsZero()) { continue; }
+
+ std::string type = "";
+ if (IsString(ev.union_type)) {
+ type = "string"; // no need to wrap string type in namespace
+ } else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
+ type = GetObjApiClassName(
+ AddImport(imports, union_enum, *ev.union_type.struct_def), opts);
+ } else {
+ FLATBUFFERS_ASSERT(false);
+ }
+ type_list.insert(type);
+ }
+
+ size_t totalPrinted = 0;
+ for (auto it = type_list.begin(); it != type_list.end(); ++it) {
+ ++totalPrinted;
+ ret += *it + ((totalPrinted == type_list.size()) ? "" : "|");
+ }
+
+ return ret;
+ }
+
+ std::string GenUnionConvFuncName(const EnumDef &enum_def) {
+ return "unionTo" + enum_def.name;
+ }
+
+ std::string GenUnionListConvFuncName(const EnumDef &enum_def) {
+ return "unionListTo" + enum_def.name;
+ }
+
+ std::string GenUnionConvFunc(const Type &union_type, import_set &imports) {
+ if (union_type.enum_def) {
+ const auto &enum_def = *union_type.enum_def;
+
+ const auto valid_union_type = GenUnionTypeTS(enum_def, imports);
+ const auto valid_union_type_with_null = valid_union_type + "|null";
+
+ auto ret = "\n\nexport function " + GenUnionConvFuncName(enum_def) +
+ "(\n type: " + enum_def.name +
+ ",\n accessor: (obj:" + valid_union_type + ") => " +
+ valid_union_type_with_null +
+ "\n): " + valid_union_type_with_null + " {\n";
+
+ const auto enum_type = AddImport(imports, enum_def, enum_def);
+
+ const auto union_enum_loop = [&](const std::string &accessor_str) {
+ ret += " switch(" + enum_type + "[type]) {\n";
+ ret += " case 'NONE': return null; \n";
+
+ for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+ ++it) {
+ const auto &ev = **it;
+ if (ev.IsZero()) { continue; }
+
+ ret += " case '" + ev.name + "': ";
+
+ if (IsString(ev.union_type)) {
+ ret += "return " + accessor_str + "'') as string;";
+ } else if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
+ const auto type =
+ AddImport(imports, enum_def, *ev.union_type.struct_def);
+ ret += "return " + accessor_str + "new " + type + "())! as " +
+ type + ";";
+ } else {
+ FLATBUFFERS_ASSERT(false);
+ }
+ ret += "\n";
+ }
+
+ ret += " default: return null;\n";
+ ret += " }\n";
+ };
+
+ union_enum_loop("accessor(");
+ ret += "}";
+
+ ret += "\n\nexport function " + GenUnionListConvFuncName(enum_def) +
+ "(\n type: " + enum_def.name +
+ ", \n accessor: (index: number, obj:" + valid_union_type +
+ ") => " + valid_union_type_with_null +
+ ", \n index: number\n): " + valid_union_type_with_null + " {\n";
+ union_enum_loop("accessor(index, ");
+ ret += "}";
+
+ return ret;
+ }
+ FLATBUFFERS_ASSERT(0);
+ return "";
+ }
+
+ // Used for generating a short function that returns the correct class
+ // based on union enum type. Assume the context is inside the non object api
+ // type
+ std::string GenUnionValTS(import_set &imports, const std::string &field_name,
+ const Type &union_type,
+ const bool is_array = false) {
+ if (union_type.enum_def) {
+ const auto &enum_def = *union_type.enum_def;
+ const auto enum_type = AddImport(imports, enum_def, enum_def);
+ const std::string union_accessor = "this." + field_name;
+
+ const auto union_has_string = UnionHasStringType(enum_def);
+ const auto field_binded_method = "this." + field_name + ".bind(this)";
+
+ std::string ret;
+
+ if (!is_array) {
+ const auto conversion_function = GenUnionConvFuncName(enum_def);
+ const auto target_enum = "this." + field_name + "Type()";
+
+ ret = "(() => {\n";
+ ret += " let temp = " + conversion_function + "(" + target_enum +
+ ", " + field_binded_method + ");\n";
+ ret += " if(temp === null) { return null; }\n";
+ ret += union_has_string
+ ? " if(typeof temp === 'string') { return temp; }\n"
+ : "";
+ ret += " return temp.unpack()\n";
+ ret += " })()";
+ } else {
+ const auto conversion_function = GenUnionListConvFuncName(enum_def);
+ const auto target_enum_accesor = "this." + field_name + "Type";
+ const auto target_enum_length = target_enum_accesor + "Length()";
+
+ ret = "(() => {\n";
+ ret += " let ret = [];\n";
+ ret += " for(let targetEnumIndex = 0; targetEnumIndex < " +
+ target_enum_length +
+ "; "
+ "++targetEnumIndex) {\n";
+ ret += " let targetEnum = " + target_enum_accesor +
+ "(targetEnumIndex);\n";
+ ret += " if(targetEnum === null || " + enum_type +
+ "[targetEnum!] === 'NONE') { "
+ "continue; }\n\n";
+ ret += " let temp = " + conversion_function + "(targetEnum, " +
+ field_binded_method + ", targetEnumIndex);\n";
+ ret += " if(temp === null) { continue; }\n";
+ ret += union_has_string ? " if(typeof temp === 'string') { "
+ "ret.push(temp); continue; }\n"
+ : "";
+ ret += " ret.push(temp.unpack());\n";
+ ret += " }\n";
+ ret += " return ret;\n";
+ ret += " })()";
+ }
+
+ return ret;
+ }
+
+ FLATBUFFERS_ASSERT(0);
+ return "";
+ }
+
+ static std::string GenNullCheckConditional(
+ const std::string &nullCheckVar, const std::string &trueVal,
+ const std::string &falseVal = "null") {
+ return "(" + nullCheckVar + " !== null ? " + trueVal + " : " + falseVal +
+ ")";
+ }
+
+ std::string GenStructMemberValueTS(const StructDef &struct_def,
+ const std::string &prefix,
+ const std::string &delimiter,
+ const bool nullCheck = true) {
+ std::string ret;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+
+ const auto curr_member_accessor =
+ prefix + "." + MakeCamel(field.name, false);
+ if (IsStruct(field.value.type)) {
+ ret += GenStructMemberValueTS(*field.value.type.struct_def,
+ curr_member_accessor, delimiter);
+ } else {
+ if (nullCheck) {
+ ret +=
+ "(" + prefix + " === null ? 0 : " + curr_member_accessor + "!)";
+ } else {
+ ret += curr_member_accessor;
+ }
+ }
+
+ if (std::next(it) != struct_def.fields.vec.end()) { ret += delimiter; }
+ }
+
+ return ret;
+ }
+
+ void GenObjApi(const Parser &parser, StructDef &struct_def,
+ std::string &obj_api_unpack_func, std::string &obj_api_class,
+ import_set &imports) {
+ const auto class_name = GetObjApiClassName(struct_def, parser.opts);
+
+ std::string unpack_func = "\nunpack(): " + class_name +
+ " {\n return new " + class_name + "(" +
+ (struct_def.fields.vec.empty() ? "" : "\n");
+ std::string unpack_to_func = "\nunpackTo(_o: " + class_name + "): void {" +
+ +(struct_def.fields.vec.empty() ? "" : "\n");
+
+ std::string constructor_func = "constructor(";
+ constructor_func += (struct_def.fields.vec.empty() ? "" : "\n");
+
+ const auto has_create =
+ struct_def.fixed || CanCreateFactoryMethod(struct_def);
+
+ std::string pack_func_prototype =
+ "\npack(builder:flatbuffers.Builder): flatbuffers.Offset {\n";
+
+ std::string pack_func_offset_decl;
+ std::string pack_func_create_call;
+
+ const auto struct_name = AddImport(imports, struct_def, struct_def);
+
+ if (has_create) {
+ pack_func_create_call = " return " + struct_name + ".create" +
+ GetPrefixedName(struct_def) + "(builder" +
+ (struct_def.fields.vec.empty() ? "" : ",\n ");
+ } else {
+ pack_func_create_call = " " + struct_name + ".start" +
+ GetPrefixedName(struct_def) + "(builder);\n";
+ }
+
+ if (struct_def.fixed) {
+ // when packing struct, nested struct's members instead of the struct's
+ // offset are used
+ pack_func_create_call +=
+ GenStructMemberValueTS(struct_def, "this", ",\n ", false) + "\n ";
+ }
+
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+
+ const auto field_name = MakeCamel(field.name, false);
+ const std::string field_binded_method =
+ "this." + field_name + ".bind(this)";
+
+ std::string field_val;
+ std::string field_type;
+ // a string that declares a variable containing the
+ // offset for things that can't be generated inline
+ // empty otw
+ std::string field_offset_decl;
+ // a string that contains values for things that can be created inline or
+ // the variable name from field_offset_decl
+ std::string field_offset_val;
+ const auto field_default_val =
+ GenDefaultValue(field, "flatbuffers", imports);
+
+ // Emit a scalar field
+ const auto is_string = IsString(field.value.type);
+ if (IsScalar(field.value.type.base_type) || is_string) {
+ const auto has_null_default = is_string || HasNullDefault(field);
+
+ field_type += GenTypeName(imports, field, field.value.type, false,
+ has_null_default);
+ field_val = "this." + field_name + "()";
+
+ if (field.value.type.base_type != BASE_TYPE_STRING) {
+ field_offset_val = "this." + field_name;
+ } else {
+ field_offset_decl = GenNullCheckConditional(
+ "this." + field_name,
+ "builder.createString(this." + field_name + "!)", "0");
+ }
+ }
+
+ // Emit an object field
+ else {
+ auto is_vector = false;
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ const auto &sd = *field.value.type.struct_def;
+ field_type += GetObjApiClassName(sd, parser.opts);
+
+ const std::string field_accessor = "this." + field_name + "()";
+ field_val = GenNullCheckConditional(field_accessor,
+ field_accessor + "!.unpack()");
+ auto packing = GenNullCheckConditional(
+ "this." + field_name, "this." + field_name + "!.pack(builder)",
+ "0");
+
+ if (sd.fixed) {
+ field_offset_val = std::move(packing);
+ } else {
+ field_offset_decl = std::move(packing);
+ }
+
+ break;
+ }
+
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ auto vectortypename =
+ GenTypeName(imports, struct_def, vectortype, false);
+ is_vector = true;
+
+ field_type = "(";
+
+ switch (vectortype.base_type) {
+ case BASE_TYPE_STRUCT: {
+ const auto &sd = *field.value.type.struct_def;
+ field_type += GetObjApiClassName(sd, parser.opts);
+ field_type += ")[]";
+
+ field_val = GenBBAccess() + ".createObjList(" +
+ field_binded_method + ", this." + field_name +
+ "Length())";
+
+ if (sd.fixed) {
+ field_offset_decl =
+ "builder.createStructOffsetList(this." + field_name +
+ ", " + AddImport(imports, struct_def, struct_def) +
+ ".start" + MakeCamel(field_name) + "Vector)";
+ } else {
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def) + ".create" +
+ MakeCamel(field_name) +
+ "Vector(builder, builder.createObjectOffsetList(" +
+ "this." + field_name + "))";
+ }
+
+ break;
+ }
+
+ case BASE_TYPE_STRING: {
+ field_type += "string)[]";
+ field_val = GenBBAccess() + ".createScalarList(" +
+ field_binded_method + ", this." + field_name +
+ "Length())";
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def) + ".create" +
+ MakeCamel(field_name) +
+ "Vector(builder, builder.createObjectOffsetList(" +
+ "this." + field_name + "))";
+ break;
+ }
+
+ case BASE_TYPE_UNION: {
+ field_type += GenObjApiUnionTypeTS(imports, parser.opts,
+ *(vectortype.enum_def));
+ field_type += ")[]";
+ field_val =
+ GenUnionValTS(imports, field_name, vectortype, true);
+
+ field_offset_decl =
+ AddImport(imports, struct_def, struct_def) + ".create" +
+ MakeCamel(field_name) +
+ "Vector(builder, builder.createObjectOffsetList(" +
+ "this." + field_name + "))";
+
+ break;
+ }
+ default: {
+ if (vectortype.enum_def) {
+ field_type += GenTypeName(imports, struct_def, vectortype,
+ false, HasNullDefault(field));
+ } else {
+ field_type += vectortypename;
+ }
+ field_type += ")[]";
+ field_val = GenBBAccess() + ".createScalarList(" +
+ field_binded_method + ", this." + field_name +
+ "Length())";
+
+ field_offset_decl = AddImport(imports, struct_def, struct_def) +
+ ".create" + MakeCamel(field_name) +
+ "Vector(builder, this." + field_name + ")";
+
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case BASE_TYPE_UNION: {
+ field_type += GenObjApiUnionTypeTS(imports, parser.opts,
+ *(field.value.type.enum_def));
+
+ field_val = GenUnionValTS(imports, field_name, field.value.type);
+ field_offset_decl =
+ "builder.createObjectOffset(this." + field_name + ")";
+ break;
+ }
+
+ default: FLATBUFFERS_ASSERT(0); break;
+ }
+
+ // length 0 vector is simply empty instead of null
+ field_type += is_vector ? "" : "|null";
+ }
+
+ if (!field_offset_decl.empty()) {
+ field_offset_decl =
+ " const " + field_name + " = " + field_offset_decl + ";";
+ }
+ if (field_offset_val.empty()) { field_offset_val = field_name; }
+
+ unpack_func += " " + field_val;
+ unpack_to_func += " _o." + field_name + " = " + field_val + ";";
+
+ constructor_func += " public " + field_name + ": " + field_type + " = " +
+ field_default_val;
+
+ if (!struct_def.fixed) {
+ if (!field_offset_decl.empty()) {
+ pack_func_offset_decl += field_offset_decl + "\n";
+ }
+
+ if (has_create) {
+ pack_func_create_call += field_offset_val;
+ } else {
+ pack_func_create_call += " " + struct_name + ".add" +
+ MakeCamel(field.name) + "(builder, " +
+ field_offset_val + ");\n";
+ }
+ }
+
+ if (std::next(it) != struct_def.fields.vec.end()) {
+ constructor_func += ",\n";
+
+ if (!struct_def.fixed && has_create) {
+ pack_func_create_call += ",\n ";
+ }
+
+ unpack_func += ",\n";
+ unpack_to_func += "\n";
+ } else {
+ constructor_func += "\n";
+ if (!struct_def.fixed) {
+ pack_func_offset_decl += (pack_func_offset_decl.empty() ? "" : "\n");
+ pack_func_create_call += "\n ";
+ }
+
+ unpack_func += "\n ";
+ unpack_to_func += "\n";
+ }
+ }
+
+ constructor_func += "){}\n\n";
+
+ if (has_create) {
+ pack_func_create_call += ");";
+ } else {
+ pack_func_create_call += "return " + struct_name + ".end" +
+ GetPrefixedName(struct_def) + "(builder);";
+ }
+
+ obj_api_class = "\nexport class " +
+ GetObjApiClassName(struct_def, parser.opts) + " {\n";
+
+ obj_api_class += constructor_func;
+ obj_api_class += pack_func_prototype + pack_func_offset_decl +
+ pack_func_create_call + "\n}";
+
+ obj_api_class += "\n}\n";
+
+ unpack_func += ");\n}";
+ unpack_to_func += "}\n";
+
+ obj_api_unpack_func = unpack_func + "\n\n" + unpack_to_func;
+ }
+
+ static bool CanCreateFactoryMethod(const StructDef &struct_def) {
+ // to preserve backwards compatibility, we allow the first field to be a
+ // struct
+ return struct_def.fields.vec.size() < 2 ||
+ std::all_of(std::begin(struct_def.fields.vec) + 1,
+ std::end(struct_def.fields.vec),
+ [](const FieldDef *f) -> bool {
+ FLATBUFFERS_ASSERT(f != nullptr);
+ return f->value.type.base_type != BASE_TYPE_STRUCT;
+ });
+ }
+
+ // Generate an accessor struct with constructor for a flatbuffers struct.
+ void GenStruct(const Parser &parser, StructDef &struct_def,
+ std::string *code_ptr, import_set &imports) {
+ if (struct_def.generated) return;
+ std::string &code = *code_ptr;
+
+ std::string object_name;
+ std::string object_namespace = GetNameSpace(struct_def);
+
+ // Emit constructor
+ object_name = struct_def.name;
+ GenDocComment(struct_def.doc_comment, code_ptr);
+ code += "export class " + struct_def.name;
+ code += " {\n";
+ code += " bb: flatbuffers.ByteBuffer|null = null;\n";
+ code += " bb_pos = 0;\n";
+
+ // Generate the __init method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ code +=
+ "__init(i:number, bb:flatbuffers.ByteBuffer):" + object_name + " {\n";
+ code += " this.bb_pos = i;\n";
+ code += " this.bb = bb;\n";
+ code += " return this;\n";
+ code += "}\n\n";
+
+ // Generate special accessors for the table that when used as the root of a
+ // FlatBuffer
+ GenerateRootAccessor(struct_def, code_ptr, code, object_name, false);
+ GenerateRootAccessor(struct_def, code_ptr, code, object_name, true);
+
+ // Generate the identifier check method
+ if (!struct_def.fixed && parser_.root_struct_def_ == &struct_def &&
+ !parser_.file_identifier_.empty()) {
+ GenDocComment(code_ptr);
+ code +=
+ "static bufferHasIdentifier(bb:flatbuffers.ByteBuffer):boolean "
+ "{\n";
+ code += " return bb.__has_identifier('" + parser_.file_identifier_;
+ code += "');\n}\n\n";
+ }
+
+ // Emit field accessors
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ auto offset_prefix =
+ " const offset = " + GenBBAccess() + ".__offset(this.bb_pos, " +
+ NumToString(field.value.offset) + ");\n return offset ? ";
+
+ // Emit a scalar field
+ const auto is_string = IsString(field.value.type);
+ if (IsScalar(field.value.type.base_type) || is_string) {
+ const auto has_null_default = is_string || HasNullDefault(field);
+
+ GenDocComment(field.doc_comment, code_ptr);
+ std::string prefix = MakeCamel(field.name, false) + "(";
+ if (is_string) {
+ code += prefix + "):string|null\n";
+ code +=
+ prefix + "optionalEncoding:flatbuffers.Encoding" + "):" +
+ GenTypeName(imports, struct_def, field.value.type, false, true) +
+ "\n";
+ code += prefix + "optionalEncoding?:any";
+ } else {
+ code += prefix;
+ }
+ if (field.value.type.enum_def) {
+ code += "):" +
+ GenTypeName(imports, struct_def, field.value.type, false,
+ field.IsOptional()) +
+ " {\n";
+ } else {
+ code += "):" +
+ GenTypeName(imports, struct_def, field.value.type, false,
+ has_null_default) +
+ " {\n";
+ }
+
+ if (struct_def.fixed) {
+ code +=
+ " return " +
+ GenGetter(field.value.type,
+ "(this.bb_pos" + MaybeAdd(field.value.offset) + ")") +
+ ";\n";
+ } else {
+ std::string index = "this.bb_pos + offset";
+ if (is_string) { index += ", optionalEncoding"; }
+ code += offset_prefix +
+ GenGetter(field.value.type, "(" + index + ")") + " : " +
+ GenDefaultValue(field, GenBBAccess(), imports);
+ code += ";\n";
+ }
+ }
+
+ // Emit an object field
+ else {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT: {
+ const auto type =
+ AddImport(imports, struct_def, *field.value.type.struct_def);
+ GenDocComment(field.doc_comment, code_ptr);
+ code += MakeCamel(field.name, false);
+ code += "(obj?:" + type + "):" + type + "|null {\n";
+
+ if (struct_def.fixed) {
+ code += " return (obj || " + GenerateNewExpression(type);
+ code += ").__init(this.bb_pos";
+ code +=
+ MaybeAdd(field.value.offset) + ", " + GenBBAccess() + ");\n";
+ } else {
+ code += offset_prefix + "(obj || " + GenerateNewExpression(type) +
+ ").__init(";
+ code += field.value.type.struct_def->fixed
+ ? "this.bb_pos + offset"
+ : GenBBAccess() + ".__indirect(this.bb_pos + offset)";
+ code += ", " + GenBBAccess() + ") : null;\n";
+ }
+
+ break;
+ }
+
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ auto vectortypename =
+ GenTypeName(imports, struct_def, vectortype, false);
+ auto inline_size = InlineSize(vectortype);
+ auto index = GenBBAccess() +
+ ".__vector(this.bb_pos + offset) + index" +
+ MaybeScale(inline_size);
+ std::string ret_type;
+ bool is_union = false;
+ switch (vectortype.base_type) {
+ case BASE_TYPE_STRUCT: ret_type = vectortypename; break;
+ case BASE_TYPE_STRING: ret_type = vectortypename; break;
+ case BASE_TYPE_UNION:
+ ret_type = "?flatbuffers.Table";
+ is_union = true;
+ break;
+ default: ret_type = vectortypename;
+ }
+ GenDocComment(field.doc_comment, code_ptr);
+ std::string prefix = MakeCamel(field.name, false);
+ // TODO: make it work without any
+ // if (is_union) { prefix += "<T extends flatbuffers.Table>"; }
+ if (is_union) { prefix += ""; }
+ prefix += "(index: number";
+ if (is_union) {
+ const auto union_type =
+ GenUnionGenericTypeTS(*(field.value.type.enum_def));
+
+ vectortypename = union_type;
+ code += prefix + ", obj:" + union_type;
+ } else if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ code += prefix + ", obj?:" + vectortypename;
+ } else if (IsString(vectortype)) {
+ code += prefix + "):string\n";
+ code += prefix + ",optionalEncoding:flatbuffers.Encoding" +
+ "):" + vectortypename + "\n";
+ code += prefix + ",optionalEncoding?:any";
+ } else {
+ code += prefix;
+ }
+ code += "):" + vectortypename + "|null {\n";
+
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ code += offset_prefix + "(obj || " +
+ GenerateNewExpression(vectortypename);
+ code += ").__init(";
+ code += vectortype.struct_def->fixed
+ ? index
+ : GenBBAccess() + ".__indirect(" + index + ")";
+ code += ", " + GenBBAccess() + ")";
+ } else {
+ if (is_union) {
+ index = "obj, " + index;
+ } else if (IsString(vectortype)) {
+ index += ", optionalEncoding";
+ }
+ code += offset_prefix + GenGetter(vectortype, "(" + index + ")");
+ }
+ code += " : ";
+ if (field.value.type.element == BASE_TYPE_BOOL) {
+ code += "false";
+ } else if (field.value.type.element == BASE_TYPE_LONG ||
+ field.value.type.element == BASE_TYPE_ULONG) {
+ code += GenBBAccess() + ".createLong(0, 0)";
+ } else if (IsScalar(field.value.type.element)) {
+ if (field.value.type.enum_def) {
+ code += field.value.constant;
+ } else {
+ code += "0";
+ }
+ } else {
+ code += "null";
+ }
+ code += ";\n";
+ break;
+ }
+
+ case BASE_TYPE_UNION: {
+ GenDocComment(field.doc_comment, code_ptr);
+ code += MakeCamel(field.name, false);
+
+ const auto &union_enum = *(field.value.type.enum_def);
+ const auto union_type = GenUnionGenericTypeTS(union_enum);
+ code += "<T extends flatbuffers.Table>(obj:" + union_type +
+ "):" + union_type +
+ "|null "
+ "{\n";
+
+ code += offset_prefix +
+ GenGetter(field.value.type, "(obj, this.bb_pos + offset)") +
+ " : null;\n";
+ break;
+ }
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+ code += "}\n\n";
+
+ // Adds the mutable scalar value to the output
+ if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer &&
+ !IsUnion(field.value.type)) {
+ std::string type =
+ GenTypeName(imports, struct_def, field.value.type, true);
+
+ code += "mutate_" + field.name + "(value:" + type + "):boolean {\n";
+
+ if (struct_def.fixed) {
+ code += " " + GenBBAccess() + ".write" +
+ MakeCamel(GenType(field.value.type)) + "(this.bb_pos + " +
+ NumToString(field.value.offset) + ", ";
+ } else {
+ code += " const offset = " + GenBBAccess() +
+ ".__offset(this.bb_pos, " + NumToString(field.value.offset) +
+ ");\n\n";
+ code += " if (offset === 0) {\n";
+ code += " return false;\n";
+ code += " }\n\n";
+
+ // special case for bools, which are treated as uint8
+ code += " " + GenBBAccess() + ".write" +
+ MakeCamel(GenType(field.value.type)) +
+ "(this.bb_pos + offset, ";
+ if (field.value.type.base_type == BASE_TYPE_BOOL) { code += "+"; }
+ }
+
+ code += "value);\n";
+ code += " return true;\n";
+ code += "}\n\n";
+ }
+
+ // Emit vector helpers
+ if (IsVector(field.value.type)) {
+ // Emit a length helper
+ GenDocComment(code_ptr);
+ code += MakeCamel(field.name, false);
+ code += "Length():number {\n" + offset_prefix;
+
+ code +=
+ GenBBAccess() + ".__vector_len(this.bb_pos + offset) : 0;\n}\n\n";
+
+ // For scalar types, emit a typed array helper
+ auto vectorType = field.value.type.VectorType();
+ if (IsScalar(vectorType.base_type) && !IsLong(vectorType.base_type)) {
+ GenDocComment(code_ptr);
+
+ code += MakeCamel(field.name, false);
+ code += "Array():" + GenType(vectorType) + "Array|null {\n" +
+ offset_prefix;
+
+ code += "new " + GenType(vectorType) + "Array(" + GenBBAccess() +
+ ".bytes().buffer, " + GenBBAccess() +
+ ".bytes().byteOffset + " + GenBBAccess() +
+ ".__vector(this.bb_pos + offset), " + GenBBAccess() +
+ ".__vector_len(this.bb_pos + offset)) : null;\n}\n\n";
+ }
+ }
+ }
+
+ // Emit the fully qualified name
+ if (parser_.opts.generate_name_strings) {
+ GenDocComment(code_ptr);
+ code += "static getFullyQualifiedName():string {\n";
+ code += " return '" + WrapInNameSpace(struct_def) + "';\n";
+ code += "}\n\n";
+ }
+
+ // Emit the size of the struct.
+ if (struct_def.fixed) {
+ GenDocComment(code_ptr);
+ code += "static sizeOf():number {\n";
+ code += " return " + NumToString(struct_def.bytesize) + ";\n";
+ code += "}\n\n";
+ }
+
+ // Emit a factory constructor
+ if (struct_def.fixed) {
+ std::string arguments;
+ GenStructArgs(imports, struct_def, &arguments, "");
+ GenDocComment(code_ptr);
+
+ code += "static create" + GetPrefixedName(struct_def) +
+ "(builder:flatbuffers.Builder";
+ code += arguments + "):flatbuffers.Offset {\n";
+
+ GenStructBody(struct_def, &code, "");
+ code += " return builder.offset();\n}\n\n";
+ } else {
+ // Generate a method to start building a new object
+ GenDocComment(code_ptr);
+
+ code += "static start" + GetPrefixedName(struct_def) +
+ "(builder:flatbuffers.Builder) {\n";
+
+ code += " builder.startObject(" +
+ NumToString(struct_def.fields.vec.size()) + ");\n";
+ code += "}\n\n";
+
+ // Generate a set of static methods that allow table construction
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (field.deprecated) continue;
+ const auto argname = GetArgName(field);
+
+ // Generate the field insertion method
+ GenDocComment(code_ptr);
+ code += "static add" + MakeCamel(field.name);
+ code += "(builder:flatbuffers.Builder, " + argname + ":" +
+ GetArgType(imports, struct_def, field, false) + ") {\n";
+ code += " builder.addField" + GenWriteMethod(field.value.type) + "(";
+ code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
+ if (field.value.type.base_type == BASE_TYPE_BOOL) { code += "+"; }
+ code += argname + ", ";
+ if (!IsScalar(field.value.type.base_type)) {
+ code += "0";
+ } else if (HasNullDefault(field)) {
+ if (IsLong(field.value.type.base_type)) {
+ code += "builder.createLong(0, 0)";
+ } else {
+ code += "0";
+ }
+ } else {
+ if (field.value.type.base_type == BASE_TYPE_BOOL) { code += "+"; }
+ code += GenDefaultValue(field, "builder", imports);
+ }
+ code += ");\n}\n\n";
+
+ if (IsVector(field.value.type)) {
+ auto vector_type = field.value.type.VectorType();
+ auto alignment = InlineAlignment(vector_type);
+ auto elem_size = InlineSize(vector_type);
+
+ // Generate a method to create a vector from a JavaScript array
+ if (!IsStruct(vector_type)) {
+ GenDocComment(code_ptr);
+
+ const std::string sig_begin =
+ "static create" + MakeCamel(field.name) +
+ "Vector(builder:flatbuffers.Builder, data:";
+ const std::string sig_end = "):flatbuffers.Offset";
+ std::string type =
+ GenTypeName(imports, struct_def, vector_type, true) + "[]";
+ if (type == "number[]") {
+ const auto &array_type = GenType(vector_type);
+ // the old type should be deprecated in the future
+ std::string type_old = "number[]|Uint8Array";
+ std::string type_new = "number[]|" + array_type + "Array";
+ if (type_old == type_new) {
+ type = type_new;
+ } else {
+ // add function overloads
+ code += sig_begin + type_new + sig_end + ";\n";
+ code +=
+ "/**\n * @deprecated This Uint8Array overload will "
+ "be removed in the future.\n */\n";
+ code += sig_begin + type_old + sig_end + ";\n";
+ type = type_new + "|Uint8Array";
+ }
+ }
+ code += sig_begin + type + sig_end + " {\n";
+ code += " builder.startVector(" + NumToString(elem_size);
+ code += ", data.length, " + NumToString(alignment) + ");\n";
+ code += " for (let i = data.length - 1; i >= 0; i--) {\n";
+ code += " builder.add" + GenWriteMethod(vector_type) + "(";
+ if (vector_type.base_type == BASE_TYPE_BOOL) { code += "+"; }
+ code += "data[i]!);\n";
+ code += " }\n";
+ code += " return builder.endVector();\n";
+ code += "}\n\n";
+ }
+
+ // Generate a method to start a vector, data to be added manually
+ // after
+ GenDocComment(code_ptr);
+
+ code += "static start" + MakeCamel(field.name);
+ code += "Vector(builder:flatbuffers.Builder, numElems:number) {\n";
+ code += " builder.startVector(" + NumToString(elem_size);
+ code += ", numElems, " + NumToString(alignment) + ");\n";
+ code += "}\n\n";
+ }
+ }
+
+ // Generate a method to stop building a new object
+ GenDocComment(code_ptr);
+
+ code += "static end" + GetPrefixedName(struct_def);
+ code += "(builder:flatbuffers.Builder):flatbuffers.Offset {\n";
+
+ code += " const offset = builder.endObject();\n";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ auto &field = **it;
+ if (!field.deprecated && field.IsRequired()) {
+ code += " builder.requiredField(offset, ";
+ code += NumToString(field.value.offset);
+ code += ") // " + field.name + "\n";
+ }
+ }
+ code += " return offset;\n";
+ code += "}\n\n";
+
+ // Generate the methods to complete buffer construction
+ GenerateFinisher(struct_def, code_ptr, code, false);
+ GenerateFinisher(struct_def, code_ptr, code, true);
+
+ // Generate a convenient CreateX function
+ if (CanCreateFactoryMethod(struct_def)) {
+ code += "static create" + GetPrefixedName(struct_def);
+ code += "(builder:flatbuffers.Builder";
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) continue;
+ code += ", " + GetArgName(field) + ":" +
+ GetArgType(imports, struct_def, field, true);
+ }
+
+ code += "):flatbuffers.Offset {\n";
+ code += " " + struct_def.name + ".start" +
+ GetPrefixedName(struct_def) + "(builder);\n";
+
+ std::string methodPrefix = struct_def.name;
+ for (auto it = struct_def.fields.vec.begin();
+ it != struct_def.fields.vec.end(); ++it) {
+ const auto &field = **it;
+ if (field.deprecated) continue;
+
+ const auto arg_name = GetArgName(field);
+
+ if (field.IsScalarOptional()) {
+ code += " if (" + arg_name + " !== null)\n ";
+ }
+
+ code += " " + methodPrefix + ".add" + MakeCamel(field.name) + "(";
+ code += "builder, " + arg_name + ");\n";
+ }
+
+ code += " return " + methodPrefix + ".end" +
+ GetPrefixedName(struct_def) + "(builder);\n";
+ code += "}\n";
+ }
+ }
+
+ if (!struct_def.fixed && parser_.services_.vec.size() != 0) {
+ auto name = GetPrefixedName(struct_def, "");
+ code += "\n";
+ code += "serialize():Uint8Array {\n";
+ code += " return this.bb!.bytes();\n";
+ code += "}\n";
+
+ code += "\n";
+ code += "static deserialize(buffer: Uint8Array):" + name + " {\n";
+ code += " return " + AddImport(imports, struct_def, struct_def) +
+ ".getRootAs" + name + "(new flatbuffers.ByteBuffer(buffer))\n";
+ code += "}\n";
+ }
+
+ if (parser_.opts.generate_object_based_api) {
+ std::string obj_api_class;
+ std::string obj_api_unpack_func;
+ GenObjApi(parser_, struct_def, obj_api_unpack_func, obj_api_class,
+ imports);
+
+ code += obj_api_unpack_func + "}\n" + obj_api_class;
+ } else {
+ code += "}\n";
+ }
+ }
+
+ static bool HasNullDefault(const FieldDef &field) {
+ return field.IsOptional() && field.value.constant == "null";
+ }
+
+ std::string GetArgType(import_set &imports, const Definition &owner,
+ const FieldDef &field, bool allowNull) {
+ return GenTypeName(imports, owner, field.value.type, true,
+ allowNull && field.IsOptional());
+ }
+
+ static std::string GetArgName(const FieldDef &field) {
+ auto argname = MakeCamel(field.name, false);
+ if (!IsScalar(field.value.type.base_type)) { argname += "Offset"; }
+
+ return argname;
+ }
+
+ std::string GetPrefixedName(const StructDef &struct_def,
+ const char *prefix = "") {
+ return prefix + struct_def.name;
+ }
+}; // namespace ts
+} // namespace ts
+
+bool GenerateTS(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ ts::TsGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+
+std::string TSMakeRule(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ FLATBUFFERS_ASSERT(parser.opts.lang <= IDLOptions::kMAX);
+
+ std::string filebase =
+ flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
+ ts::TsGenerator generator(parser, path, file_name);
+ std::string make_rule =
+ generator.GeneratedFileName(path, filebase, parser.opts) + ": ";
+
+ auto included_files = parser.GetIncludedFilesRecursive(file_name);
+ for (auto it = included_files.begin(); it != included_files.end(); ++it) {
+ make_rule += " " + *it;
+ }
+ return make_rule;
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/idl_parser.cpp b/contrib/libs/flatbuffers/src/idl_parser.cpp
new file mode 100644
index 0000000000..ad642d79a9
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/idl_parser.cpp
@@ -0,0 +1,3986 @@
+/*
+ * 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.
+ */
+
+#include <algorithm>
+#include <cmath>
+#include <list>
+#include <string>
+#include <utility>
+
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace flatbuffers {
+
+// Reflects the version at the compiling time of binary(lib/dll/so).
+const char *FLATBUFFERS_VERSION() {
+ // clang-format off
+ return
+ FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
+ FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
+ FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
+ // clang-format on
+}
+
+const double kPi = 3.14159265358979323846;
+
+// clang-format off
+const char *const kTypeNames[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
+ IDLTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ nullptr
+};
+
+const char kTypeSizes[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ sizeof(CTYPE),
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+};
+// clang-format on
+
+// The enums in the reflection schema should match the ones we use internally.
+// Compare the last element to check if these go out of sync.
+static_assert(BASE_TYPE_UNION == static_cast<BaseType>(reflection::Union),
+ "enums don't match");
+
+// Any parsing calls have to be wrapped in this macro, which automates
+// handling of recursive error checking a bit. It will check the received
+// CheckedError object, and return straight away on error.
+#define ECHECK(call) \
+ { \
+ auto ce = (call); \
+ if (ce.Check()) return ce; \
+ }
+
+// These two functions are called hundreds of times below, so define a short
+// form:
+#define NEXT() ECHECK(Next())
+#define EXPECT(tok) ECHECK(Expect(tok))
+
+static bool ValidateUTF8(const std::string &str) {
+ const char *s = &str[0];
+ const char *const sEnd = s + str.length();
+ while (s < sEnd) {
+ if (FromUTF8(&s) < 0) { return false; }
+ }
+ return true;
+}
+
+static bool IsLowerSnakeCase(const std::string &str) {
+ for (size_t i = 0; i < str.length(); i++) {
+ char c = str[i];
+ if (!check_ascii_range(c, 'a', 'z') && !is_digit(c) && c != '_') {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Convert an underscore_based_identifier in to camelCase.
+// Also uppercases the first character if first is true.
+std::string MakeCamel(const std::string &in, bool first) {
+ std::string s;
+ for (size_t i = 0; i < in.length(); i++) {
+ if (!i && first)
+ s += CharToUpper(in[0]);
+ else if (in[i] == '_' && i + 1 < in.length())
+ s += CharToUpper(in[++i]);
+ else
+ s += in[i];
+ }
+ return s;
+}
+
+// Convert an underscore_based_identifier in to screaming snake case.
+std::string MakeScreamingCamel(const std::string &in) {
+ std::string s;
+ for (size_t i = 0; i < in.length(); i++) {
+ if (in[i] != '_')
+ s += CharToUpper(in[i]);
+ else
+ s += in[i];
+ }
+ return s;
+}
+
+void DeserializeDoc(std::vector<std::string> &doc,
+ const Vector<Offset<String>> *documentation) {
+ if (documentation == nullptr) return;
+ for (uoffset_t index = 0; index < documentation->size(); index++)
+ doc.push_back(documentation->Get(index)->str());
+}
+
+void Parser::Message(const std::string &msg) {
+ if (!error_.empty()) error_ += "\n"; // log all warnings and errors
+ error_ += file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : "";
+ // clang-format off
+
+ #ifdef _WIN32 // MSVC alike
+ error_ +=
+ "(" + NumToString(line_) + ", " + NumToString(CursorPosition()) + ")";
+ #else // gcc alike
+ if (file_being_parsed_.length()) error_ += ":";
+ error_ += NumToString(line_) + ": " + NumToString(CursorPosition());
+ #endif
+ // clang-format on
+ error_ += ": " + msg;
+}
+
+void Parser::Warning(const std::string &msg) {
+ if (!opts.no_warnings) Message("warning: " + msg);
+}
+
+CheckedError Parser::Error(const std::string &msg) {
+ Message("error: " + msg);
+ return CheckedError(true);
+}
+
+inline CheckedError NoError() { return CheckedError(false); }
+
+CheckedError Parser::RecurseError() {
+ return Error("maximum parsing depth " + NumToString(parse_depth_counter_) +
+ " reached");
+}
+
+class Parser::ParseDepthGuard {
+ public:
+ explicit ParseDepthGuard(Parser *parser_not_null)
+ : parser_(*parser_not_null), caller_depth_(parser_.parse_depth_counter_) {
+ FLATBUFFERS_ASSERT(caller_depth_ <= (FLATBUFFERS_MAX_PARSING_DEPTH) &&
+ "Check() must be called to prevent stack overflow");
+ parser_.parse_depth_counter_ += 1;
+ }
+
+ ~ParseDepthGuard() { parser_.parse_depth_counter_ -= 1; }
+
+ CheckedError Check() {
+ return caller_depth_ >= (FLATBUFFERS_MAX_PARSING_DEPTH)
+ ? parser_.RecurseError()
+ : CheckedError(false);
+ }
+
+ FLATBUFFERS_DELETE_FUNC(ParseDepthGuard(const ParseDepthGuard &));
+ FLATBUFFERS_DELETE_FUNC(ParseDepthGuard &operator=(const ParseDepthGuard &));
+
+ private:
+ Parser &parser_;
+ const int caller_depth_;
+};
+
+template<typename T> std::string TypeToIntervalString() {
+ return "[" + NumToString((flatbuffers::numeric_limits<T>::lowest)()) + "; " +
+ NumToString((flatbuffers::numeric_limits<T>::max)()) + "]";
+}
+
+// atot: template version of atoi/atof: convert a string to an instance of T.
+template<typename T>
+bool atot_scalar(const char *s, T *val, bool_constant<false>) {
+ return StringToNumber(s, val);
+}
+
+template<typename T>
+bool atot_scalar(const char *s, T *val, bool_constant<true>) {
+ // Normalize NaN parsed from fbs or json to unsigned NaN.
+ if (false == StringToNumber(s, val)) return false;
+ *val = (*val != *val) ? std::fabs(*val) : *val;
+ return true;
+}
+
+template<typename T> CheckedError atot(const char *s, Parser &parser, T *val) {
+ auto done = atot_scalar(s, val, bool_constant<is_floating_point<T>::value>());
+ if (done) return NoError();
+ if (0 == *val)
+ return parser.Error("invalid number: \"" + std::string(s) + "\"");
+ else
+ return parser.Error("invalid number: \"" + std::string(s) + "\"" +
+ ", constant does not fit " + TypeToIntervalString<T>());
+}
+template<>
+inline CheckedError atot<Offset<void>>(const char *s, Parser &parser,
+ Offset<void> *val) {
+ (void)parser;
+ *val = Offset<void>(atoi(s));
+ return NoError();
+}
+
+std::string Namespace::GetFullyQualifiedName(const std::string &name,
+ size_t max_components) const {
+ // Early exit if we don't have a defined namespace.
+ if (components.empty() || !max_components) { return name; }
+ std::string stream_str;
+ for (size_t i = 0; i < std::min(components.size(), max_components); i++) {
+ stream_str += components[i];
+ stream_str += '.';
+ }
+ if (!stream_str.empty()) stream_str.pop_back();
+ if (name.length()) {
+ stream_str += '.';
+ stream_str += name;
+ }
+ return stream_str;
+}
+
+template<typename T>
+T *LookupTableByName(const SymbolTable<T> &table, const std::string &name,
+ const Namespace &current_namespace, size_t skip_top) {
+ const auto &components = current_namespace.components;
+ if (table.dict.empty()) return nullptr;
+ if (components.size() < skip_top) return nullptr;
+ const auto N = components.size() - skip_top;
+ std::string full_name;
+ for (size_t i = 0; i < N; i++) {
+ full_name += components[i];
+ full_name += '.';
+ }
+ for (size_t i = N; i > 0; i--) {
+ full_name += name;
+ auto obj = table.Lookup(full_name);
+ if (obj) return obj;
+ auto len = full_name.size() - components[i - 1].size() - 1 - name.size();
+ full_name.resize(len);
+ }
+ FLATBUFFERS_ASSERT(full_name.empty());
+ return table.Lookup(name); // lookup in global namespace
+}
+
+// Declare tokens we'll use. Single character tokens are represented by their
+// ascii character code (e.g. '{'), others above 256.
+// clang-format off
+#define FLATBUFFERS_GEN_TOKENS(TD) \
+ TD(Eof, 256, "end of file") \
+ TD(StringConstant, 257, "string constant") \
+ TD(IntegerConstant, 258, "integer constant") \
+ TD(FloatConstant, 259, "float constant") \
+ TD(Identifier, 260, "identifier")
+#ifdef __GNUC__
+__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
+#endif
+enum {
+ #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) kToken ## NAME = VALUE,
+ FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN)
+ #undef FLATBUFFERS_TOKEN
+};
+
+static std::string TokenToString(int t) {
+ static const char * const tokens[] = {
+ #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING,
+ FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN)
+ #undef FLATBUFFERS_TOKEN
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
+ IDLTYPE,
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ };
+ if (t < 256) { // A single ascii char token.
+ std::string s;
+ s.append(1, static_cast<char>(t));
+ return s;
+ } else { // Other tokens.
+ return tokens[t - 256];
+ }
+}
+// clang-format on
+
+std::string Parser::TokenToStringId(int t) const {
+ return t == kTokenIdentifier ? attribute_ : TokenToString(t);
+}
+
+// Parses exactly nibbles worth of hex digits into a number, or error.
+CheckedError Parser::ParseHexNum(int nibbles, uint64_t *val) {
+ FLATBUFFERS_ASSERT(nibbles > 0);
+ for (int i = 0; i < nibbles; i++)
+ if (!is_xdigit(cursor_[i]))
+ return Error("escape code must be followed by " + NumToString(nibbles) +
+ " hex digits");
+ std::string target(cursor_, cursor_ + nibbles);
+ *val = StringToUInt(target.c_str(), 16);
+ cursor_ += nibbles;
+ return NoError();
+}
+
+CheckedError Parser::SkipByteOrderMark() {
+ if (static_cast<unsigned char>(*cursor_) != 0xef) return NoError();
+ cursor_++;
+ if (static_cast<unsigned char>(*cursor_) != 0xbb)
+ return Error("invalid utf-8 byte order mark");
+ cursor_++;
+ if (static_cast<unsigned char>(*cursor_) != 0xbf)
+ return Error("invalid utf-8 byte order mark");
+ cursor_++;
+ return NoError();
+}
+
+static inline bool IsIdentifierStart(char c) {
+ return is_alpha(c) || (c == '_');
+}
+
+CheckedError Parser::Next() {
+ doc_comment_.clear();
+ bool seen_newline = cursor_ == source_;
+ attribute_.clear();
+ attr_is_trivial_ascii_string_ = true;
+ for (;;) {
+ char c = *cursor_++;
+ token_ = c;
+ switch (c) {
+ case '\0':
+ cursor_--;
+ token_ = kTokenEof;
+ return NoError();
+ case ' ':
+ case '\r':
+ case '\t': break;
+ case '\n':
+ MarkNewLine();
+ seen_newline = true;
+ break;
+ case '{':
+ case '}':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ case ',':
+ case ':':
+ case ';':
+ case '=': return NoError();
+ case '\"':
+ case '\'': {
+ int unicode_high_surrogate = -1;
+
+ while (*cursor_ != c) {
+ if (*cursor_ < ' ' && static_cast<signed char>(*cursor_) >= 0)
+ return Error("illegal character in string constant");
+ if (*cursor_ == '\\') {
+ attr_is_trivial_ascii_string_ = false; // has escape sequence
+ cursor_++;
+ if (unicode_high_surrogate != -1 && *cursor_ != 'u') {
+ return Error(
+ "illegal Unicode sequence (unpaired high surrogate)");
+ }
+ switch (*cursor_) {
+ case 'n':
+ attribute_ += '\n';
+ cursor_++;
+ break;
+ case 't':
+ attribute_ += '\t';
+ cursor_++;
+ break;
+ case 'r':
+ attribute_ += '\r';
+ cursor_++;
+ break;
+ case 'b':
+ attribute_ += '\b';
+ cursor_++;
+ break;
+ case 'f':
+ attribute_ += '\f';
+ cursor_++;
+ break;
+ case '\"':
+ attribute_ += '\"';
+ cursor_++;
+ break;
+ case '\'':
+ attribute_ += '\'';
+ cursor_++;
+ break;
+ case '\\':
+ attribute_ += '\\';
+ cursor_++;
+ break;
+ case '/':
+ attribute_ += '/';
+ cursor_++;
+ break;
+ case 'x': { // Not in the JSON standard
+ cursor_++;
+ uint64_t val;
+ ECHECK(ParseHexNum(2, &val));
+ attribute_ += static_cast<char>(val);
+ break;
+ }
+ case 'u': {
+ cursor_++;
+ uint64_t val;
+ ECHECK(ParseHexNum(4, &val));
+ if (val >= 0xD800 && val <= 0xDBFF) {
+ if (unicode_high_surrogate != -1) {
+ return Error(
+ "illegal Unicode sequence (multiple high surrogates)");
+ } else {
+ unicode_high_surrogate = static_cast<int>(val);
+ }
+ } else if (val >= 0xDC00 && val <= 0xDFFF) {
+ if (unicode_high_surrogate == -1) {
+ return Error(
+ "illegal Unicode sequence (unpaired low surrogate)");
+ } else {
+ int code_point = 0x10000 +
+ ((unicode_high_surrogate & 0x03FF) << 10) +
+ (val & 0x03FF);
+ ToUTF8(code_point, &attribute_);
+ unicode_high_surrogate = -1;
+ }
+ } else {
+ if (unicode_high_surrogate != -1) {
+ return Error(
+ "illegal Unicode sequence (unpaired high surrogate)");
+ }
+ ToUTF8(static_cast<int>(val), &attribute_);
+ }
+ break;
+ }
+ default: return Error("unknown escape code in string constant");
+ }
+ } else { // printable chars + UTF-8 bytes
+ if (unicode_high_surrogate != -1) {
+ return Error(
+ "illegal Unicode sequence (unpaired high surrogate)");
+ }
+ // reset if non-printable
+ attr_is_trivial_ascii_string_ &=
+ check_ascii_range(*cursor_, ' ', '~');
+
+ attribute_ += *cursor_++;
+ }
+ }
+ if (unicode_high_surrogate != -1) {
+ return Error("illegal Unicode sequence (unpaired high surrogate)");
+ }
+ cursor_++;
+ if (!attr_is_trivial_ascii_string_ && !opts.allow_non_utf8 &&
+ !ValidateUTF8(attribute_)) {
+ return Error("illegal UTF-8 sequence");
+ }
+ token_ = kTokenStringConstant;
+ return NoError();
+ }
+ case '/':
+ if (*cursor_ == '/') {
+ const char *start = ++cursor_;
+ while (*cursor_ && *cursor_ != '\n' && *cursor_ != '\r') cursor_++;
+ if (*start == '/') { // documentation comment
+ if (!seen_newline)
+ return Error(
+ "a documentation comment should be on a line on its own");
+ doc_comment_.push_back(std::string(start + 1, cursor_));
+ }
+ break;
+ } else if (*cursor_ == '*') {
+ cursor_++;
+ // TODO: make nested.
+ while (*cursor_ != '*' || cursor_[1] != '/') {
+ if (*cursor_ == '\n') MarkNewLine();
+ if (!*cursor_) return Error("end of file in comment");
+ cursor_++;
+ }
+ cursor_ += 2;
+ break;
+ }
+ FLATBUFFERS_FALLTHROUGH(); // else fall thru
+ default:
+ if (IsIdentifierStart(c)) {
+ // Collect all chars of an identifier:
+ const char *start = cursor_ - 1;
+ while (IsIdentifierStart(*cursor_) || is_digit(*cursor_)) cursor_++;
+ attribute_.append(start, cursor_);
+ token_ = kTokenIdentifier;
+ return NoError();
+ }
+
+ const auto has_sign = (c == '+') || (c == '-');
+ if (has_sign && IsIdentifierStart(*cursor_)) {
+ // '-'/'+' and following identifier - it could be a predefined
+ // constant. Return the sign in token_, see ParseSingleValue.
+ return NoError();
+ }
+
+ auto dot_lvl =
+ (c == '.') ? 0 : 1; // dot_lvl==0 <=> exactly one '.' seen
+ if (!dot_lvl && !is_digit(*cursor_)) return NoError(); // enum?
+ // Parser accepts hexadecimal-floating-literal (see C++ 5.13.4).
+ if (is_digit(c) || has_sign || !dot_lvl) {
+ const auto start = cursor_ - 1;
+ auto start_digits = !is_digit(c) ? cursor_ : cursor_ - 1;
+ if (!is_digit(c) && is_digit(*cursor_)) {
+ start_digits = cursor_; // see digit in cursor_ position
+ c = *cursor_++;
+ }
+ // hex-float can't begind with '.'
+ auto use_hex = dot_lvl && (c == '0') && is_alpha_char(*cursor_, 'X');
+ if (use_hex) start_digits = ++cursor_; // '0x' is the prefix, skip it
+ // Read an integer number or mantisa of float-point number.
+ do {
+ if (use_hex) {
+ while (is_xdigit(*cursor_)) cursor_++;
+ } else {
+ while (is_digit(*cursor_)) cursor_++;
+ }
+ } while ((*cursor_ == '.') && (++cursor_) && (--dot_lvl >= 0));
+ // Exponent of float-point number.
+ if ((dot_lvl >= 0) && (cursor_ > start_digits)) {
+ // The exponent suffix of hexadecimal float number is mandatory.
+ if (use_hex && !dot_lvl) start_digits = cursor_;
+ if ((use_hex && is_alpha_char(*cursor_, 'P')) ||
+ is_alpha_char(*cursor_, 'E')) {
+ dot_lvl = 0; // Emulate dot to signal about float-point number.
+ cursor_++;
+ if (*cursor_ == '+' || *cursor_ == '-') cursor_++;
+ start_digits = cursor_; // the exponent-part has to have digits
+ // Exponent is decimal integer number
+ while (is_digit(*cursor_)) cursor_++;
+ if (*cursor_ == '.') {
+ cursor_++; // If see a dot treat it as part of invalid number.
+ dot_lvl = -1; // Fall thru to Error().
+ }
+ }
+ }
+ // Finalize.
+ if ((dot_lvl >= 0) && (cursor_ > start_digits)) {
+ attribute_.append(start, cursor_);
+ token_ = dot_lvl ? kTokenIntegerConstant : kTokenFloatConstant;
+ return NoError();
+ } else {
+ return Error("invalid number: " + std::string(start, cursor_));
+ }
+ }
+ std::string ch;
+ ch = c;
+ if (false == check_ascii_range(c, ' ', '~'))
+ ch = "code: " + NumToString(c);
+ return Error("illegal character: " + ch);
+ }
+ }
+}
+
+// Check if a given token is next.
+bool Parser::Is(int t) const { return t == token_; }
+
+bool Parser::IsIdent(const char *id) const {
+ return token_ == kTokenIdentifier && attribute_ == id;
+}
+
+// Expect a given token to be next, consume it, or error if not present.
+CheckedError Parser::Expect(int t) {
+ if (t != token_) {
+ return Error("expecting: " + TokenToString(t) +
+ " instead got: " + TokenToStringId(token_));
+ }
+ NEXT();
+ return NoError();
+}
+
+CheckedError Parser::ParseNamespacing(std::string *id, std::string *last) {
+ while (Is('.')) {
+ NEXT();
+ *id += ".";
+ *id += attribute_;
+ if (last) *last = attribute_;
+ EXPECT(kTokenIdentifier);
+ }
+ return NoError();
+}
+
+EnumDef *Parser::LookupEnum(const std::string &id) {
+ // Search thru parent namespaces.
+ return LookupTableByName(enums_, id, *current_namespace_, 0);
+}
+
+StructDef *Parser::LookupStruct(const std::string &id) const {
+ auto sd = structs_.Lookup(id);
+ if (sd) sd->refcount++;
+ return sd;
+}
+
+StructDef *Parser::LookupStructThruParentNamespaces(
+ const std::string &id) const {
+ auto sd = LookupTableByName(structs_, id, *current_namespace_, 1);
+ if (sd) sd->refcount++;
+ return sd;
+}
+
+CheckedError Parser::ParseTypeIdent(Type &type) {
+ std::string id = attribute_;
+ EXPECT(kTokenIdentifier);
+ ECHECK(ParseNamespacing(&id, nullptr));
+ auto enum_def = LookupEnum(id);
+ if (enum_def) {
+ type = enum_def->underlying_type;
+ if (enum_def->is_union) type.base_type = BASE_TYPE_UNION;
+ } else {
+ type.base_type = BASE_TYPE_STRUCT;
+ type.struct_def = LookupCreateStruct(id);
+ }
+ return NoError();
+}
+
+// Parse any IDL type.
+CheckedError Parser::ParseType(Type &type) {
+ if (token_ == kTokenIdentifier) {
+ if (IsIdent("bool")) {
+ type.base_type = BASE_TYPE_BOOL;
+ NEXT();
+ } else if (IsIdent("byte") || IsIdent("int8")) {
+ type.base_type = BASE_TYPE_CHAR;
+ NEXT();
+ } else if (IsIdent("ubyte") || IsIdent("uint8")) {
+ type.base_type = BASE_TYPE_UCHAR;
+ NEXT();
+ } else if (IsIdent("short") || IsIdent("int16")) {
+ type.base_type = BASE_TYPE_SHORT;
+ NEXT();
+ } else if (IsIdent("ushort") || IsIdent("uint16")) {
+ type.base_type = BASE_TYPE_USHORT;
+ NEXT();
+ } else if (IsIdent("int") || IsIdent("int32")) {
+ type.base_type = BASE_TYPE_INT;
+ NEXT();
+ } else if (IsIdent("uint") || IsIdent("uint32")) {
+ type.base_type = BASE_TYPE_UINT;
+ NEXT();
+ } else if (IsIdent("long") || IsIdent("int64")) {
+ type.base_type = BASE_TYPE_LONG;
+ NEXT();
+ } else if (IsIdent("ulong") || IsIdent("uint64")) {
+ type.base_type = BASE_TYPE_ULONG;
+ NEXT();
+ } else if (IsIdent("float") || IsIdent("float32")) {
+ type.base_type = BASE_TYPE_FLOAT;
+ NEXT();
+ } else if (IsIdent("double") || IsIdent("float64")) {
+ type.base_type = BASE_TYPE_DOUBLE;
+ NEXT();
+ } else if (IsIdent("string")) {
+ type.base_type = BASE_TYPE_STRING;
+ NEXT();
+ } else {
+ ECHECK(ParseTypeIdent(type));
+ }
+ } else if (token_ == '[') {
+ ParseDepthGuard depth_guard(this);
+ ECHECK(depth_guard.Check());
+ NEXT();
+ Type subtype;
+ ECHECK(ParseType(subtype));
+ if (IsSeries(subtype)) {
+ // We could support this, but it will complicate things, and it's
+ // easier to work around with a struct around the inner vector.
+ return Error("nested vector types not supported (wrap in table first)");
+ }
+ if (token_ == ':') {
+ NEXT();
+ if (token_ != kTokenIntegerConstant) {
+ return Error("length of fixed-length array must be an integer value");
+ }
+ uint16_t fixed_length = 0;
+ bool check = StringToNumber(attribute_.c_str(), &fixed_length);
+ if (!check || fixed_length < 1) {
+ return Error(
+ "length of fixed-length array must be positive and fit to "
+ "uint16_t type");
+ }
+ type = Type(BASE_TYPE_ARRAY, subtype.struct_def, subtype.enum_def,
+ fixed_length);
+ NEXT();
+ } else {
+ type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def);
+ }
+ type.element = subtype.base_type;
+ EXPECT(']');
+ } else {
+ return Error("illegal type syntax");
+ }
+ return NoError();
+}
+
+CheckedError Parser::AddField(StructDef &struct_def, const std::string &name,
+ const Type &type, FieldDef **dest) {
+ auto &field = *new FieldDef();
+ field.value.offset =
+ FieldIndexToOffset(static_cast<voffset_t>(struct_def.fields.vec.size()));
+ field.name = name;
+ field.file = struct_def.file;
+ field.value.type = type;
+ if (struct_def.fixed) { // statically compute the field offset
+ auto size = InlineSize(type);
+ auto alignment = InlineAlignment(type);
+ // structs_ need to have a predictable format, so we need to align to
+ // the largest scalar
+ struct_def.minalign = std::max(struct_def.minalign, alignment);
+ struct_def.PadLastField(alignment);
+ field.value.offset = static_cast<voffset_t>(struct_def.bytesize);
+ struct_def.bytesize += size;
+ }
+ if (struct_def.fields.Add(name, &field))
+ return Error("field already exists: " + name);
+ *dest = &field;
+ return NoError();
+}
+
+CheckedError Parser::ParseField(StructDef &struct_def) {
+ std::string name = attribute_;
+
+ if (LookupCreateStruct(name, false, false))
+ return Error("field name can not be the same as table/struct name");
+
+ if (!IsLowerSnakeCase(name)) {
+ Warning("field names should be lowercase snake_case, got: " + name);
+ }
+
+ std::vector<std::string> dc = doc_comment_;
+ EXPECT(kTokenIdentifier);
+ EXPECT(':');
+ Type type;
+ ECHECK(ParseType(type));
+
+ if (struct_def.fixed) {
+ auto valid = IsScalar(type.base_type) || IsStruct(type);
+ if (!valid && IsArray(type)) {
+ const auto &elem_type = type.VectorType();
+ valid |= IsScalar(elem_type.base_type) || IsStruct(elem_type);
+ }
+ if (!valid)
+ return Error("structs may contain only scalar or struct fields");
+ }
+
+ if (!struct_def.fixed && IsArray(type))
+ return Error("fixed-length array in table must be wrapped in struct");
+
+ if (IsArray(type)) {
+ advanced_features_ |= reflection::AdvancedArrayFeatures;
+ if (!SupportsAdvancedArrayFeatures()) {
+ return Error(
+ "Arrays are not yet supported in all "
+ "the specified programming languages.");
+ }
+ }
+
+ FieldDef *typefield = nullptr;
+ if (type.base_type == BASE_TYPE_UNION) {
+ // For union fields, add a second auto-generated field to hold the type,
+ // with a special suffix.
+ ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
+ type.enum_def->underlying_type, &typefield));
+ } else if (IsVector(type) && type.element == BASE_TYPE_UNION) {
+ advanced_features_ |= reflection::AdvancedUnionFeatures;
+ // Only cpp, js and ts supports the union vector feature so far.
+ if (!SupportsAdvancedUnionFeatures()) {
+ return Error(
+ "Vectors of unions are not yet supported in at least one of "
+ "the specified programming languages.");
+ }
+ // For vector of union fields, add a second auto-generated vector field to
+ // hold the types, with a special suffix.
+ Type union_vector(BASE_TYPE_VECTOR, nullptr, type.enum_def);
+ union_vector.element = BASE_TYPE_UTYPE;
+ ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), union_vector,
+ &typefield));
+ }
+
+ FieldDef *field;
+ ECHECK(AddField(struct_def, name, type, &field));
+
+ if (token_ == '=') {
+ NEXT();
+ ECHECK(ParseSingleValue(&field->name, field->value, true));
+ if (IsStruct(type) || (struct_def.fixed && field->value.constant != "0"))
+ return Error(
+ "default values are not supported for struct fields, table fields, "
+ "or in structs.");
+ if (IsString(type) || IsVector(type)) {
+ advanced_features_ |= reflection::DefaultVectorsAndStrings;
+ if (field->value.constant != "0" && field->value.constant != "null" &&
+ !SupportsDefaultVectorsAndStrings()) {
+ return Error(
+ "Default values for strings and vectors are not supported in one "
+ "of the specified programming languages");
+ }
+ }
+
+ if (IsVector(type) && field->value.constant != "0" &&
+ field->value.constant != "[]") {
+ return Error("The only supported default for vectors is `[]`.");
+ }
+ }
+
+ // Append .0 if the value has not it (skip hex and scientific floats).
+ // This suffix needed for generated C++ code.
+ if (IsFloat(type.base_type)) {
+ auto &text = field->value.constant;
+ FLATBUFFERS_ASSERT(false == text.empty());
+ auto s = text.c_str();
+ while (*s == ' ') s++;
+ if (*s == '-' || *s == '+') s++;
+ // 1) A float constants (nan, inf, pi, etc) is a kind of identifier.
+ // 2) A float number needn't ".0" at the end if it has exponent.
+ if ((false == IsIdentifierStart(*s)) &&
+ (std::string::npos == field->value.constant.find_first_of(".eEpP"))) {
+ field->value.constant += ".0";
+ }
+ }
+
+ field->doc_comment = dc;
+ ECHECK(ParseMetaData(&field->attributes));
+ field->deprecated = field->attributes.Lookup("deprecated") != nullptr;
+ auto hash_name = field->attributes.Lookup("hash");
+ if (hash_name) {
+ switch ((IsVector(type)) ? type.element : type.base_type) {
+ case BASE_TYPE_SHORT:
+ case BASE_TYPE_USHORT: {
+ if (FindHashFunction16(hash_name->constant.c_str()) == nullptr)
+ return Error("Unknown hashing algorithm for 16 bit types: " +
+ hash_name->constant);
+ break;
+ }
+ case BASE_TYPE_INT:
+ case BASE_TYPE_UINT: {
+ if (FindHashFunction32(hash_name->constant.c_str()) == nullptr)
+ return Error("Unknown hashing algorithm for 32 bit types: " +
+ hash_name->constant);
+ break;
+ }
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG: {
+ if (FindHashFunction64(hash_name->constant.c_str()) == nullptr)
+ return Error("Unknown hashing algorithm for 64 bit types: " +
+ hash_name->constant);
+ break;
+ }
+ default:
+ return Error(
+ "only short, ushort, int, uint, long and ulong data types support "
+ "hashing.");
+ }
+ }
+
+ // For historical convenience reasons, string keys are assumed required.
+ // Scalars are kDefault unless otherwise specified.
+ // Nonscalars are kOptional unless required;
+ field->key = field->attributes.Lookup("key") != nullptr;
+ const bool required = field->attributes.Lookup("required") != nullptr ||
+ (IsString(type) && field->key);
+ const bool default_str_or_vec =
+ ((IsString(type) || IsVector(type)) && field->value.constant != "0");
+ const bool optional = IsScalar(type.base_type)
+ ? (field->value.constant == "null")
+ : !(required || default_str_or_vec);
+ if (required && optional) {
+ return Error("Fields cannot be both optional and required.");
+ }
+ field->presence = FieldDef::MakeFieldPresence(optional, required);
+
+ if (required && (struct_def.fixed || IsScalar(type.base_type))) {
+ return Error("only non-scalar fields in tables may be 'required'");
+ }
+ if (field->key) {
+ if (struct_def.has_key) return Error("only one field may be set as 'key'");
+ struct_def.has_key = true;
+ if (!IsScalar(type.base_type) && !IsString(type)) {
+ return Error("'key' field must be string or scalar type");
+ }
+ }
+
+ if (field->IsScalarOptional()) {
+ advanced_features_ |= reflection::OptionalScalars;
+ if (type.enum_def && type.enum_def->Lookup("null")) {
+ FLATBUFFERS_ASSERT(IsInteger(type.base_type));
+ return Error(
+ "the default 'null' is reserved for declaring optional scalar "
+ "fields, it conflicts with declaration of enum '" +
+ type.enum_def->name + "'.");
+ }
+ if (field->attributes.Lookup("key")) {
+ return Error(
+ "only a non-optional scalar field can be used as a 'key' field");
+ }
+ if (!SupportsOptionalScalars()) {
+ return Error(
+ "Optional scalars are not yet supported in at least one the of "
+ "the specified programming languages.");
+ }
+ }
+
+ if (type.enum_def) {
+ // Verify the enum's type and default value.
+ const std::string &constant = field->value.constant;
+ if (type.base_type == BASE_TYPE_UNION) {
+ if (constant != "0") { return Error("Union defaults must be NONE"); }
+ } else if (IsVector(type)) {
+ if (constant != "0" && constant != "[]") {
+ return Error("Vector defaults may only be `[]`.");
+ }
+ } else if (IsArray(type)) {
+ if (constant != "0") {
+ return Error("Array defaults are not supported yet.");
+ }
+ } else {
+ if (!IsInteger(type.base_type)) {
+ return Error("Enums must have integer base types");
+ }
+ // Optional and bitflags enums may have default constants that are not
+ // their specified variants.
+ if (!field->IsOptional() &&
+ type.enum_def->attributes.Lookup("bit_flags") == nullptr) {
+ if (type.enum_def->FindByValue(constant) == nullptr) {
+ return Error("default value of `" + constant + "` for " + "field `" +
+ name + "` is not part of enum `" + type.enum_def->name +
+ "`.");
+ }
+ }
+ }
+ }
+
+ if (field->deprecated && struct_def.fixed)
+ return Error("can't deprecate fields in a struct");
+
+ auto cpp_type = field->attributes.Lookup("cpp_type");
+ if (cpp_type) {
+ if (!hash_name)
+ return Error("cpp_type can only be used with a hashed field");
+ /// forcing cpp_ptr_type to 'naked' if unset
+ auto cpp_ptr_type = field->attributes.Lookup("cpp_ptr_type");
+ if (!cpp_ptr_type) {
+ auto val = new Value();
+ val->type = cpp_type->type;
+ val->constant = "naked";
+ field->attributes.Add("cpp_ptr_type", val);
+ }
+ }
+
+ field->shared = field->attributes.Lookup("shared") != nullptr;
+ if (field->shared && field->value.type.base_type != BASE_TYPE_STRING)
+ return Error("shared can only be defined on strings");
+
+ auto field_native_custom_alloc =
+ field->attributes.Lookup("native_custom_alloc");
+ if (field_native_custom_alloc)
+ return Error(
+ "native_custom_alloc can only be used with a table or struct "
+ "definition");
+
+ field->native_inline = field->attributes.Lookup("native_inline") != nullptr;
+ if (field->native_inline && !IsStruct(field->value.type))
+ return Error("native_inline can only be defined on structs");
+
+ auto nested = field->attributes.Lookup("nested_flatbuffer");
+ if (nested) {
+ if (nested->type.base_type != BASE_TYPE_STRING)
+ return Error(
+ "nested_flatbuffer attribute must be a string (the root type)");
+ if (type.base_type != BASE_TYPE_VECTOR || type.element != BASE_TYPE_UCHAR)
+ return Error(
+ "nested_flatbuffer attribute may only apply to a vector of ubyte");
+ // This will cause an error if the root type of the nested flatbuffer
+ // wasn't defined elsewhere.
+ field->nested_flatbuffer = LookupCreateStruct(nested->constant);
+ }
+
+ if (field->attributes.Lookup("flexbuffer")) {
+ field->flexbuffer = true;
+ uses_flexbuffers_ = true;
+ if (type.base_type != BASE_TYPE_VECTOR || type.element != BASE_TYPE_UCHAR)
+ return Error("flexbuffer attribute may only apply to a vector of ubyte");
+ }
+
+ if (typefield) {
+ if (!IsScalar(typefield->value.type.base_type)) {
+ // this is a union vector field
+ typefield->presence = field->presence;
+ }
+ // If this field is a union, and it has a manually assigned id,
+ // the automatically added type field should have an id as well (of N - 1).
+ auto attr = field->attributes.Lookup("id");
+ if (attr) {
+ const auto &id_str = attr->constant;
+ voffset_t id = 0;
+ const auto done = !atot(id_str.c_str(), *this, &id).Check();
+ if (done && id > 0) {
+ auto val = new Value();
+ val->type = attr->type;
+ val->constant = NumToString(id - 1);
+ typefield->attributes.Add("id", val);
+ } else {
+ return Error(
+ "a union type effectively adds two fields with non-negative ids, "
+ "its id must be that of the second field (the first field is "
+ "the type field and not explicitly declared in the schema);\n"
+ "field: " +
+ field->name + ", id: " + id_str);
+ }
+ }
+ // if this field is a union that is deprecated,
+ // the automatically added type field should be deprecated as well
+ if (field->deprecated) { typefield->deprecated = true; }
+ }
+
+ EXPECT(';');
+ return NoError();
+}
+
+CheckedError Parser::ParseString(Value &val, bool use_string_pooling) {
+ auto s = attribute_;
+ EXPECT(kTokenStringConstant);
+ if (use_string_pooling) {
+ val.constant = NumToString(builder_.CreateSharedString(s).o);
+ } else {
+ val.constant = NumToString(builder_.CreateString(s).o);
+ }
+ return NoError();
+}
+
+CheckedError Parser::ParseComma() {
+ if (!opts.protobuf_ascii_alike) EXPECT(',');
+ return NoError();
+}
+
+CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
+ size_t parent_fieldn,
+ const StructDef *parent_struct_def,
+ uoffset_t count, bool inside_vector) {
+ switch (val.type.base_type) {
+ case BASE_TYPE_UNION: {
+ FLATBUFFERS_ASSERT(field);
+ std::string constant;
+ Vector<uint8_t> *vector_of_union_types = nullptr;
+ // Find corresponding type field we may have already parsed.
+ for (auto elem = field_stack_.rbegin() + count;
+ elem != field_stack_.rbegin() + parent_fieldn + count; ++elem) {
+ auto &type = elem->second->value.type;
+ if (type.enum_def == val.type.enum_def) {
+ if (inside_vector) {
+ if (IsVector(type) && type.element == BASE_TYPE_UTYPE) {
+ // Vector of union type field.
+ uoffset_t offset;
+ ECHECK(atot(elem->first.constant.c_str(), *this, &offset));
+ vector_of_union_types = reinterpret_cast<Vector<uint8_t> *>(
+ builder_.GetCurrentBufferPointer() + builder_.GetSize() -
+ offset);
+ break;
+ }
+ } else {
+ if (type.base_type == BASE_TYPE_UTYPE) {
+ // Union type field.
+ constant = elem->first.constant;
+ break;
+ }
+ }
+ }
+ }
+ if (constant.empty() && !inside_vector) {
+ // We haven't seen the type field yet. Sadly a lot of JSON writers
+ // output these in alphabetical order, meaning it comes after this
+ // value. So we scan past the value to find it, then come back here.
+ // We currently don't do this for vectors of unions because the
+ // scanning/serialization logic would get very complicated.
+ auto type_name = field->name + UnionTypeFieldSuffix();
+ FLATBUFFERS_ASSERT(parent_struct_def);
+ auto type_field = parent_struct_def->fields.Lookup(type_name);
+ FLATBUFFERS_ASSERT(type_field); // Guaranteed by ParseField().
+ // Remember where we are in the source file, so we can come back here.
+ auto backup = *static_cast<ParserState *>(this);
+ ECHECK(SkipAnyJsonValue()); // The table.
+ ECHECK(ParseComma());
+ auto next_name = attribute_;
+ if (Is(kTokenStringConstant)) {
+ NEXT();
+ } else {
+ EXPECT(kTokenIdentifier);
+ }
+ if (next_name == type_name) {
+ EXPECT(':');
+ ParseDepthGuard depth_guard(this);
+ ECHECK(depth_guard.Check());
+ Value type_val = type_field->value;
+ ECHECK(ParseAnyValue(type_val, type_field, 0, nullptr, 0));
+ constant = type_val.constant;
+ // Got the information we needed, now rewind:
+ *static_cast<ParserState *>(this) = backup;
+ }
+ }
+ if (constant.empty() && !vector_of_union_types) {
+ return Error("missing type field for this union value: " + field->name);
+ }
+ uint8_t enum_idx;
+ if (vector_of_union_types) {
+ enum_idx = vector_of_union_types->Get(count);
+ } else {
+ ECHECK(atot(constant.c_str(), *this, &enum_idx));
+ }
+ auto enum_val = val.type.enum_def->ReverseLookup(enum_idx, true);
+ if (!enum_val) return Error("illegal type id for: " + field->name);
+ if (enum_val->union_type.base_type == BASE_TYPE_STRUCT) {
+ ECHECK(ParseTable(*enum_val->union_type.struct_def, &val.constant,
+ nullptr));
+ if (enum_val->union_type.struct_def->fixed) {
+ // All BASE_TYPE_UNION values are offsets, so turn this into one.
+ SerializeStruct(*enum_val->union_type.struct_def, val);
+ builder_.ClearOffsets();
+ val.constant = NumToString(builder_.GetSize());
+ }
+ } else if (IsString(enum_val->union_type)) {
+ ECHECK(ParseString(val, field->shared));
+ } else {
+ FLATBUFFERS_ASSERT(false);
+ }
+ break;
+ }
+ case BASE_TYPE_STRUCT:
+ ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr));
+ break;
+ case BASE_TYPE_STRING: {
+ ECHECK(ParseString(val, field->shared));
+ break;
+ }
+ case BASE_TYPE_VECTOR: {
+ uoffset_t off;
+ ECHECK(ParseVector(val.type.VectorType(), &off, field, parent_fieldn));
+ val.constant = NumToString(off);
+ break;
+ }
+ case BASE_TYPE_ARRAY: {
+ ECHECK(ParseArray(val));
+ break;
+ }
+ case BASE_TYPE_INT:
+ case BASE_TYPE_UINT:
+ case BASE_TYPE_LONG:
+ case BASE_TYPE_ULONG: {
+ if (field && field->attributes.Lookup("hash") &&
+ (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) {
+ ECHECK(ParseHash(val, field));
+ } else {
+ ECHECK(ParseSingleValue(field ? &field->name : nullptr, val, false));
+ }
+ break;
+ }
+ default:
+ ECHECK(ParseSingleValue(field ? &field->name : nullptr, val, false));
+ break;
+ }
+ return NoError();
+}
+
+void Parser::SerializeStruct(const StructDef &struct_def, const Value &val) {
+ SerializeStruct(builder_, struct_def, val);
+}
+
+void Parser::SerializeStruct(FlatBufferBuilder &builder,
+ const StructDef &struct_def, const Value &val) {
+ FLATBUFFERS_ASSERT(val.constant.length() == struct_def.bytesize);
+ builder.Align(struct_def.minalign);
+ builder.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()),
+ struct_def.bytesize);
+ builder.AddStructOffset(val.offset, builder.GetSize());
+}
+
+template<typename F>
+CheckedError Parser::ParseTableDelimiters(size_t &fieldn,
+ const StructDef *struct_def, F body) {
+ // We allow tables both as JSON object{ .. } with field names
+ // or vector[..] with all fields in order
+ char terminator = '}';
+ bool is_nested_vector = struct_def && Is('[');
+ if (is_nested_vector) {
+ NEXT();
+ terminator = ']';
+ } else {
+ EXPECT('{');
+ }
+ for (;;) {
+ if ((!opts.strict_json || !fieldn) && Is(terminator)) break;
+ std::string name;
+ if (is_nested_vector) {
+ if (fieldn >= struct_def->fields.vec.size()) {
+ return Error("too many unnamed fields in nested array");
+ }
+ name = struct_def->fields.vec[fieldn]->name;
+ } else {
+ name = attribute_;
+ if (Is(kTokenStringConstant)) {
+ NEXT();
+ } else {
+ EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier);
+ }
+ if (!opts.protobuf_ascii_alike || !(Is('{') || Is('['))) EXPECT(':');
+ }
+ ECHECK(body(name, fieldn, struct_def));
+ if (Is(terminator)) break;
+ ECHECK(ParseComma());
+ }
+ NEXT();
+ if (is_nested_vector && fieldn != struct_def->fields.vec.size()) {
+ return Error("wrong number of unnamed fields in table vector");
+ }
+ return NoError();
+}
+
+CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
+ uoffset_t *ovalue) {
+ ParseDepthGuard depth_guard(this);
+ ECHECK(depth_guard.Check());
+
+ size_t fieldn_outer = 0;
+ auto err = ParseTableDelimiters(
+ fieldn_outer, &struct_def,
+ [&](const std::string &name, size_t &fieldn,
+ const StructDef *struct_def_inner) -> CheckedError {
+ if (name == "$schema") {
+ ECHECK(Expect(kTokenStringConstant));
+ return NoError();
+ }
+ auto field = struct_def_inner->fields.Lookup(name);
+ if (!field) {
+ if (!opts.skip_unexpected_fields_in_json) {
+ return Error("unknown field: " + name);
+ } else {
+ ECHECK(SkipAnyJsonValue());
+ }
+ } else {
+ if (IsIdent("null") && !IsScalar(field->value.type.base_type)) {
+ ECHECK(Next()); // Ignore this field.
+ } else {
+ Value val = field->value;
+ if (field->flexbuffer) {
+ flexbuffers::Builder builder(1024,
+ flexbuffers::BUILDER_FLAG_SHARE_ALL);
+ ECHECK(ParseFlexBufferValue(&builder));
+ builder.Finish();
+ // Force alignment for nested flexbuffer
+ builder_.ForceVectorAlignment(builder.GetSize(), sizeof(uint8_t),
+ sizeof(largest_scalar_t));
+ auto off = builder_.CreateVector(builder.GetBuffer());
+ val.constant = NumToString(off.o);
+ } else if (field->nested_flatbuffer) {
+ ECHECK(
+ ParseNestedFlatbuffer(val, field, fieldn, struct_def_inner));
+ } else {
+ ECHECK(ParseAnyValue(val, field, fieldn, struct_def_inner, 0));
+ }
+ // Hardcoded insertion-sort with error-check.
+ // If fields are specified in order, then this loop exits
+ // immediately.
+ auto elem = field_stack_.rbegin();
+ for (; elem != field_stack_.rbegin() + fieldn; ++elem) {
+ auto existing_field = elem->second;
+ if (existing_field == field)
+ return Error("field set more than once: " + field->name);
+ if (existing_field->value.offset < field->value.offset) break;
+ }
+ // Note: elem points to before the insertion point, thus .base()
+ // points to the correct spot.
+ field_stack_.insert(elem.base(), std::make_pair(val, field));
+ fieldn++;
+ }
+ }
+ return NoError();
+ });
+ ECHECK(err);
+
+ // Check if all required fields are parsed.
+ for (auto field_it = struct_def.fields.vec.begin();
+ field_it != struct_def.fields.vec.end(); ++field_it) {
+ auto required_field = *field_it;
+ if (!required_field->IsRequired()) { continue; }
+ bool found = false;
+ for (auto pf_it = field_stack_.end() - fieldn_outer;
+ pf_it != field_stack_.end(); ++pf_it) {
+ auto parsed_field = pf_it->second;
+ if (parsed_field == required_field) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return Error("required field is missing: " + required_field->name +
+ " in " + struct_def.name);
+ }
+ }
+
+ if (struct_def.fixed && fieldn_outer != struct_def.fields.vec.size())
+ return Error("struct: wrong number of initializers: " + struct_def.name);
+
+ auto start = struct_def.fixed ? builder_.StartStruct(struct_def.minalign)
+ : builder_.StartTable();
+
+ for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; size;
+ size /= 2) {
+ // Go through elements in reverse, since we're building the data backwards.
+ for (auto it = field_stack_.rbegin();
+ it != field_stack_.rbegin() + fieldn_outer; ++it) {
+ auto &field_value = it->first;
+ auto field = it->second;
+ if (!struct_def.sortbysize ||
+ size == SizeOf(field_value.type.base_type)) {
+ switch (field_value.type.base_type) {
+ // clang-format off
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_ ## ENUM: \
+ builder_.Pad(field->padding); \
+ if (struct_def.fixed) { \
+ CTYPE val; \
+ ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
+ builder_.PushElement(val); \
+ } else { \
+ CTYPE val, valdef; \
+ ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
+ ECHECK(atot(field->value.constant.c_str(), *this, &valdef)); \
+ builder_.AddElement(field_value.offset, val, valdef); \
+ } \
+ break;
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_ ## ENUM: \
+ builder_.Pad(field->padding); \
+ if (IsStruct(field->value.type)) { \
+ SerializeStruct(*field->value.type.struct_def, field_value); \
+ } else { \
+ CTYPE val; \
+ ECHECK(atot(field_value.constant.c_str(), *this, &val)); \
+ builder_.AddOffset(field_value.offset, val); \
+ } \
+ break;
+ FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ case BASE_TYPE_ARRAY:
+ builder_.Pad(field->padding);
+ builder_.PushBytes(
+ reinterpret_cast<const uint8_t*>(field_value.constant.c_str()),
+ InlineSize(field_value.type));
+ break;
+ // clang-format on
+ }
+ }
+ }
+ }
+ for (size_t i = 0; i < fieldn_outer; i++) field_stack_.pop_back();
+
+ if (struct_def.fixed) {
+ builder_.ClearOffsets();
+ builder_.EndStruct();
+ FLATBUFFERS_ASSERT(value);
+ // Temporarily store this struct in the value string, since it is to
+ // be serialized in-place elsewhere.
+ value->assign(
+ reinterpret_cast<const char *>(builder_.GetCurrentBufferPointer()),
+ struct_def.bytesize);
+ builder_.PopBytes(struct_def.bytesize);
+ FLATBUFFERS_ASSERT(!ovalue);
+ } else {
+ auto val = builder_.EndTable(start);
+ if (ovalue) *ovalue = val;
+ if (value) *value = NumToString(val);
+ }
+ return NoError();
+}
+
+template<typename F>
+CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) {
+ EXPECT('[');
+ for (;;) {
+ if ((!opts.strict_json || !count) && Is(']')) break;
+ ECHECK(body(count));
+ count++;
+ if (Is(']')) break;
+ ECHECK(ParseComma());
+ }
+ NEXT();
+ return NoError();
+}
+
+static bool CompareSerializedScalars(const uint8_t *a, const uint8_t *b,
+ const FieldDef &key) {
+ switch (key.value.type.base_type) {
+#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_##ENUM: { \
+ CTYPE def = static_cast<CTYPE>(0); \
+ if (!a || !b) { StringToNumber(key.value.constant.c_str(), &def); } \
+ const auto av = a ? ReadScalar<CTYPE>(a) : def; \
+ const auto bv = b ? ReadScalar<CTYPE>(b) : def; \
+ return av < bv; \
+ }
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
+#undef FLATBUFFERS_TD
+ default: {
+ FLATBUFFERS_ASSERT(false && "scalar type expected");
+ return false;
+ }
+ }
+}
+
+static bool CompareTablesByScalarKey(const Offset<Table> *_a,
+ const Offset<Table> *_b,
+ const FieldDef &key) {
+ const voffset_t offset = key.value.offset;
+ // Indirect offset pointer to table pointer.
+ auto a = reinterpret_cast<const uint8_t *>(_a) + ReadScalar<uoffset_t>(_a);
+ auto b = reinterpret_cast<const uint8_t *>(_b) + ReadScalar<uoffset_t>(_b);
+ // Fetch field address from table.
+ a = reinterpret_cast<const Table *>(a)->GetAddressOf(offset);
+ b = reinterpret_cast<const Table *>(b)->GetAddressOf(offset);
+ return CompareSerializedScalars(a, b, key);
+}
+
+static bool CompareTablesByStringKey(const Offset<Table> *_a,
+ const Offset<Table> *_b,
+ const FieldDef &key) {
+ const voffset_t offset = key.value.offset;
+ // Indirect offset pointer to table pointer.
+ auto a = reinterpret_cast<const uint8_t *>(_a) + ReadScalar<uoffset_t>(_a);
+ auto b = reinterpret_cast<const uint8_t *>(_b) + ReadScalar<uoffset_t>(_b);
+ // Fetch field address from table.
+ a = reinterpret_cast<const Table *>(a)->GetAddressOf(offset);
+ b = reinterpret_cast<const Table *>(b)->GetAddressOf(offset);
+ if (a && b) {
+ // Indirect offset pointer to string pointer.
+ a += ReadScalar<uoffset_t>(a);
+ b += ReadScalar<uoffset_t>(b);
+ return *reinterpret_cast<const String *>(a) <
+ *reinterpret_cast<const String *>(b);
+ } else {
+ return a ? true : false;
+ }
+}
+
+static void SwapSerializedTables(Offset<Table> *a, Offset<Table> *b) {
+ // These are serialized offsets, so are relative where they are
+ // stored in memory, so compute the distance between these pointers:
+ ptrdiff_t diff = (b - a) * sizeof(Offset<Table>);
+ FLATBUFFERS_ASSERT(diff >= 0); // Guaranteed by SimpleQsort.
+ auto udiff = static_cast<uoffset_t>(diff);
+ a->o = EndianScalar(ReadScalar<uoffset_t>(a) - udiff);
+ b->o = EndianScalar(ReadScalar<uoffset_t>(b) + udiff);
+ std::swap(*a, *b);
+}
+
+// See below for why we need our own sort :(
+template<typename T, typename F, typename S>
+void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) {
+ if (end - begin <= static_cast<ptrdiff_t>(width)) return;
+ auto l = begin + width;
+ auto r = end;
+ while (l < r) {
+ if (comparator(begin, l)) {
+ r -= width;
+ swapper(l, r);
+ } else {
+ l += width;
+ }
+ }
+ l -= width;
+ swapper(begin, l);
+ SimpleQsort(begin, l, width, comparator, swapper);
+ SimpleQsort(r, end, width, comparator, swapper);
+}
+
+CheckedError Parser::ParseAlignAttribute(const std::string &align_constant,
+ size_t min_align, size_t *align) {
+ // Use uint8_t to avoid problems with size_t==`unsigned long` on LP64.
+ uint8_t align_value;
+ if (StringToNumber(align_constant.c_str(), &align_value) &&
+ VerifyAlignmentRequirements(static_cast<size_t>(align_value),
+ min_align)) {
+ *align = align_value;
+ return NoError();
+ }
+ return Error("unexpected force_align value '" + align_constant +
+ "', alignment must be a power of two integer ranging from the "
+ "type\'s natural alignment " +
+ NumToString(min_align) + " to " +
+ NumToString(FLATBUFFERS_MAX_ALIGNMENT));
+}
+
+CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
+ FieldDef *field, size_t fieldn) {
+ uoffset_t count = 0;
+ auto err = ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
+ Value val;
+ val.type = type;
+ ECHECK(ParseAnyValue(val, field, fieldn, nullptr, count, true));
+ field_stack_.push_back(std::make_pair(val, nullptr));
+ return NoError();
+ });
+ ECHECK(err);
+
+ const size_t len = count * InlineSize(type) / InlineAlignment(type);
+ const size_t elemsize = InlineAlignment(type);
+ const auto force_align = field->attributes.Lookup("force_align");
+ if (force_align) {
+ size_t align;
+ ECHECK(ParseAlignAttribute(force_align->constant, 1, &align));
+ if (align > 1) { builder_.ForceVectorAlignment(len, elemsize, align); }
+ }
+
+ builder_.StartVector(len, elemsize);
+ for (uoffset_t i = 0; i < count; i++) {
+ // start at the back, since we're building the data backwards.
+ auto &val = field_stack_.back().first;
+ switch (val.type.base_type) {
+ // clang-format off
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE,...) \
+ case BASE_TYPE_ ## ENUM: \
+ if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \
+ else { \
+ CTYPE elem; \
+ ECHECK(atot(val.constant.c_str(), *this, &elem)); \
+ builder_.PushElement(elem); \
+ } \
+ break;
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ // clang-format on
+ }
+ field_stack_.pop_back();
+ }
+
+ builder_.ClearOffsets();
+ *ovalue = builder_.EndVector(count);
+
+ if (type.base_type == BASE_TYPE_STRUCT && type.struct_def->has_key) {
+ // We should sort this vector. Find the key first.
+ const FieldDef *key = nullptr;
+ for (auto it = type.struct_def->fields.vec.begin();
+ it != type.struct_def->fields.vec.end(); ++it) {
+ if ((*it)->key) {
+ key = (*it);
+ break;
+ }
+ }
+ FLATBUFFERS_ASSERT(key);
+ // Now sort it.
+ // We can't use std::sort because for structs the size is not known at
+ // compile time, and for tables our iterators dereference offsets, so can't
+ // be used to swap elements.
+ // And we can't use C qsort either, since that would force use to use
+ // globals, making parsing thread-unsafe.
+ // So for now, we use SimpleQsort above.
+ // TODO: replace with something better, preferably not recursive.
+
+ if (type.struct_def->fixed) {
+ const voffset_t offset = key->value.offset;
+ const size_t struct_size = type.struct_def->bytesize;
+ auto v =
+ reinterpret_cast<VectorOfAny *>(builder_.GetCurrentBufferPointer());
+ SimpleQsort<uint8_t>(
+ v->Data(), v->Data() + v->size() * type.struct_def->bytesize,
+ type.struct_def->bytesize,
+ [offset, key](const uint8_t *a, const uint8_t *b) -> bool {
+ return CompareSerializedScalars(a + offset, b + offset, *key);
+ },
+ [struct_size](uint8_t *a, uint8_t *b) {
+ // FIXME: faster?
+ for (size_t i = 0; i < struct_size; i++) { std::swap(a[i], b[i]); }
+ });
+ } else {
+ auto v = reinterpret_cast<Vector<Offset<Table>> *>(
+ builder_.GetCurrentBufferPointer());
+ // Here also can't use std::sort. We do have an iterator type for it,
+ // but it is non-standard as it will dereference the offsets, and thus
+ // can't be used to swap elements.
+ if (key->value.type.base_type == BASE_TYPE_STRING) {
+ SimpleQsort<Offset<Table>>(
+ v->data(), v->data() + v->size(), 1,
+ [key](const Offset<Table> *_a, const Offset<Table> *_b) -> bool {
+ return CompareTablesByStringKey(_a, _b, *key);
+ },
+ SwapSerializedTables);
+ } else {
+ SimpleQsort<Offset<Table>>(
+ v->data(), v->data() + v->size(), 1,
+ [key](const Offset<Table> *_a, const Offset<Table> *_b) -> bool {
+ return CompareTablesByScalarKey(_a, _b, *key);
+ },
+ SwapSerializedTables);
+ }
+ }
+ }
+ return NoError();
+}
+
+CheckedError Parser::ParseArray(Value &array) {
+ std::vector<Value> stack;
+ FlatBufferBuilder builder;
+ const auto &type = array.type.VectorType();
+ auto length = array.type.fixed_length;
+ uoffset_t count = 0;
+ auto err = ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
+ vector_emplace_back(&stack, Value());
+ auto &val = stack.back();
+ val.type = type;
+ if (IsStruct(type)) {
+ ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr));
+ } else {
+ ECHECK(ParseSingleValue(nullptr, val, false));
+ }
+ return NoError();
+ });
+ ECHECK(err);
+ if (length != count) return Error("Fixed-length array size is incorrect.");
+
+ for (auto it = stack.rbegin(); it != stack.rend(); ++it) {
+ auto &val = *it;
+ // clang-format off
+ switch (val.type.base_type) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_ ## ENUM: \
+ if (IsStruct(val.type)) { \
+ SerializeStruct(builder, *val.type.struct_def, val); \
+ } else { \
+ CTYPE elem; \
+ ECHECK(atot(val.constant.c_str(), *this, &elem)); \
+ builder.PushElement(elem); \
+ } \
+ break;
+ FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ // clang-format on
+ }
+
+ array.constant.assign(
+ reinterpret_cast<const char *>(builder.GetCurrentBufferPointer()),
+ InlineSize(array.type));
+ return NoError();
+}
+
+CheckedError Parser::ParseNestedFlatbuffer(Value &val, FieldDef *field,
+ size_t fieldn,
+ const StructDef *parent_struct_def) {
+ if (token_ == '[') { // backwards compat for 'legacy' ubyte buffers
+ ECHECK(ParseAnyValue(val, field, fieldn, parent_struct_def, 0));
+ } else {
+ auto cursor_at_value_begin = cursor_;
+ ECHECK(SkipAnyJsonValue());
+ std::string substring(cursor_at_value_begin - 1, cursor_ - 1);
+
+ // Create and initialize new parser
+ Parser nested_parser;
+ FLATBUFFERS_ASSERT(field->nested_flatbuffer);
+ nested_parser.root_struct_def_ = field->nested_flatbuffer;
+ nested_parser.enums_ = enums_;
+ nested_parser.opts = opts;
+ nested_parser.uses_flexbuffers_ = uses_flexbuffers_;
+ nested_parser.parse_depth_counter_ = parse_depth_counter_;
+ // Parse JSON substring into new flatbuffer builder using nested_parser
+ bool ok = nested_parser.Parse(substring.c_str(), nullptr, nullptr);
+
+ // Clean nested_parser to avoid deleting the elements in
+ // the SymbolTables on destruction
+ nested_parser.enums_.dict.clear();
+ nested_parser.enums_.vec.clear();
+
+ if (!ok) { ECHECK(Error(nested_parser.error_)); }
+ // Force alignment for nested flatbuffer
+ builder_.ForceVectorAlignment(
+ nested_parser.builder_.GetSize(), sizeof(uint8_t),
+ nested_parser.builder_.GetBufferMinAlignment());
+
+ auto off = builder_.CreateVector(nested_parser.builder_.GetBufferPointer(),
+ nested_parser.builder_.GetSize());
+ val.constant = NumToString(off.o);
+ }
+ return NoError();
+}
+
+CheckedError Parser::ParseMetaData(SymbolTable<Value> *attributes) {
+ if (Is('(')) {
+ NEXT();
+ for (;;) {
+ auto name = attribute_;
+ if (false == (Is(kTokenIdentifier) || Is(kTokenStringConstant)))
+ return Error("attribute name must be either identifier or string: " +
+ name);
+ if (known_attributes_.find(name) == known_attributes_.end())
+ return Error("user define attributes must be declared before use: " +
+ name);
+ NEXT();
+ auto e = new Value();
+ if (attributes->Add(name, e)) Warning("attribute already found: " + name);
+ if (Is(':')) {
+ NEXT();
+ ECHECK(ParseSingleValue(&name, *e, true));
+ }
+ if (Is(')')) {
+ NEXT();
+ break;
+ }
+ EXPECT(',');
+ }
+ }
+ return NoError();
+}
+
+CheckedError Parser::ParseEnumFromString(const Type &type,
+ std::string *result) {
+ const auto base_type =
+ type.enum_def ? type.enum_def->underlying_type.base_type : type.base_type;
+ if (!IsInteger(base_type)) return Error("not a valid value for this field");
+ uint64_t u64 = 0;
+ for (size_t pos = 0; pos != std::string::npos;) {
+ const auto delim = attribute_.find_first_of(' ', pos);
+ const auto last = (std::string::npos == delim);
+ auto word = attribute_.substr(pos, !last ? delim - pos : std::string::npos);
+ pos = !last ? delim + 1 : std::string::npos;
+ const EnumVal *ev = nullptr;
+ if (type.enum_def) {
+ ev = type.enum_def->Lookup(word);
+ } else {
+ auto dot = word.find_first_of('.');
+ if (std::string::npos == dot)
+ return Error("enum values need to be qualified by an enum type");
+ auto enum_def_str = word.substr(0, dot);
+ const auto enum_def = LookupEnum(enum_def_str);
+ if (!enum_def) return Error("unknown enum: " + enum_def_str);
+ auto enum_val_str = word.substr(dot + 1);
+ ev = enum_def->Lookup(enum_val_str);
+ }
+ if (!ev) return Error("unknown enum value: " + word);
+ u64 |= ev->GetAsUInt64();
+ }
+ *result = IsUnsigned(base_type) ? NumToString(u64)
+ : NumToString(static_cast<int64_t>(u64));
+ return NoError();
+}
+
+CheckedError Parser::ParseHash(Value &e, FieldDef *field) {
+ FLATBUFFERS_ASSERT(field);
+ Value *hash_name = field->attributes.Lookup("hash");
+ switch (e.type.base_type) {
+ case BASE_TYPE_SHORT: {
+ auto hash = FindHashFunction16(hash_name->constant.c_str());
+ int16_t hashed_value = static_cast<int16_t>(hash(attribute_.c_str()));
+ e.constant = NumToString(hashed_value);
+ break;
+ }
+ case BASE_TYPE_USHORT: {
+ auto hash = FindHashFunction16(hash_name->constant.c_str());
+ uint16_t hashed_value = hash(attribute_.c_str());
+ e.constant = NumToString(hashed_value);
+ break;
+ }
+ case BASE_TYPE_INT: {
+ auto hash = FindHashFunction32(hash_name->constant.c_str());
+ int32_t hashed_value = static_cast<int32_t>(hash(attribute_.c_str()));
+ e.constant = NumToString(hashed_value);
+ break;
+ }
+ case BASE_TYPE_UINT: {
+ auto hash = FindHashFunction32(hash_name->constant.c_str());
+ uint32_t hashed_value = hash(attribute_.c_str());
+ e.constant = NumToString(hashed_value);
+ break;
+ }
+ case BASE_TYPE_LONG: {
+ auto hash = FindHashFunction64(hash_name->constant.c_str());
+ int64_t hashed_value = static_cast<int64_t>(hash(attribute_.c_str()));
+ e.constant = NumToString(hashed_value);
+ break;
+ }
+ case BASE_TYPE_ULONG: {
+ auto hash = FindHashFunction64(hash_name->constant.c_str());
+ uint64_t hashed_value = hash(attribute_.c_str());
+ e.constant = NumToString(hashed_value);
+ break;
+ }
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ NEXT();
+ return NoError();
+}
+
+CheckedError Parser::TokenError() {
+ return Error("cannot parse value starting with: " + TokenToStringId(token_));
+}
+
+// Re-pack helper (ParseSingleValue) to normalize defaults of scalars.
+template<typename T> inline void SingleValueRepack(Value &e, T val) {
+ // Remove leading zeros.
+ if (IsInteger(e.type.base_type)) { e.constant = NumToString(val); }
+}
+#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
+// Normalize defaults NaN to unsigned quiet-NaN(0) if value was parsed from
+// hex-float literal.
+static inline void SingleValueRepack(Value &e, float val) {
+ if (val != val) e.constant = "nan";
+}
+static inline void SingleValueRepack(Value &e, double val) {
+ if (val != val) e.constant = "nan";
+}
+#endif
+
+CheckedError Parser::ParseFunction(const std::string *name, Value &e) {
+ ParseDepthGuard depth_guard(this);
+ ECHECK(depth_guard.Check());
+
+ // Copy name, attribute will be changed on NEXT().
+ const auto functionname = attribute_;
+ if (!IsFloat(e.type.base_type)) {
+ return Error(functionname + ": type of argument mismatch, expecting: " +
+ kTypeNames[BASE_TYPE_DOUBLE] +
+ ", found: " + kTypeNames[e.type.base_type] +
+ ", name: " + (name ? *name : "") + ", value: " + e.constant);
+ }
+ NEXT();
+ EXPECT('(');
+ ECHECK(ParseSingleValue(name, e, false));
+ EXPECT(')');
+ // calculate with double precision
+ double x, y = 0.0;
+ ECHECK(atot(e.constant.c_str(), *this, &x));
+ // clang-format off
+ auto func_match = false;
+ #define FLATBUFFERS_FN_DOUBLE(name, op) \
+ if (!func_match && functionname == name) { y = op; func_match = true; }
+ FLATBUFFERS_FN_DOUBLE("deg", x / kPi * 180);
+ FLATBUFFERS_FN_DOUBLE("rad", x * kPi / 180);
+ FLATBUFFERS_FN_DOUBLE("sin", sin(x));
+ FLATBUFFERS_FN_DOUBLE("cos", cos(x));
+ FLATBUFFERS_FN_DOUBLE("tan", tan(x));
+ FLATBUFFERS_FN_DOUBLE("asin", asin(x));
+ FLATBUFFERS_FN_DOUBLE("acos", acos(x));
+ FLATBUFFERS_FN_DOUBLE("atan", atan(x));
+ // TODO(wvo): add more useful conversion functions here.
+ #undef FLATBUFFERS_FN_DOUBLE
+ // clang-format on
+ if (true != func_match) {
+ return Error(std::string("Unknown conversion function: ") + functionname +
+ ", field name: " + (name ? *name : "") +
+ ", value: " + e.constant);
+ }
+ e.constant = NumToString(y);
+ return NoError();
+}
+
+CheckedError Parser::TryTypedValue(const std::string *name, int dtoken,
+ bool check, Value &e, BaseType req,
+ bool *destmatch) {
+ FLATBUFFERS_ASSERT(*destmatch == false && dtoken == token_);
+ *destmatch = true;
+ e.constant = attribute_;
+ // Check token match
+ if (!check) {
+ if (e.type.base_type == BASE_TYPE_NONE) {
+ e.type.base_type = req;
+ } else {
+ return Error(std::string("type mismatch: expecting: ") +
+ kTypeNames[e.type.base_type] +
+ ", found: " + kTypeNames[req] +
+ ", name: " + (name ? *name : "") + ", value: " + e.constant);
+ }
+ }
+ // The exponent suffix of hexadecimal float-point number is mandatory.
+ // A hex-integer constant is forbidden as an initializer of float number.
+ if ((kTokenFloatConstant != dtoken) && IsFloat(e.type.base_type)) {
+ const auto &s = e.constant;
+ const auto k = s.find_first_of("0123456789.");
+ if ((std::string::npos != k) && (s.length() > (k + 1)) &&
+ (s[k] == '0' && is_alpha_char(s[k + 1], 'X')) &&
+ (std::string::npos == s.find_first_of("pP", k + 2))) {
+ return Error(
+ "invalid number, the exponent suffix of hexadecimal "
+ "floating-point literals is mandatory: \"" +
+ s + "\"");
+ }
+ }
+ NEXT();
+ return NoError();
+}
+
+CheckedError Parser::ParseSingleValue(const std::string *name, Value &e,
+ bool check_now) {
+ if (token_ == '+' || token_ == '-') {
+ const char sign = static_cast<char>(token_);
+ // Get an indentifier: NAN, INF, or function name like cos/sin/deg.
+ NEXT();
+ if (token_ != kTokenIdentifier) return Error("constant name expected");
+ attribute_.insert(size_t(0), size_t(1), sign);
+ }
+
+ const auto in_type = e.type.base_type;
+ const auto is_tok_ident = (token_ == kTokenIdentifier);
+ const auto is_tok_string = (token_ == kTokenStringConstant);
+
+ // First see if this could be a conversion function.
+ if (is_tok_ident && *cursor_ == '(') { return ParseFunction(name, e); }
+
+ // clang-format off
+ auto match = false;
+
+ #define IF_ECHECK_(force, dtoken, check, req) \
+ if (!match && ((dtoken) == token_) && ((check) || 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)
+ // clang-format on
+
+ if (is_tok_ident || is_tok_string) {
+ const auto kTokenStringOrIdent = token_;
+ // The string type is a most probable type, check it first.
+ TRY_ECHECK(kTokenStringConstant, in_type == BASE_TYPE_STRING,
+ BASE_TYPE_STRING);
+
+ // avoid escaped and non-ascii in the string
+ if (!match && is_tok_string && IsScalar(in_type) &&
+ !attr_is_trivial_ascii_string_) {
+ return Error(
+ std::string("type mismatch or invalid value, an initializer of "
+ "non-string field must be trivial ASCII string: type: ") +
+ kTypeNames[in_type] + ", name: " + (name ? *name : "") +
+ ", value: " + attribute_);
+ }
+
+ // A boolean as true/false. Boolean as Integer check below.
+ if (!match && IsBool(in_type)) {
+ auto is_true = attribute_ == "true";
+ if (is_true || attribute_ == "false") {
+ attribute_ = is_true ? "1" : "0";
+ // accepts both kTokenStringConstant and kTokenIdentifier
+ TRY_ECHECK(kTokenStringOrIdent, IsBool(in_type), BASE_TYPE_BOOL);
+ }
+ }
+ // Check for optional scalars.
+ if (!match && IsScalar(in_type) && attribute_ == "null") {
+ e.constant = "null";
+ NEXT();
+ match = true;
+ }
+ // Check if this could be a string/identifier enum value.
+ // Enum can have only true integer base type.
+ if (!match && IsInteger(in_type) && !IsBool(in_type) &&
+ IsIdentifierStart(*attribute_.c_str())) {
+ ECHECK(ParseEnumFromString(e.type, &e.constant));
+ NEXT();
+ match = true;
+ }
+ // Parse a float/integer number from the string.
+ // A "scalar-in-string" value needs extra checks.
+ if (!match && is_tok_string && IsScalar(in_type)) {
+ // Strip trailing whitespaces from attribute_.
+ auto last_non_ws = attribute_.find_last_not_of(' ');
+ if (std::string::npos != last_non_ws) attribute_.resize(last_non_ws + 1);
+ if (IsFloat(e.type.base_type)) {
+ // The functions strtod() and strtof() accept both 'nan' and
+ // 'nan(number)' literals. While 'nan(number)' is rejected by the parser
+ // as an unsupported function if is_tok_ident is true.
+ if (attribute_.find_last_of(')') != std::string::npos) {
+ return Error("invalid number: " + attribute_);
+ }
+ }
+ }
+ // Float numbers or nan, inf, pi, etc.
+ TRY_ECHECK(kTokenStringOrIdent, IsFloat(in_type), BASE_TYPE_FLOAT);
+ // An integer constant in string.
+ TRY_ECHECK(kTokenStringOrIdent, IsInteger(in_type), BASE_TYPE_INT);
+ // Unknown tokens will be interpreted as string type.
+ // An attribute value may be a scalar or string constant.
+ FORCE_ECHECK(kTokenStringConstant, in_type == BASE_TYPE_STRING,
+ BASE_TYPE_STRING);
+ } else {
+ // Try a float number.
+ TRY_ECHECK(kTokenFloatConstant, IsFloat(in_type), BASE_TYPE_FLOAT);
+ // Integer token can init any scalar (integer of float).
+ FORCE_ECHECK(kTokenIntegerConstant, IsScalar(in_type), BASE_TYPE_INT);
+ }
+ // Match empty vectors for default-empty-vectors.
+ if (!match && IsVector(e.type) && token_ == '[') {
+ NEXT();
+ if (token_ != ']') { return Error("Expected `]` in vector default"); }
+ NEXT();
+ match = true;
+ e.constant = "[]";
+ }
+
+#undef FORCE_ECHECK
+#undef TRY_ECHECK
+#undef IF_ECHECK_
+
+ if (!match) {
+ std::string msg;
+ msg += "Cannot assign token starting with '" + TokenToStringId(token_) +
+ "' to value of <" + std::string(kTypeNames[in_type]) + "> type.";
+ return Error(msg);
+ }
+ const auto match_type = e.type.base_type; // may differ from in_type
+ // The check_now flag must be true when parse a fbs-schema.
+ // This flag forces to check default scalar values or metadata of field.
+ // For JSON parser the flag should be false.
+ // If it is set for JSON each value will be checked twice (see ParseTable).
+ // Special case 'null' since atot can't handle that.
+ if (check_now && IsScalar(match_type) && e.constant != "null") {
+ // clang-format off
+ switch (match_type) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_ ## ENUM: {\
+ CTYPE val; \
+ ECHECK(atot(e.constant.c_str(), *this, &val)); \
+ SingleValueRepack(e, val); \
+ break; }
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ default: break;
+ }
+ // clang-format on
+ }
+ return NoError();
+}
+
+StructDef *Parser::LookupCreateStruct(const std::string &name,
+ bool create_if_new, bool definition) {
+ std::string qualified_name = current_namespace_->GetFullyQualifiedName(name);
+ // See if it exists pre-declared by an unqualified use.
+ auto struct_def = LookupStruct(name);
+ if (struct_def && struct_def->predecl) {
+ if (definition) {
+ // Make sure it has the current namespace, and is registered under its
+ // qualified name.
+ struct_def->defined_namespace = current_namespace_;
+ structs_.Move(name, qualified_name);
+ }
+ return struct_def;
+ }
+ // See if it exists pre-declared by an qualified use.
+ struct_def = LookupStruct(qualified_name);
+ if (struct_def && struct_def->predecl) {
+ if (definition) {
+ // Make sure it has the current namespace.
+ struct_def->defined_namespace = current_namespace_;
+ }
+ return struct_def;
+ }
+ if (!definition && !struct_def) {
+ struct_def = LookupStructThruParentNamespaces(name);
+ }
+ if (!struct_def && create_if_new) {
+ struct_def = new StructDef();
+ if (definition) {
+ structs_.Add(qualified_name, struct_def);
+ struct_def->name = name;
+ struct_def->defined_namespace = current_namespace_;
+ } else {
+ // Not a definition.
+ // Rather than failing, we create a "pre declared" StructDef, due to
+ // circular references, and check for errors at the end of parsing.
+ // It is defined in the current namespace, as the best guess what the
+ // final namespace will be.
+ structs_.Add(name, struct_def);
+ struct_def->name = name;
+ struct_def->defined_namespace = current_namespace_;
+ struct_def->original_location.reset(
+ new std::string(file_being_parsed_ + ":" + NumToString(line_)));
+ }
+ }
+ return struct_def;
+}
+
+const EnumVal *EnumDef::MinValue() const {
+ return vals.vec.empty() ? nullptr : vals.vec.front();
+}
+const EnumVal *EnumDef::MaxValue() const {
+ return vals.vec.empty() ? nullptr : vals.vec.back();
+}
+
+template<typename T> static uint64_t EnumDistanceImpl(T e1, T e2) {
+ if (e1 < e2) { std::swap(e1, e2); } // use std for scalars
+ // Signed overflow may occur, use unsigned calculation.
+ // The unsigned overflow is well-defined by C++ standard (modulo 2^n).
+ return static_cast<uint64_t>(e1) - static_cast<uint64_t>(e2);
+}
+
+uint64_t EnumDef::Distance(const EnumVal *v1, const EnumVal *v2) const {
+ return IsUInt64() ? EnumDistanceImpl(v1->GetAsUInt64(), v2->GetAsUInt64())
+ : EnumDistanceImpl(v1->GetAsInt64(), v2->GetAsInt64());
+}
+
+std::string EnumDef::AllFlags() const {
+ FLATBUFFERS_ASSERT(attributes.Lookup("bit_flags"));
+ uint64_t u64 = 0;
+ for (auto it = Vals().begin(); it != Vals().end(); ++it) {
+ u64 |= (*it)->GetAsUInt64();
+ }
+ return IsUInt64() ? NumToString(u64) : NumToString(static_cast<int64_t>(u64));
+}
+
+EnumVal *EnumDef::ReverseLookup(int64_t enum_idx,
+ bool skip_union_default) const {
+ auto skip_first = static_cast<int>(is_union && skip_union_default);
+ for (auto it = Vals().begin() + skip_first; it != Vals().end(); ++it) {
+ if ((*it)->GetAsInt64() == enum_idx) { return *it; }
+ }
+ return nullptr;
+}
+
+EnumVal *EnumDef::FindByValue(const std::string &constant) const {
+ int64_t i64;
+ auto done = false;
+ if (IsUInt64()) {
+ uint64_t u64; // avoid reinterpret_cast of pointers
+ done = StringToNumber(constant.c_str(), &u64);
+ i64 = static_cast<int64_t>(u64);
+ } else {
+ done = StringToNumber(constant.c_str(), &i64);
+ }
+ FLATBUFFERS_ASSERT(done);
+ if (!done) return nullptr;
+ return ReverseLookup(i64, false);
+}
+
+void EnumDef::SortByValue() {
+ auto &v = vals.vec;
+ if (IsUInt64())
+ std::sort(v.begin(), v.end(), [](const EnumVal *e1, const EnumVal *e2) {
+ return e1->GetAsUInt64() < e2->GetAsUInt64();
+ });
+ else
+ std::sort(v.begin(), v.end(), [](const EnumVal *e1, const EnumVal *e2) {
+ return e1->GetAsInt64() < e2->GetAsInt64();
+ });
+}
+
+void EnumDef::RemoveDuplicates() {
+ // This method depends form SymbolTable implementation!
+ // 1) vals.vec - owner (raw pointer)
+ // 2) vals.dict - access map
+ auto first = vals.vec.begin();
+ auto last = vals.vec.end();
+ if (first == last) return;
+ auto result = first;
+ while (++first != last) {
+ if ((*result)->value != (*first)->value) {
+ *(++result) = *first;
+ } else {
+ auto ev = *first;
+ for (auto it = vals.dict.begin(); it != vals.dict.end(); ++it) {
+ if (it->second == ev) it->second = *result; // reassign
+ }
+ delete ev; // delete enum value
+ *first = nullptr;
+ }
+ }
+ vals.vec.erase(++result, last);
+}
+
+template<typename T> void EnumDef::ChangeEnumValue(EnumVal *ev, T new_value) {
+ ev->value = static_cast<int64_t>(new_value);
+}
+
+namespace EnumHelper {
+template<BaseType E> struct EnumValType { typedef int64_t type; };
+template<> struct EnumValType<BASE_TYPE_ULONG> { typedef uint64_t type; };
+} // namespace EnumHelper
+
+struct EnumValBuilder {
+ EnumVal *CreateEnumerator(const std::string &ev_name) {
+ FLATBUFFERS_ASSERT(!temp);
+ auto first = enum_def.vals.vec.empty();
+ user_value = first;
+ temp = new EnumVal(ev_name, first ? 0 : enum_def.vals.vec.back()->value);
+ return temp;
+ }
+
+ EnumVal *CreateEnumerator(const std::string &ev_name, int64_t val) {
+ FLATBUFFERS_ASSERT(!temp);
+ user_value = true;
+ temp = new EnumVal(ev_name, val);
+ return temp;
+ }
+
+ FLATBUFFERS_CHECKED_ERROR AcceptEnumerator(const std::string &name) {
+ FLATBUFFERS_ASSERT(temp);
+ ECHECK(ValidateValue(&temp->value, false == user_value));
+ FLATBUFFERS_ASSERT((temp->union_type.enum_def == nullptr) ||
+ (temp->union_type.enum_def == &enum_def));
+ auto not_unique = enum_def.vals.Add(name, temp);
+ temp = nullptr;
+ if (not_unique) return parser.Error("enum value already exists: " + name);
+ return NoError();
+ }
+
+ FLATBUFFERS_CHECKED_ERROR AcceptEnumerator() {
+ return AcceptEnumerator(temp->name);
+ }
+
+ FLATBUFFERS_CHECKED_ERROR AssignEnumeratorValue(const std::string &value) {
+ user_value = true;
+ auto fit = false;
+ if (enum_def.IsUInt64()) {
+ uint64_t u64;
+ fit = StringToNumber(value.c_str(), &u64);
+ temp->value = static_cast<int64_t>(u64); // well-defined since C++20.
+ } else {
+ int64_t i64;
+ fit = StringToNumber(value.c_str(), &i64);
+ temp->value = i64;
+ }
+ if (!fit) return parser.Error("enum value does not fit, \"" + value + "\"");
+ return NoError();
+ }
+
+ template<BaseType E, typename CTYPE>
+ inline FLATBUFFERS_CHECKED_ERROR ValidateImpl(int64_t *ev, int m) {
+ typedef typename EnumHelper::EnumValType<E>::type T; // int64_t or uint64_t
+ static_assert(sizeof(T) == sizeof(int64_t), "invalid EnumValType");
+ const auto v = static_cast<T>(*ev);
+ auto up = static_cast<T>((flatbuffers::numeric_limits<CTYPE>::max)());
+ auto dn = static_cast<T>((flatbuffers::numeric_limits<CTYPE>::lowest)());
+ if (v < dn || v > (up - m)) {
+ return parser.Error("enum value does not fit, \"" + NumToString(v) +
+ (m ? " + 1\"" : "\"") + " out of " +
+ TypeToIntervalString<CTYPE>());
+ }
+ *ev = static_cast<int64_t>(v + m); // well-defined since C++20.
+ return NoError();
+ }
+
+ FLATBUFFERS_CHECKED_ERROR ValidateValue(int64_t *ev, bool next) {
+ // clang-format off
+ switch (enum_def.underlying_type.base_type) {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_##ENUM: { \
+ if (!IsInteger(BASE_TYPE_##ENUM)) break; \
+ return ValidateImpl<BASE_TYPE_##ENUM, CTYPE>(ev, next ? 1 : 0); \
+ }
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
+ #undef FLATBUFFERS_TD
+ default: break;
+ }
+ // clang-format on
+ return parser.Error("fatal: invalid enum underlying type");
+ }
+
+ EnumValBuilder(Parser &_parser, EnumDef &_enum_def)
+ : parser(_parser),
+ enum_def(_enum_def),
+ temp(nullptr),
+ user_value(false) {}
+
+ ~EnumValBuilder() { delete temp; }
+
+ Parser &parser;
+ EnumDef &enum_def;
+ EnumVal *temp;
+ bool user_value;
+};
+
+CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest) {
+ std::vector<std::string> enum_comment = doc_comment_;
+ NEXT();
+ std::string enum_name = attribute_;
+ EXPECT(kTokenIdentifier);
+ EnumDef *enum_def;
+ ECHECK(StartEnum(enum_name, is_union, &enum_def));
+ enum_def->doc_comment = enum_comment;
+ if (!is_union && !opts.proto_mode) {
+ // Give specialized error message, since this type spec used to
+ // be optional in the first FlatBuffers release.
+ if (!Is(':')) {
+ return Error(
+ "must specify the underlying integer type for this"
+ " enum (e.g. \': short\', which was the default).");
+ } else {
+ NEXT();
+ }
+ // Specify the integer type underlying this enum.
+ ECHECK(ParseType(enum_def->underlying_type));
+ if (!IsInteger(enum_def->underlying_type.base_type) ||
+ IsBool(enum_def->underlying_type.base_type))
+ return Error("underlying enum type must be integral");
+ // Make this type refer back to the enum it was derived from.
+ enum_def->underlying_type.enum_def = enum_def;
+ }
+ ECHECK(ParseMetaData(&enum_def->attributes));
+ const auto underlying_type = enum_def->underlying_type.base_type;
+ if (enum_def->attributes.Lookup("bit_flags") &&
+ !IsUnsigned(underlying_type)) {
+ // todo: Convert to the Error in the future?
+ Warning("underlying type of bit_flags enum must be unsigned");
+ }
+ EnumValBuilder evb(*this, *enum_def);
+ EXPECT('{');
+ // A lot of code generatos expect that an enum is not-empty.
+ if ((is_union || Is('}')) && !opts.proto_mode) {
+ evb.CreateEnumerator("NONE");
+ ECHECK(evb.AcceptEnumerator());
+ }
+ std::set<std::pair<BaseType, StructDef *>> union_types;
+ while (!Is('}')) {
+ if (opts.proto_mode && attribute_ == "option") {
+ ECHECK(ParseProtoOption());
+ } else {
+ auto &ev = *evb.CreateEnumerator(attribute_);
+ auto full_name = ev.name;
+ ev.doc_comment = doc_comment_;
+ EXPECT(kTokenIdentifier);
+ if (is_union) {
+ ECHECK(ParseNamespacing(&full_name, &ev.name));
+ if (opts.union_value_namespacing) {
+ // Since we can't namespace the actual enum identifiers, turn
+ // namespace parts into part of the identifier.
+ ev.name = full_name;
+ std::replace(ev.name.begin(), ev.name.end(), '.', '_');
+ }
+ if (Is(':')) {
+ NEXT();
+ ECHECK(ParseType(ev.union_type));
+ if (ev.union_type.base_type != BASE_TYPE_STRUCT &&
+ ev.union_type.base_type != BASE_TYPE_STRING)
+ return Error("union value type may only be table/struct/string");
+ } else {
+ ev.union_type = Type(BASE_TYPE_STRUCT, LookupCreateStruct(full_name));
+ }
+ if (!enum_def->uses_multiple_type_instances) {
+ auto ins = union_types.insert(std::make_pair(
+ ev.union_type.base_type, ev.union_type.struct_def));
+ enum_def->uses_multiple_type_instances = (false == ins.second);
+ }
+ }
+
+ if (Is('=')) {
+ NEXT();
+ ECHECK(evb.AssignEnumeratorValue(attribute_));
+ EXPECT(kTokenIntegerConstant);
+ }
+
+ ECHECK(evb.AcceptEnumerator());
+
+ if (opts.proto_mode && Is('[')) {
+ NEXT();
+ // ignore attributes on enums.
+ while (token_ != ']') NEXT();
+ NEXT();
+ }
+ }
+ if (!Is(opts.proto_mode ? ';' : ',')) break;
+ NEXT();
+ }
+ EXPECT('}');
+
+ // At this point, the enum can be empty if input is invalid proto-file.
+ if (!enum_def->size())
+ return Error("incomplete enum declaration, values not found");
+
+ if (enum_def->attributes.Lookup("bit_flags")) {
+ const auto base_width = static_cast<uint64_t>(8 * SizeOf(underlying_type));
+ for (auto it = enum_def->Vals().begin(); it != enum_def->Vals().end();
+ ++it) {
+ auto ev = *it;
+ const auto u = ev->GetAsUInt64();
+ // Stop manipulations with the sign.
+ if (!IsUnsigned(underlying_type) && u == (base_width - 1))
+ return Error("underlying type of bit_flags enum must be unsigned");
+ if (u >= base_width)
+ return Error("bit flag out of range of underlying integral type");
+ enum_def->ChangeEnumValue(ev, 1ULL << u);
+ }
+ }
+
+ enum_def->SortByValue(); // Must be sorted to use MinValue/MaxValue.
+
+ // Ensure enum value uniqueness.
+ auto prev_it = enum_def->Vals().begin();
+ for (auto it = prev_it + 1; it != enum_def->Vals().end(); ++it) {
+ auto prev_ev = *prev_it;
+ auto ev = *it;
+ if (prev_ev->GetAsUInt64() == ev->GetAsUInt64())
+ return Error("all enum values must be unique: " + prev_ev->name +
+ " and " + ev->name + " are both " +
+ NumToString(ev->GetAsInt64()));
+ }
+
+ if (dest) *dest = enum_def;
+ types_.Add(current_namespace_->GetFullyQualifiedName(enum_def->name),
+ new Type(BASE_TYPE_UNION, nullptr, enum_def));
+ return NoError();
+}
+
+CheckedError Parser::StartStruct(const std::string &name, StructDef **dest) {
+ auto &struct_def = *LookupCreateStruct(name, true, true);
+ if (!struct_def.predecl) return Error("datatype already exists: " + name);
+ struct_def.predecl = false;
+ struct_def.name = name;
+ struct_def.file = file_being_parsed_;
+ // Move this struct to the back of the vector just in case it was predeclared,
+ // to preserve declaration order.
+ *std::remove(structs_.vec.begin(), structs_.vec.end(), &struct_def) =
+ &struct_def;
+ *dest = &struct_def;
+ return NoError();
+}
+
+CheckedError Parser::CheckClash(std::vector<FieldDef *> &fields,
+ StructDef *struct_def, const char *suffix,
+ BaseType basetype) {
+ auto len = strlen(suffix);
+ for (auto it = fields.begin(); it != fields.end(); ++it) {
+ auto &fname = (*it)->name;
+ if (fname.length() > len &&
+ fname.compare(fname.length() - len, len, suffix) == 0 &&
+ (*it)->value.type.base_type != BASE_TYPE_UTYPE) {
+ auto field =
+ struct_def->fields.Lookup(fname.substr(0, fname.length() - len));
+ if (field && field->value.type.base_type == basetype)
+ return Error("Field " + fname +
+ " would clash with generated functions for field " +
+ field->name);
+ }
+ }
+ return NoError();
+}
+
+bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts) {
+ static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
+ IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster |
+ IDLOptions::kKotlin | IDLOptions::kCpp | IDLOptions::kJava |
+ IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kBinary;
+ unsigned long langs = opts.lang_to_generate;
+ return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs);
+}
+bool Parser::SupportsOptionalScalars() const {
+ // Check in general if a language isn't specified.
+ return opts.lang_to_generate == 0 || SupportsOptionalScalars(opts);
+}
+
+bool Parser::SupportsDefaultVectorsAndStrings() const {
+ static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
+ IDLOptions::kRust | IDLOptions::kSwift;
+ return !(opts.lang_to_generate & ~supported_langs);
+}
+
+bool Parser::SupportsAdvancedUnionFeatures() const {
+ return opts.lang_to_generate != 0 &&
+ (opts.lang_to_generate &
+ ~(IDLOptions::kCpp | IDLOptions::kTs | IDLOptions::kPhp |
+ IDLOptions::kJava | IDLOptions::kCSharp | IDLOptions::kKotlin |
+ IDLOptions::kBinary | IDLOptions::kSwift)) == 0;
+}
+
+bool Parser::SupportsAdvancedArrayFeatures() const {
+ return (opts.lang_to_generate &
+ ~(IDLOptions::kCpp | IDLOptions::kPython | IDLOptions::kJava |
+ IDLOptions::kCSharp | IDLOptions::kJsonSchema | IDLOptions::kJson |
+ IDLOptions::kBinary | IDLOptions::kRust)) == 0;
+}
+
+Namespace *Parser::UniqueNamespace(Namespace *ns) {
+ for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
+ if (ns->components == (*it)->components) {
+ delete ns;
+ return *it;
+ }
+ }
+ namespaces_.push_back(ns);
+ return ns;
+}
+
+std::string Parser::UnqualifiedName(const std::string &full_qualified_name) {
+ Namespace *ns = new Namespace();
+
+ std::size_t current, previous = 0;
+ current = full_qualified_name.find('.');
+ while (current != std::string::npos) {
+ ns->components.push_back(
+ full_qualified_name.substr(previous, current - previous));
+ previous = current + 1;
+ current = full_qualified_name.find('.', previous);
+ }
+ current_namespace_ = UniqueNamespace(ns);
+ return full_qualified_name.substr(previous, current - previous);
+}
+
+static bool compareFieldDefs(const FieldDef *a, const FieldDef *b) {
+ auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str());
+ auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str());
+ return a_id < b_id;
+}
+
+CheckedError Parser::ParseDecl() {
+ std::vector<std::string> dc = doc_comment_;
+ bool fixed = IsIdent("struct");
+ if (!fixed && !IsIdent("table")) return Error("declaration expected");
+ NEXT();
+ std::string name = attribute_;
+ EXPECT(kTokenIdentifier);
+ StructDef *struct_def;
+ ECHECK(StartStruct(name, &struct_def));
+ struct_def->doc_comment = dc;
+ struct_def->fixed = fixed;
+ ECHECK(ParseMetaData(&struct_def->attributes));
+ struct_def->sortbysize =
+ struct_def->attributes.Lookup("original_order") == nullptr && !fixed;
+ EXPECT('{');
+ while (token_ != '}') ECHECK(ParseField(*struct_def));
+ if (fixed) {
+ const auto force_align = struct_def->attributes.Lookup("force_align");
+ if (force_align) {
+ size_t align;
+ ECHECK(ParseAlignAttribute(force_align->constant, struct_def->minalign,
+ &align));
+ struct_def->minalign = align;
+ }
+ if (!struct_def->bytesize) return Error("size 0 structs not allowed");
+ }
+ struct_def->PadLastField(struct_def->minalign);
+ // Check if this is a table that has manual id assignments
+ auto &fields = struct_def->fields.vec;
+ if (!fixed && fields.size()) {
+ size_t num_id_fields = 0;
+ for (auto it = fields.begin(); it != fields.end(); ++it) {
+ if ((*it)->attributes.Lookup("id")) num_id_fields++;
+ }
+ // If any fields have ids..
+ if (num_id_fields || opts.require_explicit_ids) {
+ // Then all fields must have them.
+ if (num_id_fields != fields.size()) {
+ if (opts.require_explicit_ids) {
+ return Error(
+ "all fields must have an 'id' attribute when "
+ "--require-explicit-ids is used");
+ } else {
+ return Error(
+ "either all fields or no fields must have an 'id' attribute");
+ }
+ }
+ // Simply sort by id, then the fields are the same as if no ids had
+ // been specified.
+ std::sort(fields.begin(), fields.end(), compareFieldDefs);
+ // Verify we have a contiguous set, and reassign vtable offsets.
+ FLATBUFFERS_ASSERT(fields.size() <=
+ flatbuffers::numeric_limits<voffset_t>::max());
+ for (voffset_t i = 0; i < static_cast<voffset_t>(fields.size()); i++) {
+ auto &field = *fields[i];
+ const auto &id_str = field.attributes.Lookup("id")->constant;
+ // Metadata values have a dynamic type, they can be `float`, 'int', or
+ // 'string`.
+ // The FieldIndexToOffset(i) expects the voffset_t so `id` is limited by
+ // this type.
+ voffset_t id = 0;
+ const auto done = !atot(id_str.c_str(), *this, &id).Check();
+ if (!done)
+ return Error("field id\'s must be non-negative number, field: " +
+ field.name + ", id: " + id_str);
+ if (i != id)
+ return Error("field id\'s must be consecutive from 0, id " +
+ NumToString(i) + " missing or set twice, field: " +
+ field.name + ", id: " + id_str);
+ field.value.offset = FieldIndexToOffset(i);
+ }
+ }
+ }
+
+ ECHECK(
+ CheckClash(fields, struct_def, UnionTypeFieldSuffix(), BASE_TYPE_UNION));
+ ECHECK(CheckClash(fields, struct_def, "Type", BASE_TYPE_UNION));
+ ECHECK(CheckClash(fields, struct_def, "_length", BASE_TYPE_VECTOR));
+ ECHECK(CheckClash(fields, struct_def, "Length", BASE_TYPE_VECTOR));
+ ECHECK(CheckClash(fields, struct_def, "_byte_vector", BASE_TYPE_STRING));
+ ECHECK(CheckClash(fields, struct_def, "ByteVector", BASE_TYPE_STRING));
+ EXPECT('}');
+ types_.Add(current_namespace_->GetFullyQualifiedName(struct_def->name),
+ new Type(BASE_TYPE_STRUCT, struct_def, nullptr));
+ return NoError();
+}
+
+CheckedError Parser::ParseService() {
+ std::vector<std::string> service_comment = doc_comment_;
+ NEXT();
+ auto service_name = attribute_;
+ EXPECT(kTokenIdentifier);
+ auto &service_def = *new ServiceDef();
+ service_def.name = service_name;
+ service_def.file = file_being_parsed_;
+ service_def.doc_comment = service_comment;
+ service_def.defined_namespace = current_namespace_;
+ if (services_.Add(current_namespace_->GetFullyQualifiedName(service_name),
+ &service_def))
+ return Error("service already exists: " + service_name);
+ ECHECK(ParseMetaData(&service_def.attributes));
+ EXPECT('{');
+ do {
+ std::vector<std::string> doc_comment = doc_comment_;
+ auto rpc_name = attribute_;
+ EXPECT(kTokenIdentifier);
+ EXPECT('(');
+ Type reqtype, resptype;
+ ECHECK(ParseTypeIdent(reqtype));
+ EXPECT(')');
+ EXPECT(':');
+ ECHECK(ParseTypeIdent(resptype));
+ if (reqtype.base_type != BASE_TYPE_STRUCT || reqtype.struct_def->fixed ||
+ resptype.base_type != BASE_TYPE_STRUCT || resptype.struct_def->fixed)
+ return Error("rpc request and response types must be tables");
+ auto &rpc = *new RPCCall();
+ rpc.name = rpc_name;
+ rpc.request = reqtype.struct_def;
+ rpc.response = resptype.struct_def;
+ rpc.doc_comment = doc_comment;
+ if (service_def.calls.Add(rpc_name, &rpc))
+ return Error("rpc already exists: " + rpc_name);
+ ECHECK(ParseMetaData(&rpc.attributes));
+ EXPECT(';');
+ } while (token_ != '}');
+ NEXT();
+ return NoError();
+}
+
+bool Parser::SetRootType(const char *name) {
+ root_struct_def_ = LookupStruct(name);
+ if (!root_struct_def_)
+ root_struct_def_ =
+ LookupStruct(current_namespace_->GetFullyQualifiedName(name));
+ return root_struct_def_ != nullptr;
+}
+
+void Parser::MarkGenerated() {
+ // This function marks all existing definitions as having already
+ // been generated, which signals no code for included files should be
+ // generated.
+ for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) {
+ (*it)->generated = true;
+ }
+ for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) {
+ if (!(*it)->predecl) { (*it)->generated = true; }
+ }
+ for (auto it = services_.vec.begin(); it != services_.vec.end(); ++it) {
+ (*it)->generated = true;
+ }
+}
+
+CheckedError Parser::ParseNamespace() {
+ NEXT();
+ auto ns = new Namespace();
+ namespaces_.push_back(ns); // Store it here to not leak upon error.
+ if (token_ != ';') {
+ for (;;) {
+ ns->components.push_back(attribute_);
+ EXPECT(kTokenIdentifier);
+ if (Is('.')) NEXT() else break;
+ }
+ }
+ namespaces_.pop_back();
+ current_namespace_ = UniqueNamespace(ns);
+ EXPECT(';');
+ return NoError();
+}
+
+// Best effort parsing of .proto declarations, with the aim to turn them
+// in the closest corresponding FlatBuffer equivalent.
+// We parse everything as identifiers instead of keywords, since we don't
+// want protobuf keywords to become invalid identifiers in FlatBuffers.
+CheckedError Parser::ParseProtoDecl() {
+ bool isextend = IsIdent("extend");
+ if (IsIdent("package")) {
+ // These are identical in syntax to FlatBuffer's namespace decl.
+ ECHECK(ParseNamespace());
+ } else if (IsIdent("message") || isextend) {
+ std::vector<std::string> struct_comment = doc_comment_;
+ NEXT();
+ StructDef *struct_def = nullptr;
+ Namespace *parent_namespace = nullptr;
+ if (isextend) {
+ if (Is('.')) NEXT(); // qualified names may start with a . ?
+ auto id = attribute_;
+ EXPECT(kTokenIdentifier);
+ ECHECK(ParseNamespacing(&id, nullptr));
+ struct_def = LookupCreateStruct(id, false);
+ if (!struct_def)
+ return Error("cannot extend unknown message type: " + id);
+ } else {
+ std::string name = attribute_;
+ EXPECT(kTokenIdentifier);
+ ECHECK(StartStruct(name, &struct_def));
+ // Since message definitions can be nested, we create a new namespace.
+ auto ns = new Namespace();
+ // Copy of current namespace.
+ *ns = *current_namespace_;
+ // But with current message name.
+ ns->components.push_back(name);
+ ns->from_table++;
+ parent_namespace = current_namespace_;
+ current_namespace_ = UniqueNamespace(ns);
+ }
+ struct_def->doc_comment = struct_comment;
+ ECHECK(ParseProtoFields(struct_def, isextend, false));
+ if (!isextend) { current_namespace_ = parent_namespace; }
+ if (Is(';')) NEXT();
+ } else if (IsIdent("enum")) {
+ // These are almost the same, just with different terminator:
+ EnumDef *enum_def;
+ ECHECK(ParseEnum(false, &enum_def));
+ if (Is(';')) NEXT();
+ // Temp: remove any duplicates, as .fbs files can't handle them.
+ enum_def->RemoveDuplicates();
+ } else if (IsIdent("syntax")) { // Skip these.
+ NEXT();
+ EXPECT('=');
+ EXPECT(kTokenStringConstant);
+ EXPECT(';');
+ } else if (IsIdent("option")) { // Skip these.
+ ECHECK(ParseProtoOption());
+ EXPECT(';');
+ } else if (IsIdent("service")) { // Skip these.
+ NEXT();
+ EXPECT(kTokenIdentifier);
+ ECHECK(ParseProtoCurliesOrIdent());
+ } else {
+ return Error("don\'t know how to parse .proto declaration starting with " +
+ TokenToStringId(token_));
+ }
+ return NoError();
+}
+
+CheckedError Parser::StartEnum(const std::string &enum_name, bool is_union,
+ EnumDef **dest) {
+ auto &enum_def = *new EnumDef();
+ enum_def.name = enum_name;
+ enum_def.file = file_being_parsed_;
+ enum_def.doc_comment = doc_comment_;
+ enum_def.is_union = is_union;
+ enum_def.defined_namespace = current_namespace_;
+ if (enums_.Add(current_namespace_->GetFullyQualifiedName(enum_name),
+ &enum_def))
+ return Error("enum already exists: " + enum_name);
+ enum_def.underlying_type.base_type =
+ is_union ? BASE_TYPE_UTYPE : BASE_TYPE_INT;
+ enum_def.underlying_type.enum_def = &enum_def;
+ if (dest) *dest = &enum_def;
+ return NoError();
+}
+
+CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
+ bool inside_oneof) {
+ EXPECT('{');
+ while (token_ != '}') {
+ if (IsIdent("message") || IsIdent("extend") || IsIdent("enum")) {
+ // Nested declarations.
+ ECHECK(ParseProtoDecl());
+ } else if (IsIdent("extensions")) { // Skip these.
+ NEXT();
+ EXPECT(kTokenIntegerConstant);
+ if (Is(kTokenIdentifier)) {
+ NEXT(); // to
+ NEXT(); // num
+ }
+ EXPECT(';');
+ } else if (IsIdent("option")) { // Skip these.
+ ECHECK(ParseProtoOption());
+ EXPECT(';');
+ } else if (IsIdent("reserved")) { // Skip these.
+ NEXT();
+ while (!Is(';')) { NEXT(); } // A variety of formats, just skip.
+ NEXT();
+ } else {
+ std::vector<std::string> field_comment = doc_comment_;
+ // Parse the qualifier.
+ bool required = false;
+ bool repeated = false;
+ bool oneof = false;
+ if (!inside_oneof) {
+ if (IsIdent("optional")) {
+ // This is the default.
+ NEXT();
+ } else if (IsIdent("required")) {
+ required = true;
+ NEXT();
+ } else if (IsIdent("repeated")) {
+ repeated = true;
+ NEXT();
+ } else if (IsIdent("oneof")) {
+ oneof = true;
+ NEXT();
+ } else {
+ // can't error, proto3 allows decls without any of the above.
+ }
+ }
+ StructDef *anonymous_struct = nullptr;
+ EnumDef *oneof_union = nullptr;
+ Type type;
+ if (IsIdent("group") || oneof) {
+ if (!oneof) NEXT();
+ if (oneof && opts.proto_oneof_union) {
+ auto name = MakeCamel(attribute_, true) + "Union";
+ ECHECK(StartEnum(name, true, &oneof_union));
+ type = Type(BASE_TYPE_UNION, nullptr, oneof_union);
+ } else {
+ auto name = "Anonymous" + NumToString(anonymous_counter_++);
+ ECHECK(StartStruct(name, &anonymous_struct));
+ type = Type(BASE_TYPE_STRUCT, anonymous_struct);
+ }
+ } else {
+ ECHECK(ParseTypeFromProtoType(&type));
+ }
+ // Repeated elements get mapped to a vector.
+ if (repeated) {
+ type.element = type.base_type;
+ type.base_type = BASE_TYPE_VECTOR;
+ if (type.element == BASE_TYPE_VECTOR) {
+ // We have a vector or vectors, which FlatBuffers doesn't support.
+ // For now make it a vector of string (since the source is likely
+ // "repeated bytes").
+ // TODO(wvo): A better solution would be to wrap this in a table.
+ type.element = BASE_TYPE_STRING;
+ }
+ }
+ std::string name = attribute_;
+ EXPECT(kTokenIdentifier);
+ if (!oneof) {
+ // Parse the field id. Since we're just translating schemas, not
+ // any kind of binary compatibility, we can safely ignore these, and
+ // assign our own.
+ EXPECT('=');
+ EXPECT(kTokenIntegerConstant);
+ }
+ FieldDef *field = nullptr;
+ if (isextend) {
+ // We allow a field to be re-defined when extending.
+ // TODO: are there situations where that is problematic?
+ field = struct_def->fields.Lookup(name);
+ }
+ if (!field) ECHECK(AddField(*struct_def, name, type, &field));
+ field->doc_comment = field_comment;
+ if (!IsScalar(type.base_type) && required) {
+ field->presence = FieldDef::kRequired;
+ }
+ // See if there's a default specified.
+ if (Is('[')) {
+ NEXT();
+ for (;;) {
+ auto key = attribute_;
+ ECHECK(ParseProtoKey());
+ EXPECT('=');
+ auto val = attribute_;
+ ECHECK(ParseProtoCurliesOrIdent());
+ if (key == "default") {
+ // Temp: skip non-numeric and non-boolean defaults (enums).
+ auto numeric = strpbrk(val.c_str(), "0123456789-+.");
+ if (IsScalar(type.base_type) && numeric == val.c_str()) {
+ field->value.constant = val;
+ } else if (val == "true") {
+ field->value.constant = val;
+ } // "false" is default, no need to handle explicitly.
+ } else if (key == "deprecated") {
+ field->deprecated = val == "true";
+ }
+ if (!Is(',')) break;
+ NEXT();
+ }
+ EXPECT(']');
+ }
+ if (anonymous_struct) {
+ ECHECK(ParseProtoFields(anonymous_struct, false, oneof));
+ if (Is(';')) NEXT();
+ } else if (oneof_union) {
+ // Parse into a temporary StructDef, then transfer fields into an
+ // EnumDef describing the oneof as a union.
+ StructDef oneof_struct;
+ ECHECK(ParseProtoFields(&oneof_struct, false, oneof));
+ if (Is(';')) NEXT();
+ for (auto field_it = oneof_struct.fields.vec.begin();
+ field_it != oneof_struct.fields.vec.end(); ++field_it) {
+ const auto &oneof_field = **field_it;
+ const auto &oneof_type = oneof_field.value.type;
+ if (oneof_type.base_type != BASE_TYPE_STRUCT ||
+ !oneof_type.struct_def || oneof_type.struct_def->fixed)
+ return Error("oneof '" + name +
+ "' cannot be mapped to a union because member '" +
+ oneof_field.name + "' is not a table type.");
+ EnumValBuilder evb(*this, *oneof_union);
+ auto ev = evb.CreateEnumerator(oneof_type.struct_def->name);
+ ev->union_type = oneof_type;
+ ev->doc_comment = oneof_field.doc_comment;
+ ECHECK(evb.AcceptEnumerator(oneof_field.name));
+ }
+ } else {
+ EXPECT(';');
+ }
+ }
+ }
+ NEXT();
+ return NoError();
+}
+
+CheckedError Parser::ParseProtoKey() {
+ if (token_ == '(') {
+ NEXT();
+ // Skip "(a.b)" style custom attributes.
+ while (token_ == '.' || token_ == kTokenIdentifier) NEXT();
+ EXPECT(')');
+ while (Is('.')) {
+ NEXT();
+ EXPECT(kTokenIdentifier);
+ }
+ } else {
+ EXPECT(kTokenIdentifier);
+ }
+ return NoError();
+}
+
+CheckedError Parser::ParseProtoCurliesOrIdent() {
+ if (Is('{')) {
+ NEXT();
+ for (int nesting = 1; nesting;) {
+ if (token_ == '{')
+ nesting++;
+ else if (token_ == '}')
+ nesting--;
+ NEXT();
+ }
+ } else {
+ NEXT(); // Any single token.
+ }
+ return NoError();
+}
+
+CheckedError Parser::ParseProtoOption() {
+ NEXT();
+ ECHECK(ParseProtoKey());
+ EXPECT('=');
+ ECHECK(ParseProtoCurliesOrIdent());
+ return NoError();
+}
+
+// Parse a protobuf type, and map it to the corresponding FlatBuffer one.
+CheckedError Parser::ParseTypeFromProtoType(Type *type) {
+ struct type_lookup {
+ const char *proto_type;
+ BaseType fb_type, element;
+ };
+ static type_lookup lookup[] = {
+ { "float", BASE_TYPE_FLOAT, BASE_TYPE_NONE },
+ { "double", BASE_TYPE_DOUBLE, BASE_TYPE_NONE },
+ { "int32", BASE_TYPE_INT, BASE_TYPE_NONE },
+ { "int64", BASE_TYPE_LONG, BASE_TYPE_NONE },
+ { "uint32", BASE_TYPE_UINT, BASE_TYPE_NONE },
+ { "uint64", BASE_TYPE_ULONG, BASE_TYPE_NONE },
+ { "sint32", BASE_TYPE_INT, BASE_TYPE_NONE },
+ { "sint64", BASE_TYPE_LONG, BASE_TYPE_NONE },
+ { "fixed32", BASE_TYPE_UINT, BASE_TYPE_NONE },
+ { "fixed64", BASE_TYPE_ULONG, BASE_TYPE_NONE },
+ { "sfixed32", BASE_TYPE_INT, BASE_TYPE_NONE },
+ { "sfixed64", BASE_TYPE_LONG, BASE_TYPE_NONE },
+ { "bool", BASE_TYPE_BOOL, BASE_TYPE_NONE },
+ { "string", BASE_TYPE_STRING, BASE_TYPE_NONE },
+ { "bytes", BASE_TYPE_VECTOR, BASE_TYPE_UCHAR },
+ { nullptr, BASE_TYPE_NONE, BASE_TYPE_NONE }
+ };
+ for (auto tl = lookup; tl->proto_type; tl++) {
+ if (attribute_ == tl->proto_type) {
+ type->base_type = tl->fb_type;
+ type->element = tl->element;
+ NEXT();
+ return NoError();
+ }
+ }
+ if (Is('.')) NEXT(); // qualified names may start with a . ?
+ ECHECK(ParseTypeIdent(*type));
+ return NoError();
+}
+
+CheckedError Parser::SkipAnyJsonValue() {
+ ParseDepthGuard depth_guard(this);
+ ECHECK(depth_guard.Check());
+
+ switch (token_) {
+ case '{': {
+ size_t fieldn_outer = 0;
+ return ParseTableDelimiters(fieldn_outer, nullptr,
+ [&](const std::string &, size_t &fieldn,
+ const StructDef *) -> CheckedError {
+ ECHECK(SkipAnyJsonValue());
+ fieldn++;
+ return NoError();
+ });
+ }
+ case '[': {
+ uoffset_t count = 0;
+ return ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
+ return SkipAnyJsonValue();
+ });
+ }
+ case kTokenStringConstant:
+ case kTokenIntegerConstant:
+ case kTokenFloatConstant: NEXT(); break;
+ default:
+ if (IsIdent("true") || IsIdent("false") || IsIdent("null")) {
+ NEXT();
+ } else
+ return TokenError();
+ }
+ return NoError();
+}
+
+CheckedError Parser::ParseFlexBufferNumericConstant(
+ flexbuffers::Builder *builder) {
+ double d;
+ if (!StringToNumber(attribute_.c_str(), &d))
+ return Error("unexpected floating-point constant: " + attribute_);
+ builder->Double(d);
+ return NoError();
+}
+
+CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) {
+ ParseDepthGuard depth_guard(this);
+ ECHECK(depth_guard.Check());
+
+ switch (token_) {
+ case '{': {
+ auto start = builder->StartMap();
+ size_t fieldn_outer = 0;
+ auto err =
+ ParseTableDelimiters(fieldn_outer, nullptr,
+ [&](const std::string &name, size_t &fieldn,
+ const StructDef *) -> CheckedError {
+ builder->Key(name);
+ ECHECK(ParseFlexBufferValue(builder));
+ fieldn++;
+ return NoError();
+ });
+ ECHECK(err);
+ builder->EndMap(start);
+ if (builder->HasDuplicateKeys())
+ return Error("FlexBuffers map has duplicate keys");
+ break;
+ }
+ case '[': {
+ auto start = builder->StartVector();
+ uoffset_t count = 0;
+ ECHECK(ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
+ return ParseFlexBufferValue(builder);
+ }));
+ builder->EndVector(start, false, false);
+ break;
+ }
+ case kTokenStringConstant:
+ builder->String(attribute_);
+ EXPECT(kTokenStringConstant);
+ break;
+ case kTokenIntegerConstant:
+ builder->Int(StringToInt(attribute_.c_str()));
+ EXPECT(kTokenIntegerConstant);
+ break;
+ case kTokenFloatConstant: {
+ double d;
+ StringToNumber(attribute_.c_str(), &d);
+ builder->Double(d);
+ EXPECT(kTokenFloatConstant);
+ break;
+ }
+ case '-':
+ case '+': {
+ // `[-+]?(nan|inf|infinity)`, see ParseSingleValue().
+ const auto sign = static_cast<char>(token_);
+ NEXT();
+ if (token_ != kTokenIdentifier)
+ return Error("floating-point constant expected");
+ attribute_.insert(size_t(0), size_t(1), sign);
+ ECHECK(ParseFlexBufferNumericConstant(builder));
+ NEXT();
+ break;
+ }
+ default:
+ if (IsIdent("true")) {
+ builder->Bool(true);
+ NEXT();
+ } else if (IsIdent("false")) {
+ builder->Bool(false);
+ NEXT();
+ } else if (IsIdent("null")) {
+ builder->Null();
+ NEXT();
+ } else if (IsIdent("inf") || IsIdent("infinity") || IsIdent("nan")) {
+ ECHECK(ParseFlexBufferNumericConstant(builder));
+ NEXT();
+ } else
+ return TokenError();
+ }
+ return NoError();
+}
+
+bool Parser::ParseFlexBuffer(const char *source, const char *source_filename,
+ flexbuffers::Builder *builder) {
+ const auto initial_depth = parse_depth_counter_;
+ (void)initial_depth;
+ auto ok = !StartParseFile(source, source_filename).Check() &&
+ !ParseFlexBufferValue(builder).Check();
+ if (ok) builder->Finish();
+ FLATBUFFERS_ASSERT(initial_depth == parse_depth_counter_);
+ return ok;
+}
+
+bool Parser::Parse(const char *source, const char **include_paths,
+ const char *source_filename) {
+ const auto initial_depth = parse_depth_counter_;
+ (void)initial_depth;
+ bool r;
+
+ if (opts.use_flexbuffers) {
+ r = ParseFlexBuffer(source, source_filename, &flex_builder_);
+ } else {
+ r = !ParseRoot(source, include_paths, source_filename).Check();
+ }
+ FLATBUFFERS_ASSERT(initial_depth == parse_depth_counter_);
+ return r;
+}
+
+bool Parser::ParseJson(const char *json, const char *json_filename) {
+ const auto initial_depth = parse_depth_counter_;
+ (void)initial_depth;
+ builder_.Clear();
+ const auto done =
+ !StartParseFile(json, json_filename).Check() && !DoParseJson().Check();
+ FLATBUFFERS_ASSERT(initial_depth == parse_depth_counter_);
+ return done;
+}
+
+CheckedError Parser::StartParseFile(const char *source,
+ const char *source_filename) {
+ file_being_parsed_ = source_filename ? source_filename : "";
+ source_ = source;
+ ResetState(source_);
+ error_.clear();
+ ECHECK(SkipByteOrderMark());
+ NEXT();
+ if (Is(kTokenEof)) return Error("input file is empty");
+ return NoError();
+}
+
+CheckedError Parser::ParseRoot(const char *source, const char **include_paths,
+ const char *source_filename) {
+ ECHECK(DoParse(source, include_paths, source_filename, nullptr));
+
+ // Check that all types were defined.
+ for (auto it = structs_.vec.begin(); it != structs_.vec.end();) {
+ auto &struct_def = **it;
+ if (struct_def.predecl) {
+ if (opts.proto_mode) {
+ // Protos allow enums to be used before declaration, so check if that
+ // is the case here.
+ EnumDef *enum_def = nullptr;
+ for (size_t components =
+ struct_def.defined_namespace->components.size() + 1;
+ components && !enum_def; components--) {
+ auto qualified_name =
+ struct_def.defined_namespace->GetFullyQualifiedName(
+ struct_def.name, components - 1);
+ enum_def = LookupEnum(qualified_name);
+ }
+ if (enum_def) {
+ // This is pretty slow, but a simple solution for now.
+ auto initial_count = struct_def.refcount;
+ for (auto struct_it = structs_.vec.begin();
+ struct_it != structs_.vec.end(); ++struct_it) {
+ auto &sd = **struct_it;
+ for (auto field_it = sd.fields.vec.begin();
+ field_it != sd.fields.vec.end(); ++field_it) {
+ auto &field = **field_it;
+ if (field.value.type.struct_def == &struct_def) {
+ field.value.type.struct_def = nullptr;
+ field.value.type.enum_def = enum_def;
+ auto &bt = IsVector(field.value.type)
+ ? field.value.type.element
+ : field.value.type.base_type;
+ FLATBUFFERS_ASSERT(bt == BASE_TYPE_STRUCT);
+ bt = enum_def->underlying_type.base_type;
+ struct_def.refcount--;
+ enum_def->refcount++;
+ }
+ }
+ }
+ if (struct_def.refcount)
+ return Error("internal: " + NumToString(struct_def.refcount) + "/" +
+ NumToString(initial_count) +
+ " use(s) of pre-declaration enum not accounted for: " +
+ enum_def->name);
+ structs_.dict.erase(structs_.dict.find(struct_def.name));
+ it = structs_.vec.erase(it);
+ delete &struct_def;
+ continue; // Skip error.
+ }
+ }
+ auto err = "type referenced but not defined (check namespace): " +
+ struct_def.name;
+ if (struct_def.original_location)
+ err += ", originally at: " + *struct_def.original_location;
+ return Error(err);
+ }
+ ++it;
+ }
+
+ // This check has to happen here and not earlier, because only now do we
+ // know for sure what the type of these are.
+ for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) {
+ auto &enum_def = **it;
+ if (enum_def.is_union) {
+ for (auto val_it = enum_def.Vals().begin();
+ val_it != enum_def.Vals().end(); ++val_it) {
+ auto &val = **val_it;
+ if (!SupportsAdvancedUnionFeatures() &&
+ (IsStruct(val.union_type) || IsString(val.union_type)))
+ return Error(
+ "only tables can be union elements in the generated language: " +
+ val.name);
+ }
+ }
+ }
+ // Parse JSON object only if the scheme has been parsed.
+ if (token_ == '{') { ECHECK(DoParseJson()); }
+ EXPECT(kTokenEof);
+ return NoError();
+}
+
+// Generate a unique hash for a file based on its name and contents (if any).
+static uint64_t HashFile(const char *source_filename, const char *source) {
+ uint64_t hash = 0;
+
+ if (source_filename)
+ hash = HashFnv1a<uint64_t>(StripPath(source_filename).c_str());
+
+ if (source && *source) hash ^= HashFnv1a<uint64_t>(source);
+
+ return hash;
+}
+
+CheckedError Parser::DoParse(const char *source, const char **include_paths,
+ const char *source_filename,
+ const char *include_filename) {
+ uint64_t source_hash = 0;
+ if (source_filename) {
+ // If the file is in-memory, don't include its contents in the hash as we
+ // won't be able to load them later.
+ if (FileExists(source_filename))
+ source_hash = HashFile(source_filename, source);
+ else
+ source_hash = HashFile(source_filename, nullptr);
+
+ if (included_files_.find(source_hash) == included_files_.end()) {
+ included_files_[source_hash] = include_filename ? include_filename : "";
+ files_included_per_file_[source_filename] = std::set<std::string>();
+ } else {
+ return NoError();
+ }
+ }
+ if (!include_paths) {
+ static const char *current_directory[] = { "", nullptr };
+ include_paths = current_directory;
+ }
+ field_stack_.clear();
+ builder_.Clear();
+ // Start with a blank namespace just in case this file doesn't have one.
+ current_namespace_ = empty_namespace_;
+
+ ECHECK(StartParseFile(source, source_filename));
+
+ // Includes must come before type declarations:
+ for (;;) {
+ // Parse pre-include proto statements if any:
+ if (opts.proto_mode && (attribute_ == "option" || attribute_ == "syntax" ||
+ attribute_ == "package")) {
+ ECHECK(ParseProtoDecl());
+ } else if (IsIdent("native_include")) {
+ NEXT();
+ vector_emplace_back(&native_included_files_, attribute_);
+ EXPECT(kTokenStringConstant);
+ EXPECT(';');
+ } else if (IsIdent("include") || (opts.proto_mode && IsIdent("import"))) {
+ NEXT();
+ if (opts.proto_mode && attribute_ == "public") NEXT();
+ auto name = flatbuffers::PosixPath(attribute_.c_str());
+ EXPECT(kTokenStringConstant);
+ // Look for the file relative to the directory of the current file.
+ std::string filepath;
+ if (source_filename) {
+ auto source_file_directory =
+ flatbuffers::StripFileName(source_filename);
+ filepath = flatbuffers::ConCatPathFileName(source_file_directory, name);
+ }
+ if (filepath.empty() || !FileExists(filepath.c_str())) {
+ // Look for the file in include_paths.
+ for (auto paths = include_paths; paths && *paths; paths++) {
+ filepath = flatbuffers::ConCatPathFileName(*paths, name);
+ if (FileExists(filepath.c_str())) break;
+ }
+ }
+ if (filepath.empty())
+ return Error("unable to locate include file: " + name);
+ if (source_filename)
+ files_included_per_file_[source_filename].insert(filepath);
+
+ std::string contents;
+ bool file_loaded = LoadFile(filepath.c_str(), true, &contents);
+ if (included_files_.find(HashFile(filepath.c_str(), contents.c_str())) ==
+ included_files_.end()) {
+ // We found an include file that we have not parsed yet.
+ // Parse it.
+ if (!file_loaded) return Error("unable to load include file: " + name);
+ ECHECK(DoParse(contents.c_str(), include_paths, filepath.c_str(),
+ name.c_str()));
+ // We generally do not want to output code for any included files:
+ if (!opts.generate_all) MarkGenerated();
+ // Reset these just in case the included file had them, and the
+ // parent doesn't.
+ root_struct_def_ = nullptr;
+ file_identifier_.clear();
+ file_extension_.clear();
+ // This is the easiest way to continue this file after an include:
+ // instead of saving and restoring all the state, we simply start the
+ // file anew. This will cause it to encounter the same include
+ // statement again, but this time it will skip it, because it was
+ // entered into included_files_.
+ // This is recursive, but only go as deep as the number of include
+ // statements.
+ included_files_.erase(source_hash);
+ return DoParse(source, include_paths, source_filename,
+ include_filename);
+ }
+ EXPECT(';');
+ } else {
+ break;
+ }
+ }
+ // Now parse all other kinds of declarations:
+ while (token_ != kTokenEof) {
+ if (opts.proto_mode) {
+ ECHECK(ParseProtoDecl());
+ } else if (IsIdent("namespace")) {
+ ECHECK(ParseNamespace());
+ } else if (token_ == '{') {
+ return NoError();
+ } else if (IsIdent("enum")) {
+ ECHECK(ParseEnum(false, nullptr));
+ } else if (IsIdent("union")) {
+ ECHECK(ParseEnum(true, nullptr));
+ } else if (IsIdent("root_type")) {
+ NEXT();
+ auto root_type = attribute_;
+ EXPECT(kTokenIdentifier);
+ ECHECK(ParseNamespacing(&root_type, nullptr));
+ if (opts.root_type.empty()) {
+ if (!SetRootType(root_type.c_str()))
+ return Error("unknown root type: " + root_type);
+ if (root_struct_def_->fixed) return Error("root type must be a table");
+ }
+ EXPECT(';');
+ } else if (IsIdent("file_identifier")) {
+ NEXT();
+ file_identifier_ = attribute_;
+ EXPECT(kTokenStringConstant);
+ if (file_identifier_.length() != FlatBufferBuilder::kFileIdentifierLength)
+ return Error("file_identifier must be exactly " +
+ NumToString(FlatBufferBuilder::kFileIdentifierLength) +
+ " characters");
+ EXPECT(';');
+ } else if (IsIdent("file_extension")) {
+ NEXT();
+ file_extension_ = attribute_;
+ EXPECT(kTokenStringConstant);
+ EXPECT(';');
+ } else if (IsIdent("include")) {
+ return Error("includes must come before declarations");
+ } else if (IsIdent("attribute")) {
+ NEXT();
+ auto name = attribute_;
+ if (Is(kTokenIdentifier)) {
+ NEXT();
+ } else {
+ EXPECT(kTokenStringConstant);
+ }
+ EXPECT(';');
+ known_attributes_[name] = false;
+ } else if (IsIdent("rpc_service")) {
+ ECHECK(ParseService());
+ } else {
+ ECHECK(ParseDecl());
+ }
+ }
+ return NoError();
+}
+
+CheckedError Parser::DoParseJson() {
+ if (token_ != '{') {
+ EXPECT('{');
+ } else {
+ if (!root_struct_def_) return Error("no root type set to parse json with");
+ if (builder_.GetSize()) {
+ return Error("cannot have more than one json object in a file");
+ }
+ uoffset_t toff;
+ ECHECK(ParseTable(*root_struct_def_, nullptr, &toff));
+ if (opts.size_prefixed) {
+ builder_.FinishSizePrefixed(
+ Offset<Table>(toff),
+ file_identifier_.length() ? file_identifier_.c_str() : nullptr);
+ } else {
+ builder_.Finish(Offset<Table>(toff), file_identifier_.length()
+ ? file_identifier_.c_str()
+ : nullptr);
+ }
+ }
+ // Check that JSON file doesn't contain more objects or IDL directives.
+ // Comments after JSON are allowed.
+ EXPECT(kTokenEof);
+ return NoError();
+}
+
+std::set<std::string> Parser::GetIncludedFilesRecursive(
+ const std::string &file_name) const {
+ std::set<std::string> included_files;
+ std::list<std::string> to_process;
+
+ if (file_name.empty()) return included_files;
+ to_process.push_back(file_name);
+
+ while (!to_process.empty()) {
+ std::string current = to_process.front();
+ to_process.pop_front();
+ included_files.insert(current);
+
+ // Workaround the lack of const accessor in C++98 maps.
+ auto &new_files =
+ (*const_cast<std::map<std::string, std::set<std::string>> *>(
+ &files_included_per_file_))[current];
+ for (auto it = new_files.begin(); it != new_files.end(); ++it) {
+ if (included_files.find(*it) == included_files.end())
+ to_process.push_back(*it);
+ }
+ }
+
+ return included_files;
+}
+
+// Schema serialization functionality:
+
+template<typename T> bool compareName(const T *a, const T *b) {
+ return a->defined_namespace->GetFullyQualifiedName(a->name) <
+ b->defined_namespace->GetFullyQualifiedName(b->name);
+}
+
+template<typename T> void AssignIndices(const std::vector<T *> &defvec) {
+ // Pre-sort these vectors, such that we can set the correct indices for them.
+ auto vec = defvec;
+ std::sort(vec.begin(), vec.end(), compareName<T>);
+ for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i;
+}
+
+void Parser::Serialize() {
+ builder_.Clear();
+ AssignIndices(structs_.vec);
+ AssignIndices(enums_.vec);
+ std::vector<Offset<reflection::Object>> object_offsets;
+ for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) {
+ auto offset = (*it)->Serialize(&builder_, *this);
+ object_offsets.push_back(offset);
+ (*it)->serialized_location = offset.o;
+ }
+ std::vector<Offset<reflection::Enum>> enum_offsets;
+ for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) {
+ auto offset = (*it)->Serialize(&builder_, *this);
+ enum_offsets.push_back(offset);
+ (*it)->serialized_location = offset.o;
+ }
+ std::vector<Offset<reflection::Service>> service_offsets;
+ for (auto it = services_.vec.begin(); it != services_.vec.end(); ++it) {
+ auto offset = (*it)->Serialize(&builder_, *this);
+ service_offsets.push_back(offset);
+ (*it)->serialized_location = offset.o;
+ }
+ auto objs__ = builder_.CreateVectorOfSortedTables(&object_offsets);
+ auto enum__ = builder_.CreateVectorOfSortedTables(&enum_offsets);
+ auto fiid__ = builder_.CreateString(file_identifier_);
+ auto fext__ = builder_.CreateString(file_extension_);
+ auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets);
+ auto schema_offset = reflection::CreateSchema(
+ builder_, objs__, enum__, fiid__, fext__,
+ (root_struct_def_ ? root_struct_def_->serialized_location : 0), serv__,
+ static_cast<reflection::AdvancedFeatures>(advanced_features_));
+ if (opts.size_prefixed) {
+ builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier());
+ } else {
+ builder_.Finish(schema_offset, reflection::SchemaIdentifier());
+ }
+}
+
+static Namespace *GetNamespace(
+ const std::string &qualified_name, std::vector<Namespace *> &namespaces,
+ std::map<std::string, Namespace *> &namespaces_index) {
+ size_t dot = qualified_name.find_last_of('.');
+ std::string namespace_name = (dot != std::string::npos)
+ ? std::string(qualified_name.c_str(), dot)
+ : "";
+ Namespace *&ns = namespaces_index[namespace_name];
+
+ if (!ns) {
+ ns = new Namespace();
+ namespaces.push_back(ns);
+
+ size_t pos = 0;
+
+ for (;;) {
+ dot = qualified_name.find('.', pos);
+ if (dot == std::string::npos) { break; }
+ ns->components.push_back(qualified_name.substr(pos, dot - pos));
+ pos = dot + 1;
+ }
+ }
+
+ return ns;
+}
+
+Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const {
+ std::vector<Offset<reflection::Field>> field_offsets;
+ for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) {
+ field_offsets.push_back((*it)->Serialize(
+ builder, static_cast<uint16_t>(it - fields.vec.begin()), parser));
+ }
+ auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
+ auto name__ = builder->CreateString(qualified_name);
+ auto flds__ = builder->CreateVectorOfSortedTables(&field_offsets);
+ auto attr__ = SerializeAttributes(builder, parser);
+ auto docs__ = parser.opts.binary_schema_comments
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ return reflection::CreateObject(*builder, name__, flds__, fixed,
+ static_cast<int>(minalign),
+ static_cast<int>(bytesize), attr__, docs__);
+}
+
+bool StructDef::Deserialize(Parser &parser, const reflection::Object *object) {
+ if (!DeserializeAttributes(parser, object->attributes())) return false;
+ DeserializeDoc(doc_comment, object->documentation());
+ name = parser.UnqualifiedName(object->name()->str());
+ predecl = false;
+ sortbysize = attributes.Lookup("original_order") == nullptr && !fixed;
+ const auto &of = *(object->fields());
+ auto indexes = std::vector<uoffset_t>(of.size());
+ for (uoffset_t i = 0; i < of.size(); i++) indexes[of.Get(i)->id()] = i;
+ size_t tmp_struct_size = 0;
+ for (size_t i = 0; i < indexes.size(); i++) {
+ auto field = of.Get(indexes[i]);
+ auto field_def = new FieldDef();
+ if (!field_def->Deserialize(parser, field) ||
+ fields.Add(field_def->name, field_def)) {
+ delete field_def;
+ return false;
+ }
+ if (fixed) {
+ // Recompute padding since that's currently not serialized.
+ auto size = InlineSize(field_def->value.type);
+ auto next_field =
+ i + 1 < indexes.size() ? of.Get(indexes[i + 1]) : nullptr;
+ tmp_struct_size += size;
+ field_def->padding =
+ next_field ? (next_field->offset() - field_def->value.offset) - size
+ : PaddingBytes(tmp_struct_size, minalign);
+ tmp_struct_size += field_def->padding;
+ }
+ }
+ FLATBUFFERS_ASSERT(static_cast<int>(tmp_struct_size) == object->bytesize());
+ return true;
+}
+
+Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
+ uint16_t id,
+ const Parser &parser) const {
+ auto name__ = builder->CreateString(name);
+ auto type__ = value.type.Serialize(builder);
+ auto attr__ = SerializeAttributes(builder, parser);
+ auto docs__ = parser.opts.binary_schema_comments
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ double d;
+ StringToNumber(value.constant.c_str(), &d);
+ return reflection::CreateField(
+ *builder, name__, type__, id, value.offset,
+ // Is uint64>max(int64) tested?
+ IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0,
+ // result may be platform-dependent if underlying is float (not double)
+ IsFloat(value.type.base_type) ? d : 0.0, deprecated, IsRequired(), key,
+ attr__, docs__, IsOptional());
+ // TODO: value.constant is almost always "0", we could save quite a bit of
+ // space by sharing it. Same for common values of value.type.
+}
+
+bool FieldDef::Deserialize(Parser &parser, const reflection::Field *field) {
+ name = field->name()->str();
+ defined_namespace = parser.current_namespace_;
+ if (!value.type.Deserialize(parser, field->type())) return false;
+ value.offset = field->offset();
+ if (IsInteger(value.type.base_type)) {
+ value.constant = NumToString(field->default_integer());
+ } else if (IsFloat(value.type.base_type)) {
+ value.constant = FloatToString(field->default_real(), 16);
+ }
+ presence = FieldDef::MakeFieldPresence(field->optional(), field->required());
+ key = field->key();
+ if (!DeserializeAttributes(parser, field->attributes())) return false;
+ // TODO: this should probably be handled by a separate attribute
+ if (attributes.Lookup("flexbuffer")) {
+ flexbuffer = true;
+ parser.uses_flexbuffers_ = true;
+ if (value.type.base_type != BASE_TYPE_VECTOR ||
+ value.type.element != BASE_TYPE_UCHAR)
+ return false;
+ }
+ if (auto nested = attributes.Lookup("nested_flatbuffer")) {
+ auto nested_qualified_name =
+ parser.current_namespace_->GetFullyQualifiedName(nested->constant);
+ nested_flatbuffer = parser.LookupStruct(nested_qualified_name);
+ if (!nested_flatbuffer) return false;
+ }
+ shared = attributes.Lookup("shared") != nullptr;
+ DeserializeDoc(doc_comment, field->documentation());
+ return true;
+}
+
+Offset<reflection::RPCCall> RPCCall::Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const {
+ auto name__ = builder->CreateString(name);
+ auto attr__ = SerializeAttributes(builder, parser);
+ auto docs__ = parser.opts.binary_schema_comments
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ return reflection::CreateRPCCall(
+ *builder, name__, request->serialized_location,
+ response->serialized_location, attr__, docs__);
+}
+
+bool RPCCall::Deserialize(Parser &parser, const reflection::RPCCall *call) {
+ name = call->name()->str();
+ if (!DeserializeAttributes(parser, call->attributes())) return false;
+ DeserializeDoc(doc_comment, call->documentation());
+ request = parser.structs_.Lookup(call->request()->name()->str());
+ response = parser.structs_.Lookup(call->response()->name()->str());
+ if (!request || !response) { return false; }
+ return true;
+}
+
+Offset<reflection::Service> ServiceDef::Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const {
+ std::vector<Offset<reflection::RPCCall>> servicecall_offsets;
+ for (auto it = calls.vec.begin(); it != calls.vec.end(); ++it) {
+ servicecall_offsets.push_back((*it)->Serialize(builder, parser));
+ }
+ auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
+ auto name__ = builder->CreateString(qualified_name);
+ auto call__ = builder->CreateVector(servicecall_offsets);
+ auto attr__ = SerializeAttributes(builder, parser);
+ auto docs__ = parser.opts.binary_schema_comments
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ return reflection::CreateService(*builder, name__, call__, attr__, docs__);
+}
+
+bool ServiceDef::Deserialize(Parser &parser,
+ const reflection::Service *service) {
+ name = parser.UnqualifiedName(service->name()->str());
+ if (service->calls()) {
+ for (uoffset_t i = 0; i < service->calls()->size(); ++i) {
+ auto call = new RPCCall();
+ if (!call->Deserialize(parser, service->calls()->Get(i)) ||
+ calls.Add(call->name, call)) {
+ delete call;
+ return false;
+ }
+ }
+ }
+ if (!DeserializeAttributes(parser, service->attributes())) return false;
+ DeserializeDoc(doc_comment, service->documentation());
+ return true;
+}
+
+Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const {
+ std::vector<Offset<reflection::EnumVal>> enumval_offsets;
+ for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) {
+ enumval_offsets.push_back((*it)->Serialize(builder, parser));
+ }
+ auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
+ auto name__ = builder->CreateString(qualified_name);
+ auto vals__ = builder->CreateVector(enumval_offsets);
+ auto type__ = underlying_type.Serialize(builder);
+ auto attr__ = SerializeAttributes(builder, parser);
+ auto docs__ = parser.opts.binary_schema_comments
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ return reflection::CreateEnum(*builder, name__, vals__, is_union, type__,
+ attr__, docs__);
+}
+
+bool EnumDef::Deserialize(Parser &parser, const reflection::Enum *_enum) {
+ name = parser.UnqualifiedName(_enum->name()->str());
+ for (uoffset_t i = 0; i < _enum->values()->size(); ++i) {
+ auto val = new EnumVal();
+ if (!val->Deserialize(parser, _enum->values()->Get(i)) ||
+ vals.Add(val->name, val)) {
+ delete val;
+ return false;
+ }
+ }
+ is_union = _enum->is_union();
+ if (!underlying_type.Deserialize(parser, _enum->underlying_type())) {
+ return false;
+ }
+ if (!DeserializeAttributes(parser, _enum->attributes())) return false;
+ DeserializeDoc(doc_comment, _enum->documentation());
+ return true;
+}
+
+Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder,
+ const Parser &parser) const {
+ auto name__ = builder->CreateString(name);
+ auto type__ = union_type.Serialize(builder);
+ auto docs__ = parser.opts.binary_schema_comments
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ return reflection::CreateEnumVal(
+ *builder, name__, value,
+ union_type.struct_def ? union_type.struct_def->serialized_location : 0,
+ type__, docs__);
+}
+
+bool EnumVal::Deserialize(const Parser &parser,
+ const reflection::EnumVal *val) {
+ name = val->name()->str();
+ value = val->value();
+ if (!union_type.Deserialize(parser, val->union_type())) return false;
+ DeserializeDoc(doc_comment, val->documentation());
+ return true;
+}
+
+Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
+ return reflection::CreateType(
+ *builder, static_cast<reflection::BaseType>(base_type),
+ static_cast<reflection::BaseType>(element),
+ struct_def ? struct_def->index : (enum_def ? enum_def->index : -1),
+ fixed_length);
+}
+
+bool Type::Deserialize(const Parser &parser, const reflection::Type *type) {
+ if (type == nullptr) return true;
+ base_type = static_cast<BaseType>(type->base_type());
+ element = static_cast<BaseType>(type->element());
+ fixed_length = type->fixed_length();
+ if (type->index() >= 0) {
+ bool is_series = type->base_type() == reflection::Vector ||
+ type->base_type() == reflection::Array;
+ if (type->base_type() == reflection::Obj ||
+ (is_series && type->element() == reflection::Obj)) {
+ if (static_cast<size_t>(type->index()) < parser.structs_.vec.size()) {
+ struct_def = parser.structs_.vec[type->index()];
+ struct_def->refcount++;
+ } else {
+ return false;
+ }
+ } else {
+ if (static_cast<size_t>(type->index()) < parser.enums_.vec.size()) {
+ enum_def = parser.enums_.vec[type->index()];
+ } else {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+flatbuffers::Offset<
+ flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
+Definition::SerializeAttributes(FlatBufferBuilder *builder,
+ const Parser &parser) const {
+ std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs;
+ for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) {
+ auto it = parser.known_attributes_.find(kv->first);
+ FLATBUFFERS_ASSERT(it != parser.known_attributes_.end());
+ if (parser.opts.binary_schema_builtins || !it->second) {
+ auto key = builder->CreateString(kv->first);
+ auto val = builder->CreateString(kv->second->constant);
+ attrs.push_back(reflection::CreateKeyValue(*builder, key, val));
+ }
+ }
+ if (attrs.size()) {
+ return builder->CreateVectorOfSortedTables(&attrs);
+ } else {
+ return 0;
+ }
+}
+
+bool Definition::DeserializeAttributes(
+ Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs) {
+ if (attrs == nullptr) return true;
+ for (uoffset_t i = 0; i < attrs->size(); ++i) {
+ auto kv = attrs->Get(i);
+ auto value = new Value();
+ if (kv->value()) { value->constant = kv->value()->str(); }
+ if (attributes.Add(kv->key()->str(), value)) {
+ delete value;
+ return false;
+ }
+ parser.known_attributes_[kv->key()->str()];
+ }
+ return true;
+}
+
+/************************************************************************/
+/* DESERIALIZATION */
+/************************************************************************/
+bool Parser::Deserialize(const uint8_t *buf, const size_t size) {
+ flatbuffers::Verifier verifier(reinterpret_cast<const uint8_t *>(buf), size);
+ bool size_prefixed = false;
+ if (!reflection::SchemaBufferHasIdentifier(buf)) {
+ if (!flatbuffers::BufferHasIdentifier(buf, reflection::SchemaIdentifier(),
+ true))
+ return false;
+ else
+ size_prefixed = true;
+ }
+ auto verify_fn = size_prefixed ? &reflection::VerifySizePrefixedSchemaBuffer
+ : &reflection::VerifySchemaBuffer;
+ if (!verify_fn(verifier)) { return false; }
+ auto schema = size_prefixed ? reflection::GetSizePrefixedSchema(buf)
+ : reflection::GetSchema(buf);
+ return Deserialize(schema);
+}
+
+bool Parser::Deserialize(const reflection::Schema *schema) {
+ file_identifier_ = schema->file_ident() ? schema->file_ident()->str() : "";
+ file_extension_ = schema->file_ext() ? schema->file_ext()->str() : "";
+ std::map<std::string, Namespace *> namespaces_index;
+
+ // Create defs without deserializing so references from fields to structs and
+ // enums can be resolved.
+ for (auto it = schema->objects()->begin(); it != schema->objects()->end();
+ ++it) {
+ auto struct_def = new StructDef();
+ struct_def->bytesize = it->bytesize();
+ struct_def->fixed = it->is_struct();
+ struct_def->minalign = it->minalign();
+ if (structs_.Add(it->name()->str(), struct_def)) {
+ delete struct_def;
+ return false;
+ }
+ auto type = new Type(BASE_TYPE_STRUCT, struct_def, nullptr);
+ if (types_.Add(it->name()->str(), type)) {
+ delete type;
+ return false;
+ }
+ }
+ for (auto it = schema->enums()->begin(); it != schema->enums()->end(); ++it) {
+ auto enum_def = new EnumDef();
+ if (enums_.Add(it->name()->str(), enum_def)) {
+ delete enum_def;
+ return false;
+ }
+ auto type = new Type(BASE_TYPE_UNION, nullptr, enum_def);
+ if (types_.Add(it->name()->str(), type)) {
+ delete type;
+ return false;
+ }
+ }
+
+ // Now fields can refer to structs and enums by index.
+ for (auto it = schema->objects()->begin(); it != schema->objects()->end();
+ ++it) {
+ std::string qualified_name = it->name()->str();
+ auto struct_def = structs_.Lookup(qualified_name);
+ struct_def->defined_namespace =
+ GetNamespace(qualified_name, namespaces_, namespaces_index);
+ if (!struct_def->Deserialize(*this, *it)) { return false; }
+ if (schema->root_table() == *it) { root_struct_def_ = struct_def; }
+ }
+ for (auto it = schema->enums()->begin(); it != schema->enums()->end(); ++it) {
+ std::string qualified_name = it->name()->str();
+ auto enum_def = enums_.Lookup(qualified_name);
+ enum_def->defined_namespace =
+ GetNamespace(qualified_name, namespaces_, namespaces_index);
+ if (!enum_def->Deserialize(*this, *it)) { return false; }
+ }
+
+ if (schema->services()) {
+ for (auto it = schema->services()->begin(); it != schema->services()->end();
+ ++it) {
+ std::string qualified_name = it->name()->str();
+ auto service_def = new ServiceDef();
+ service_def->defined_namespace =
+ GetNamespace(qualified_name, namespaces_, namespaces_index);
+ if (!service_def->Deserialize(*this, *it) ||
+ services_.Add(qualified_name, service_def)) {
+ delete service_def;
+ return false;
+ }
+ }
+ }
+ advanced_features_ = schema->advanced_features();
+ return true;
+}
+
+std::string Parser::ConformTo(const Parser &base) {
+ for (auto sit = structs_.vec.begin(); sit != structs_.vec.end(); ++sit) {
+ auto &struct_def = **sit;
+ auto qualified_name =
+ struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name);
+ auto struct_def_base = base.LookupStruct(qualified_name);
+ if (!struct_def_base) continue;
+ for (auto fit = struct_def.fields.vec.begin();
+ fit != struct_def.fields.vec.end(); ++fit) {
+ auto &field = **fit;
+ auto field_base = struct_def_base->fields.Lookup(field.name);
+ if (field_base) {
+ if (field.value.offset != field_base->value.offset)
+ return "offsets differ for field: " + field.name;
+ if (field.value.constant != field_base->value.constant)
+ return "defaults differ for field: " + field.name;
+ if (!EqualByName(field.value.type, field_base->value.type))
+ return "types differ for field: " + field.name;
+ } else {
+ // Doesn't have to exist, deleting fields is fine.
+ // But we should check if there is a field that has the same offset
+ // but is incompatible (in the case of field renaming).
+ for (auto fbit = struct_def_base->fields.vec.begin();
+ fbit != struct_def_base->fields.vec.end(); ++fbit) {
+ field_base = *fbit;
+ if (field.value.offset == field_base->value.offset) {
+ if (!EqualByName(field.value.type, field_base->value.type))
+ return "field renamed to different type: " + field.name;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (auto eit = enums_.vec.begin(); eit != enums_.vec.end(); ++eit) {
+ auto &enum_def = **eit;
+ auto qualified_name =
+ enum_def.defined_namespace->GetFullyQualifiedName(enum_def.name);
+ auto enum_def_base = base.enums_.Lookup(qualified_name);
+ if (!enum_def_base) continue;
+ for (auto evit = enum_def.Vals().begin(); evit != enum_def.Vals().end();
+ ++evit) {
+ auto &enum_val = **evit;
+ auto enum_val_base = enum_def_base->Lookup(enum_val.name);
+ if (enum_val_base) {
+ if (enum_val != *enum_val_base)
+ return "values differ for enum: " + enum_val.name;
+ }
+ }
+ }
+ return "";
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/reflection.cpp b/contrib/libs/flatbuffers/src/reflection.cpp
new file mode 100644
index 0000000000..2dedcb4f18
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/reflection.cpp
@@ -0,0 +1,713 @@
+/*
+ * Copyright 2015 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.
+ */
+
+#include "flatbuffers/reflection.h"
+
+#include "flatbuffers/util.h"
+
+// Helper functionality for reflection.
+
+namespace flatbuffers {
+
+int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data) {
+// clang-format off
+ #define FLATBUFFERS_GET(T) static_cast<int64_t>(ReadScalar<T>(data))
+ switch (type) {
+ case reflection::UType:
+ case reflection::Bool:
+ case reflection::UByte: return FLATBUFFERS_GET(uint8_t);
+ case reflection::Byte: return FLATBUFFERS_GET(int8_t);
+ case reflection::Short: return FLATBUFFERS_GET(int16_t);
+ case reflection::UShort: return FLATBUFFERS_GET(uint16_t);
+ case reflection::Int: return FLATBUFFERS_GET(int32_t);
+ case reflection::UInt: return FLATBUFFERS_GET(uint32_t);
+ case reflection::Long: return FLATBUFFERS_GET(int64_t);
+ case reflection::ULong: return FLATBUFFERS_GET(uint64_t);
+ case reflection::Float: return FLATBUFFERS_GET(float);
+ case reflection::Double: return FLATBUFFERS_GET(double);
+ case reflection::String: {
+ auto s = reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) +
+ data);
+ return s ? StringToInt(s->c_str()) : 0;
+ }
+ default: return 0; // Tables & vectors do not make sense.
+ }
+ #undef FLATBUFFERS_GET
+ // clang-format on
+}
+
+double GetAnyValueF(reflection::BaseType type, const uint8_t *data) {
+ switch (type) {
+ case reflection::Float: return static_cast<double>(ReadScalar<float>(data));
+ case reflection::Double: return ReadScalar<double>(data);
+ case reflection::String: {
+ auto s =
+ reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) + data);
+ if (s) {
+ double d;
+ StringToNumber(s->c_str(), &d);
+ return d;
+ } else {
+ return 0.0;
+ }
+ }
+ default: return static_cast<double>(GetAnyValueI(type, data));
+ }
+}
+
+std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
+ const reflection::Schema *schema, int type_index) {
+ switch (type) {
+ case reflection::Float:
+ case reflection::Double: return NumToString(GetAnyValueF(type, data));
+ case reflection::String: {
+ auto s =
+ reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) + data);
+ return s ? s->c_str() : "";
+ }
+ case reflection::Obj:
+ if (schema) {
+ // Convert the table to a string. This is mostly for debugging purposes,
+ // and does NOT promise to be JSON compliant.
+ // Also prefixes the type.
+ auto &objectdef = *schema->objects()->Get(type_index);
+ auto s = objectdef.name()->str();
+ if (objectdef.is_struct()) {
+ s += "(struct)"; // TODO: implement this as well.
+ } else {
+ auto table_field = reinterpret_cast<const Table *>(
+ ReadScalar<uoffset_t>(data) + data);
+ s += " { ";
+ auto fielddefs = objectdef.fields();
+ for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
+ auto &fielddef = **it;
+ if (!table_field->CheckField(fielddef.offset())) continue;
+ auto val = GetAnyFieldS(*table_field, fielddef, schema);
+ if (fielddef.type()->base_type() == reflection::String) {
+ std::string esc;
+ flatbuffers::EscapeString(val.c_str(), val.length(), &esc, true,
+ false);
+ val = esc;
+ }
+ s += fielddef.name()->str();
+ s += ": ";
+ s += val;
+ s += ", ";
+ }
+ s += "}";
+ }
+ return s;
+ } else {
+ return "(table)";
+ }
+ case reflection::Vector:
+ return "[(elements)]"; // TODO: implement this as well.
+ case reflection::Union: return "(union)"; // TODO: implement this as well.
+ default: return NumToString(GetAnyValueI(type, data));
+ }
+}
+
+void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val) {
+// clang-format off
+ #define FLATBUFFERS_SET(T) WriteScalar(data, static_cast<T>(val))
+ switch (type) {
+ case reflection::UType:
+ case reflection::Bool:
+ case reflection::UByte: FLATBUFFERS_SET(uint8_t ); break;
+ case reflection::Byte: FLATBUFFERS_SET(int8_t ); break;
+ case reflection::Short: FLATBUFFERS_SET(int16_t ); break;
+ case reflection::UShort: FLATBUFFERS_SET(uint16_t); break;
+ case reflection::Int: FLATBUFFERS_SET(int32_t ); break;
+ case reflection::UInt: FLATBUFFERS_SET(uint32_t); break;
+ case reflection::Long: FLATBUFFERS_SET(int64_t ); break;
+ case reflection::ULong: FLATBUFFERS_SET(uint64_t); break;
+ case reflection::Float: FLATBUFFERS_SET(float ); break;
+ case reflection::Double: FLATBUFFERS_SET(double ); break;
+ // TODO: support strings
+ default: break;
+ }
+ #undef FLATBUFFERS_SET
+ // clang-format on
+}
+
+void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val) {
+ switch (type) {
+ case reflection::Float: WriteScalar(data, static_cast<float>(val)); break;
+ case reflection::Double: WriteScalar(data, val); break;
+ // TODO: support strings.
+ default: SetAnyValueI(type, data, static_cast<int64_t>(val)); break;
+ }
+}
+
+void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val) {
+ switch (type) {
+ case reflection::Float:
+ case reflection::Double: {
+ double d;
+ StringToNumber(val, &d);
+ SetAnyValueF(type, data, d);
+ break;
+ }
+ // TODO: support strings.
+ default: SetAnyValueI(type, data, StringToInt(val)); break;
+ }
+}
+
+// Resize a FlatBuffer in-place by iterating through all offsets in the buffer
+// and adjusting them by "delta" if they straddle the start offset.
+// Once that is done, bytes can now be inserted/deleted safely.
+// "delta" may be negative (shrinking).
+// Unless "delta" is a multiple of the largest alignment, you'll create a small
+// amount of garbage space in the buffer (usually 0..7 bytes).
+// If your FlatBuffer's root table is not the schema's root table, you should
+// pass in your root_table type as well.
+class ResizeContext {
+ public:
+ ResizeContext(const reflection::Schema &schema, uoffset_t start, int delta,
+ std::vector<uint8_t> *flatbuf,
+ const reflection::Object *root_table = nullptr)
+ : schema_(schema),
+ startptr_(vector_data(*flatbuf) + start),
+ delta_(delta),
+ buf_(*flatbuf),
+ dag_check_(flatbuf->size() / sizeof(uoffset_t), false) {
+ auto mask = static_cast<int>(sizeof(largest_scalar_t) - 1);
+ delta_ = (delta_ + mask) & ~mask;
+ if (!delta_) return; // We can't shrink by less than largest_scalar_t.
+ // Now change all the offsets by delta_.
+ auto root = GetAnyRoot(vector_data(buf_));
+ Straddle<uoffset_t, 1>(vector_data(buf_), root, vector_data(buf_));
+ ResizeTable(root_table ? *root_table : *schema.root_table(), root);
+ // We can now add or remove bytes at start.
+ if (delta_ > 0)
+ buf_.insert(buf_.begin() + start, delta_, 0);
+ else
+ buf_.erase(buf_.begin() + start + delta_, buf_.begin() + start);
+ }
+
+ // Check if the range between first (lower address) and second straddles
+ // the insertion point. If it does, change the offset at offsetloc (of
+ // type T, with direction D).
+ template<typename T, int D>
+ void Straddle(const void *first, const void *second, void *offsetloc) {
+ if (first <= startptr_ && second >= startptr_) {
+ WriteScalar<T>(offsetloc, ReadScalar<T>(offsetloc) + delta_ * D);
+ DagCheck(offsetloc) = true;
+ }
+ }
+
+ // This returns a boolean that records if the corresponding offset location
+ // has been modified already. If so, we can't even read the corresponding
+ // offset, since it is pointing to a location that is illegal until the
+ // resize actually happens.
+ // This must be checked for every offset, since we can't know which offsets
+ // will straddle and which won't.
+ uint8_t &DagCheck(const void *offsetloc) {
+ auto dag_idx = reinterpret_cast<const uoffset_t *>(offsetloc) -
+ reinterpret_cast<const uoffset_t *>(vector_data(buf_));
+ return dag_check_[dag_idx];
+ }
+
+ void ResizeTable(const reflection::Object &objectdef, Table *table) {
+ if (DagCheck(table)) return; // Table already visited.
+ auto vtable = table->GetVTable();
+ // Early out: since all fields inside the table must point forwards in
+ // memory, if the insertion point is before the table we can stop here.
+ auto tableloc = reinterpret_cast<uint8_t *>(table);
+ if (startptr_ <= tableloc) {
+ // Check if insertion point is between the table and a vtable that
+ // precedes it. This can't happen in current construction code, but check
+ // just in case we ever change the way flatbuffers are built.
+ Straddle<soffset_t, -1>(vtable, table, table);
+ } else {
+ // Check each field.
+ auto fielddefs = objectdef.fields();
+ for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
+ auto &fielddef = **it;
+ auto base_type = fielddef.type()->base_type();
+ // Ignore scalars.
+ if (base_type <= reflection::Double) continue;
+ // Ignore fields that are not stored.
+ auto offset = table->GetOptionalFieldOffset(fielddef.offset());
+ if (!offset) continue;
+ // Ignore structs.
+ auto subobjectdef =
+ base_type == reflection::Obj
+ ? schema_.objects()->Get(fielddef.type()->index())
+ : nullptr;
+ if (subobjectdef && subobjectdef->is_struct()) continue;
+ // Get this fields' offset, and read it if safe.
+ auto offsetloc = tableloc + offset;
+ if (DagCheck(offsetloc)) continue; // This offset already visited.
+ auto ref = offsetloc + ReadScalar<uoffset_t>(offsetloc);
+ Straddle<uoffset_t, 1>(offsetloc, ref, offsetloc);
+ // Recurse.
+ switch (base_type) {
+ case reflection::Obj: {
+ ResizeTable(*subobjectdef, reinterpret_cast<Table *>(ref));
+ break;
+ }
+ case reflection::Vector: {
+ auto elem_type = fielddef.type()->element();
+ if (elem_type != reflection::Obj && elem_type != reflection::String)
+ break;
+ auto vec = reinterpret_cast<Vector<uoffset_t> *>(ref);
+ auto elemobjectdef =
+ elem_type == reflection::Obj
+ ? schema_.objects()->Get(fielddef.type()->index())
+ : nullptr;
+ if (elemobjectdef && elemobjectdef->is_struct()) break;
+ for (uoffset_t i = 0; i < vec->size(); i++) {
+ auto loc = vec->Data() + i * sizeof(uoffset_t);
+ if (DagCheck(loc)) continue; // This offset already visited.
+ auto dest = loc + vec->Get(i);
+ Straddle<uoffset_t, 1>(loc, dest, loc);
+ if (elemobjectdef)
+ ResizeTable(*elemobjectdef, reinterpret_cast<Table *>(dest));
+ }
+ break;
+ }
+ case reflection::Union: {
+ ResizeTable(GetUnionType(schema_, objectdef, fielddef, *table),
+ reinterpret_cast<Table *>(ref));
+ break;
+ }
+ case reflection::String: break;
+ default: FLATBUFFERS_ASSERT(false);
+ }
+ }
+ // Check if the vtable offset points beyond the insertion point.
+ // Must do this last, since GetOptionalFieldOffset above still reads
+ // this value.
+ Straddle<soffset_t, -1>(table, vtable, table);
+ }
+ }
+
+ private:
+ const reflection::Schema &schema_;
+ uint8_t *startptr_;
+ int delta_;
+ std::vector<uint8_t> &buf_;
+ std::vector<uint8_t> dag_check_;
+};
+
+void SetString(const reflection::Schema &schema, const std::string &val,
+ const String *str, std::vector<uint8_t> *flatbuf,
+ const reflection::Object *root_table) {
+ auto delta = static_cast<int>(val.size()) - static_cast<int>(str->size());
+ auto str_start = static_cast<uoffset_t>(
+ reinterpret_cast<const uint8_t *>(str) - vector_data(*flatbuf));
+ auto start = str_start + static_cast<uoffset_t>(sizeof(uoffset_t));
+ if (delta) {
+ // Clear the old string, since we don't want parts of it remaining.
+ memset(vector_data(*flatbuf) + start, 0, str->size());
+ // Different size, we must expand (or contract).
+ ResizeContext(schema, start, delta, flatbuf, root_table);
+ // Set the new length.
+ WriteScalar(vector_data(*flatbuf) + str_start,
+ static_cast<uoffset_t>(val.size()));
+ }
+ // Copy new data. Safe because we created the right amount of space.
+ memcpy(vector_data(*flatbuf) + start, val.c_str(), val.size() + 1);
+}
+
+uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
+ const VectorOfAny *vec, uoffset_t num_elems,
+ uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
+ const reflection::Object *root_table) {
+ auto delta_elem = static_cast<int>(newsize) - static_cast<int>(num_elems);
+ auto delta_bytes = delta_elem * static_cast<int>(elem_size);
+ auto vec_start =
+ reinterpret_cast<const uint8_t *>(vec) - vector_data(*flatbuf);
+ auto start = static_cast<uoffset_t>(vec_start + sizeof(uoffset_t) +
+ elem_size * num_elems);
+ if (delta_bytes) {
+ if (delta_elem < 0) {
+ // Clear elements we're throwing away, since some might remain in the
+ // buffer.
+ auto size_clear = -delta_elem * elem_size;
+ memset(vector_data(*flatbuf) + start - size_clear, 0, size_clear);
+ }
+ ResizeContext(schema, start, delta_bytes, flatbuf, root_table);
+ WriteScalar(vector_data(*flatbuf) + vec_start, newsize); // Length field.
+ // Set new elements to 0.. this can be overwritten by the caller.
+ if (delta_elem > 0) {
+ memset(vector_data(*flatbuf) + start, 0, delta_elem * elem_size);
+ }
+ }
+ return vector_data(*flatbuf) + start;
+}
+
+const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
+ const uint8_t *newbuf, size_t newlen) {
+ // Align to sizeof(uoffset_t) past sizeof(largest_scalar_t) since we're
+ // going to chop off the root offset.
+ while ((flatbuf.size() & (sizeof(uoffset_t) - 1)) ||
+ !(flatbuf.size() & (sizeof(largest_scalar_t) - 1))) {
+ flatbuf.push_back(0);
+ }
+ auto insertion_point = static_cast<uoffset_t>(flatbuf.size());
+ // Insert the entire FlatBuffer minus the root pointer.
+ flatbuf.insert(flatbuf.end(), newbuf + sizeof(uoffset_t), newbuf + newlen);
+ auto root_offset = ReadScalar<uoffset_t>(newbuf) - sizeof(uoffset_t);
+ return vector_data(flatbuf) + insertion_point + root_offset;
+}
+
+void CopyInline(FlatBufferBuilder &fbb, const reflection::Field &fielddef,
+ const Table &table, size_t align, size_t size) {
+ fbb.Align(align);
+ fbb.PushBytes(table.GetStruct<const uint8_t *>(fielddef.offset()), size);
+ fbb.TrackField(fielddef.offset(), fbb.GetSize());
+}
+
+Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
+ const reflection::Schema &schema,
+ const reflection::Object &objectdef,
+ const Table &table, bool use_string_pooling) {
+ // Before we can construct the table, we have to first generate any
+ // subobjects, and collect their offsets.
+ std::vector<uoffset_t> offsets;
+ auto fielddefs = objectdef.fields();
+ for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
+ auto &fielddef = **it;
+ // Skip if field is not present in the source.
+ if (!table.CheckField(fielddef.offset())) continue;
+ uoffset_t offset = 0;
+ switch (fielddef.type()->base_type()) {
+ case reflection::String: {
+ offset = use_string_pooling
+ ? fbb.CreateSharedString(GetFieldS(table, fielddef)).o
+ : fbb.CreateString(GetFieldS(table, fielddef)).o;
+ break;
+ }
+ case reflection::Obj: {
+ auto &subobjectdef = *schema.objects()->Get(fielddef.type()->index());
+ if (!subobjectdef.is_struct()) {
+ offset = CopyTable(fbb, schema, subobjectdef,
+ *GetFieldT(table, fielddef), use_string_pooling)
+ .o;
+ }
+ break;
+ }
+ case reflection::Union: {
+ auto &subobjectdef = GetUnionType(schema, objectdef, fielddef, table);
+ offset = CopyTable(fbb, schema, subobjectdef,
+ *GetFieldT(table, fielddef), use_string_pooling)
+ .o;
+ break;
+ }
+ case reflection::Vector: {
+ auto vec =
+ table.GetPointer<const Vector<Offset<Table>> *>(fielddef.offset());
+ auto element_base_type = fielddef.type()->element();
+ auto elemobjectdef =
+ element_base_type == reflection::Obj
+ ? schema.objects()->Get(fielddef.type()->index())
+ : nullptr;
+ switch (element_base_type) {
+ case reflection::String: {
+ std::vector<Offset<const String *>> elements(vec->size());
+ auto vec_s = reinterpret_cast<const Vector<Offset<String>> *>(vec);
+ for (uoffset_t i = 0; i < vec_s->size(); i++) {
+ elements[i] = use_string_pooling
+ ? fbb.CreateSharedString(vec_s->Get(i)).o
+ : fbb.CreateString(vec_s->Get(i)).o;
+ }
+ offset = fbb.CreateVector(elements).o;
+ break;
+ }
+ case reflection::Obj: {
+ if (!elemobjectdef->is_struct()) {
+ std::vector<Offset<const Table *>> elements(vec->size());
+ for (uoffset_t i = 0; i < vec->size(); i++) {
+ elements[i] = CopyTable(fbb, schema, *elemobjectdef,
+ *vec->Get(i), use_string_pooling);
+ }
+ offset = fbb.CreateVector(elements).o;
+ break;
+ }
+ }
+ FLATBUFFERS_FALLTHROUGH(); // fall thru
+ default: { // Scalars and structs.
+ auto element_size = GetTypeSize(element_base_type);
+ if (elemobjectdef && elemobjectdef->is_struct())
+ element_size = elemobjectdef->bytesize();
+ fbb.StartVector(vec->size(), element_size);
+ fbb.PushBytes(vec->Data(), element_size * vec->size());
+ offset = fbb.EndVector(vec->size());
+ break;
+ }
+ }
+ break;
+ }
+ default: // Scalars.
+ break;
+ }
+ if (offset) { offsets.push_back(offset); }
+ }
+ // Now we can build the actual table from either offsets or scalar data.
+ auto start = objectdef.is_struct() ? fbb.StartStruct(objectdef.minalign())
+ : fbb.StartTable();
+ size_t offset_idx = 0;
+ for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
+ auto &fielddef = **it;
+ if (!table.CheckField(fielddef.offset())) continue;
+ auto base_type = fielddef.type()->base_type();
+ switch (base_type) {
+ case reflection::Obj: {
+ auto &subobjectdef = *schema.objects()->Get(fielddef.type()->index());
+ if (subobjectdef.is_struct()) {
+ CopyInline(fbb, fielddef, table, subobjectdef.minalign(),
+ subobjectdef.bytesize());
+ break;
+ }
+ }
+ FLATBUFFERS_FALLTHROUGH(); // fall thru
+ case reflection::Union:
+ case reflection::String:
+ case reflection::Vector:
+ fbb.AddOffset(fielddef.offset(), Offset<void>(offsets[offset_idx++]));
+ break;
+ default: { // Scalars.
+ auto size = GetTypeSize(base_type);
+ CopyInline(fbb, fielddef, table, size, size);
+ break;
+ }
+ }
+ }
+ FLATBUFFERS_ASSERT(offset_idx == offsets.size());
+ if (objectdef.is_struct()) {
+ fbb.ClearOffsets();
+ return fbb.EndStruct();
+ } else {
+ return fbb.EndTable(start);
+ }
+}
+
+bool VerifyStruct(flatbuffers::Verifier &v,
+ const flatbuffers::Table &parent_table,
+ voffset_t field_offset, const reflection::Object &obj,
+ bool required) {
+ auto offset = parent_table.GetOptionalFieldOffset(field_offset);
+ if (required && !offset) { return false; }
+
+ return !offset || v.Verify(reinterpret_cast<const uint8_t *>(&parent_table),
+ offset, obj.bytesize());
+}
+
+bool VerifyVectorOfStructs(flatbuffers::Verifier &v,
+ const flatbuffers::Table &parent_table,
+ voffset_t field_offset,
+ const reflection::Object &obj, bool required) {
+ auto p = parent_table.GetPointer<const uint8_t *>(field_offset);
+ if (required && !p) { return false; }
+
+ return !p || v.VerifyVectorOrString(p, obj.bytesize());
+}
+
+// forward declare to resolve cyclic deps between VerifyObject and VerifyVector
+bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
+ const reflection::Object &obj,
+ const flatbuffers::Table *table, bool required);
+
+bool VerifyUnion(flatbuffers::Verifier &v, const reflection::Schema &schema,
+ uint8_t utype, const uint8_t *elem,
+ const reflection::Field &union_field) {
+ if (!utype) return true; // Not present.
+ auto fb_enum = schema.enums()->Get(union_field.type()->index());
+ if (utype >= fb_enum->values()->size()) return false;
+ auto elem_type = fb_enum->values()->Get(utype)->union_type();
+ switch (elem_type->base_type()) {
+ case reflection::Obj: {
+ auto elem_obj = schema.objects()->Get(elem_type->index());
+ if (elem_obj->is_struct()) {
+ return v.VerifyFromPointer(elem, elem_obj->bytesize());
+ } else {
+ return VerifyObject(v, schema, *elem_obj,
+ reinterpret_cast<const flatbuffers::Table *>(elem),
+ true);
+ }
+ }
+ case reflection::String:
+ return v.VerifyString(
+ reinterpret_cast<const flatbuffers::String *>(elem));
+ default: return false;
+ }
+}
+
+bool VerifyVector(flatbuffers::Verifier &v, const reflection::Schema &schema,
+ const flatbuffers::Table &table,
+ const reflection::Field &vec_field) {
+ FLATBUFFERS_ASSERT(vec_field.type()->base_type() == reflection::Vector);
+ if (!table.VerifyField<uoffset_t>(v, vec_field.offset())) return false;
+
+ switch (vec_field.type()->element()) {
+ case reflection::UType:
+ return v.VerifyVector(flatbuffers::GetFieldV<uint8_t>(table, vec_field));
+ case reflection::Bool:
+ case reflection::Byte:
+ case reflection::UByte:
+ return v.VerifyVector(flatbuffers::GetFieldV<int8_t>(table, vec_field));
+ case reflection::Short:
+ case reflection::UShort:
+ return v.VerifyVector(flatbuffers::GetFieldV<int16_t>(table, vec_field));
+ case reflection::Int:
+ case reflection::UInt:
+ return v.VerifyVector(flatbuffers::GetFieldV<int32_t>(table, vec_field));
+ case reflection::Long:
+ case reflection::ULong:
+ return v.VerifyVector(flatbuffers::GetFieldV<int64_t>(table, vec_field));
+ case reflection::Float:
+ return v.VerifyVector(flatbuffers::GetFieldV<float>(table, vec_field));
+ case reflection::Double:
+ return v.VerifyVector(flatbuffers::GetFieldV<double>(table, vec_field));
+ case reflection::String: {
+ auto vec_string =
+ flatbuffers::GetFieldV<flatbuffers::Offset<flatbuffers::String>>(
+ table, vec_field);
+ if (v.VerifyVector(vec_string) && v.VerifyVectorOfStrings(vec_string)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ case reflection::Obj: {
+ auto obj = schema.objects()->Get(vec_field.type()->index());
+ if (obj->is_struct()) {
+ return VerifyVectorOfStructs(v, table, vec_field.offset(), *obj,
+ vec_field.required());
+ } else {
+ auto vec =
+ flatbuffers::GetFieldV<flatbuffers::Offset<flatbuffers::Table>>(
+ table, vec_field);
+ if (!v.VerifyVector(vec)) return false;
+ if (!vec) return true;
+ for (uoffset_t j = 0; j < vec->size(); j++) {
+ if (!VerifyObject(v, schema, *obj, vec->Get(j), true)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ case reflection::Union: {
+ auto vec = flatbuffers::GetFieldV<flatbuffers::Offset<uint8_t>>(
+ table, vec_field);
+ if (!v.VerifyVector(vec)) return false;
+ if (!vec) return true;
+ auto type_vec = table.GetPointer<Vector<uint8_t> *>(vec_field.offset() -
+ sizeof(voffset_t));
+ if (!v.VerifyVector(type_vec)) return false;
+ for (uoffset_t j = 0; j < vec->size(); j++) {
+ // get union type from the prev field
+ auto utype = type_vec->Get(j);
+ auto elem = vec->Get(j);
+ if (!VerifyUnion(v, schema, utype, elem, vec_field)) return false;
+ }
+ return true;
+ }
+ case reflection::Vector:
+ case reflection::None:
+ default: FLATBUFFERS_ASSERT(false); return false;
+ }
+}
+
+bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema,
+ const reflection::Object &obj,
+ const flatbuffers::Table *table, bool required) {
+ if (!table) return !required;
+ if (!table->VerifyTableStart(v)) return false;
+ for (uoffset_t i = 0; i < obj.fields()->size(); i++) {
+ auto field_def = obj.fields()->Get(i);
+ switch (field_def->type()->base_type()) {
+ case reflection::None: FLATBUFFERS_ASSERT(false); break;
+ case reflection::UType:
+ if (!table->VerifyField<uint8_t>(v, field_def->offset())) return false;
+ break;
+ case reflection::Bool:
+ case reflection::Byte:
+ case reflection::UByte:
+ if (!table->VerifyField<int8_t>(v, field_def->offset())) return false;
+ break;
+ case reflection::Short:
+ case reflection::UShort:
+ if (!table->VerifyField<int16_t>(v, field_def->offset())) return false;
+ break;
+ case reflection::Int:
+ case reflection::UInt:
+ if (!table->VerifyField<int32_t>(v, field_def->offset())) return false;
+ break;
+ case reflection::Long:
+ case reflection::ULong:
+ if (!table->VerifyField<int64_t>(v, field_def->offset())) return false;
+ break;
+ case reflection::Float:
+ if (!table->VerifyField<float>(v, field_def->offset())) return false;
+ break;
+ case reflection::Double:
+ if (!table->VerifyField<double>(v, field_def->offset())) return false;
+ break;
+ case reflection::String:
+ if (!table->VerifyField<uoffset_t>(v, field_def->offset()) ||
+ !v.VerifyString(flatbuffers::GetFieldS(*table, *field_def))) {
+ return false;
+ }
+ break;
+ case reflection::Vector:
+ if (!VerifyVector(v, schema, *table, *field_def)) return false;
+ break;
+ case reflection::Obj: {
+ auto child_obj = schema.objects()->Get(field_def->type()->index());
+ if (child_obj->is_struct()) {
+ if (!VerifyStruct(v, *table, field_def->offset(), *child_obj,
+ field_def->required())) {
+ return false;
+ }
+ } else {
+ if (!VerifyObject(v, schema, *child_obj,
+ flatbuffers::GetFieldT(*table, *field_def),
+ field_def->required())) {
+ return false;
+ }
+ }
+ break;
+ }
+ case reflection::Union: {
+ // get union type from the prev field
+ voffset_t utype_offset = field_def->offset() - sizeof(voffset_t);
+ auto utype = table->GetField<uint8_t>(utype_offset, 0);
+ auto uval = reinterpret_cast<const uint8_t *>(
+ flatbuffers::GetFieldT(*table, *field_def));
+ if (!VerifyUnion(v, schema, utype, uval, *field_def)) { return false; }
+ break;
+ }
+ default: FLATBUFFERS_ASSERT(false); break;
+ }
+ }
+
+ if (!v.EndTable()) return false;
+
+ return true;
+}
+
+bool Verify(const reflection::Schema &schema, const reflection::Object &root,
+ const uint8_t *buf, size_t length, uoffset_t max_depth /*= 64*/,
+ uoffset_t max_tables /*= 1000000*/) {
+ Verifier v(buf, length, max_depth, max_tables);
+ return VerifyObject(v, schema, root, flatbuffers::GetAnyRoot(buf), true);
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/src/util.cpp b/contrib/libs/flatbuffers/src/util.cpp
new file mode 100644
index 0000000000..3670a01939
--- /dev/null
+++ b/contrib/libs/flatbuffers/src/util.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2016 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.
+ */
+
+// clang-format off
+// Dont't remove `format off`, it prevent reordering of win-includes.
+
+#if defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__) || \
+ defined(__QNXNTO__)
+# define _POSIX_C_SOURCE 200809L
+# define _XOPEN_SOURCE 700L
+#endif
+
+#ifdef _WIN32
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# ifndef NOMINMAX
+# define NOMINMAX
+# endif
+# ifdef _MSC_VER
+# include <crtdbg.h>
+# endif
+# include <windows.h> // Must be included before <direct.h>
+# include <direct.h>
+# include <winbase.h>
+# undef interface // This is also important because of reasons
+#endif
+// clang-format on
+
+#include "flatbuffers/base.h"
+#include "flatbuffers/util.h"
+
+#include <sys/stat.h>
+#include <clocale>
+#include <cstdlib>
+#include <fstream>
+
+namespace flatbuffers {
+
+bool FileExistsRaw(const char *name) {
+ std::ifstream ifs(name);
+ return ifs.good();
+}
+
+bool LoadFileRaw(const char *name, bool binary, std::string *buf) {
+ if (DirExists(name)) return false;
+ std::ifstream ifs(name, binary ? std::ifstream::binary : std::ifstream::in);
+ if (!ifs.is_open()) return false;
+ if (binary) {
+ // The fastest way to read a file into a string.
+ ifs.seekg(0, std::ios::end);
+ auto size = ifs.tellg();
+ (*buf).resize(static_cast<size_t>(size));
+ ifs.seekg(0, std::ios::beg);
+ ifs.read(&(*buf)[0], (*buf).size());
+ } else {
+ // This is slower, but works correctly on all platforms for text files.
+ std::ostringstream oss;
+ oss << ifs.rdbuf();
+ *buf = oss.str();
+ }
+ return !ifs.bad();
+}
+
+static LoadFileFunction g_load_file_function = LoadFileRaw;
+static FileExistsFunction g_file_exists_function = FileExistsRaw;
+
+bool LoadFile(const char *name, bool binary, std::string *buf) {
+ FLATBUFFERS_ASSERT(g_load_file_function);
+ return g_load_file_function(name, binary, buf);
+}
+
+bool FileExists(const char *name) {
+ FLATBUFFERS_ASSERT(g_file_exists_function);
+ return g_file_exists_function(name);
+}
+
+bool DirExists(const char *name) {
+ // clang-format off
+
+ #ifdef _WIN32
+ #define flatbuffers_stat _stat
+ #define FLATBUFFERS_S_IFDIR _S_IFDIR
+ #else
+ #define flatbuffers_stat stat
+ #define FLATBUFFERS_S_IFDIR S_IFDIR
+ #endif
+ // clang-format on
+ struct flatbuffers_stat file_info;
+ if (flatbuffers_stat(name, &file_info) != 0) return false;
+ return (file_info.st_mode & FLATBUFFERS_S_IFDIR) != 0;
+}
+
+LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function) {
+ LoadFileFunction previous_function = g_load_file_function;
+ g_load_file_function = load_file_function ? load_file_function : LoadFileRaw;
+ return previous_function;
+}
+
+FileExistsFunction SetFileExistsFunction(
+ FileExistsFunction file_exists_function) {
+ FileExistsFunction previous_function = g_file_exists_function;
+ g_file_exists_function =
+ file_exists_function ? file_exists_function : FileExistsRaw;
+ return previous_function;
+}
+
+bool SaveFile(const char *name, const char *buf, size_t len, bool binary) {
+ std::ofstream ofs(name, binary ? std::ofstream::binary : std::ofstream::out);
+ if (!ofs.is_open()) return false;
+ ofs.write(buf, len);
+ return !ofs.bad();
+}
+
+// We internally store paths in posix format ('/'). Paths supplied
+// by the user should go through PosixPath to ensure correct behavior
+// on Windows when paths are string-compared.
+
+static const char kPathSeparatorWindows = '\\';
+static const char *PathSeparatorSet = "\\/"; // Intentionally no ':'
+
+std::string StripExtension(const std::string &filepath) {
+ size_t i = filepath.find_last_of('.');
+ return i != std::string::npos ? filepath.substr(0, i) : filepath;
+}
+
+std::string GetExtension(const std::string &filepath) {
+ size_t i = filepath.find_last_of('.');
+ return i != std::string::npos ? filepath.substr(i + 1) : "";
+}
+
+std::string StripPath(const std::string &filepath) {
+ size_t i = filepath.find_last_of(PathSeparatorSet);
+ return i != std::string::npos ? filepath.substr(i + 1) : filepath;
+}
+
+std::string StripFileName(const std::string &filepath) {
+ size_t i = filepath.find_last_of(PathSeparatorSet);
+ return i != std::string::npos ? filepath.substr(0, i) : "";
+}
+
+std::string ConCatPathFileName(const std::string &path,
+ const std::string &filename) {
+ std::string filepath = path;
+ if (filepath.length()) {
+ char &filepath_last_character = string_back(filepath);
+ if (filepath_last_character == kPathSeparatorWindows) {
+ filepath_last_character = kPathSeparator;
+ } else if (filepath_last_character != kPathSeparator) {
+ filepath += kPathSeparator;
+ }
+ }
+ filepath += filename;
+ // Ignore './' at the start of filepath.
+ if (filepath[0] == '.' && filepath[1] == kPathSeparator) {
+ filepath.erase(0, 2);
+ }
+ return filepath;
+}
+
+std::string PosixPath(const char *path) {
+ std::string p = path;
+ std::replace(p.begin(), p.end(), '\\', '/');
+ return p;
+}
+
+void EnsureDirExists(const std::string &filepath) {
+ auto parent = StripFileName(filepath);
+ if (parent.length()) EnsureDirExists(parent);
+ // clang-format off
+
+ #ifdef _WIN32
+ (void)_mkdir(filepath.c_str());
+ #else
+ mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
+ #endif
+ // clang-format on
+}
+
+std::string AbsolutePath(const std::string &filepath) {
+ // clang-format off
+
+ #ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
+ return filepath;
+ #else
+ #ifdef _WIN32
+ char abs_path[MAX_PATH];
+ return GetFullPathNameA(filepath.c_str(), MAX_PATH, abs_path, nullptr)
+ #else
+ char *abs_path_temp = realpath(filepath.c_str(), nullptr);
+ bool success = abs_path_temp != nullptr;
+ std::string abs_path;
+ if(success) {
+ abs_path = abs_path_temp;
+ free(abs_path_temp);
+ }
+ return success
+ #endif
+ ? abs_path
+ : filepath;
+ #endif // FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
+ // clang-format on
+}
+
+// Locale-independent code.
+#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && \
+ (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
+
+// clang-format off
+// Allocate locale instance at startup of application.
+ClassicLocale ClassicLocale::instance_;
+
+#ifdef _MSC_VER
+ ClassicLocale::ClassicLocale()
+ : locale_(_create_locale(LC_ALL, "C")) {}
+ ClassicLocale::~ClassicLocale() { _free_locale(locale_); }
+#else
+ ClassicLocale::ClassicLocale()
+ : locale_(newlocale(LC_ALL, "C", nullptr)) {}
+ ClassicLocale::~ClassicLocale() { freelocale(locale_); }
+#endif
+// clang-format on
+
+#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
+
+std::string RemoveStringQuotes(const std::string &s) {
+ auto ch = *s.c_str();
+ return ((s.size() >= 2) && (ch == '\"' || ch == '\'') &&
+ (ch == string_back(s)))
+ ? s.substr(1, s.length() - 2)
+ : s;
+}
+
+bool SetGlobalTestLocale(const char *locale_name, std::string *_value) {
+ const auto the_locale = setlocale(LC_ALL, locale_name);
+ if (!the_locale) return false;
+ if (_value) *_value = std::string(the_locale);
+ return true;
+}
+
+bool ReadEnvironmentVariable(const char *var_name, std::string *_value) {
+#ifdef _MSC_VER
+ __pragma(warning(disable : 4996)); // _CRT_SECURE_NO_WARNINGS
+#endif
+ auto env_str = std::getenv(var_name);
+ if (!env_str) return false;
+ if (_value) *_value = std::string(env_str);
+ return true;
+}
+
+void SetupDefaultCRTReportMode() {
+ // clang-format off
+
+ #ifdef _MSC_VER
+ // By default, send all reports to STDOUT to prevent CI hangs.
+ // Enable assert report box [Abort|Retry|Ignore] if a debugger is present.
+ const int dbg_mode = (_CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG) |
+ (IsDebuggerPresent() ? _CRTDBG_MODE_WNDW : 0);
+ (void)dbg_mode; // release mode fix
+ // CrtDebug reports to _CRT_WARN channel.
+ _CrtSetReportMode(_CRT_WARN, dbg_mode);
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
+ // The assert from <assert.h> reports to _CRT_ERROR channel
+ _CrtSetReportMode(_CRT_ERROR, dbg_mode);
+ _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
+ // Internal CRT assert channel?
+ _CrtSetReportMode(_CRT_ASSERT, dbg_mode);
+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
+ #endif
+
+ // clang-format on
+}
+
+} // namespace flatbuffers
diff --git a/contrib/libs/flatbuffers/ya.make b/contrib/libs/flatbuffers/ya.make
new file mode 100644
index 0000000000..0fa3e01129
--- /dev/null
+++ b/contrib/libs/flatbuffers/ya.make
@@ -0,0 +1,40 @@
+# Generated by devtools/yamaker from nixpkgs 22.05.
+
+LIBRARY()
+
+VERSION(2.0.0)
+
+ORIGINAL_SOURCE(https://github.com/google/flatbuffers/archive/v2.0.0.tar.gz)
+
+LICENSE(
+ Apache-2.0 AND
+ BSD-3-Clause
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+ADDINCL(
+ contrib/libs/flatbuffers/include
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+CFLAGS(
+ -DFLATBUFFERS_LOCALE_INDEPENDENT=1
+)
+
+SRCS(
+ src/idl_gen_text.cpp
+ src/idl_parser.cpp
+ src/reflection.cpp
+ src/util.cpp
+)
+
+END()
+
+RECURSE(
+ flatc
+ samples
+)